В одном placeholder Grid Layout допускает несколько элементов. Как они будут подстраиваться? Или как грид их будет подстраивать? Как сказать
все элементы в этом placeholder должны иметь одинаковую ширину и эта ширина должна быть не меньше max-width самого широкого?
А вообще смыслов таблиц из одной ячейки может быть много.
Например иногда имеет смысл написать так:
pre { display:table-cell; }
тогда ширина pre будет равна самой широкой строки ибо table/cell фактически ведет себя как если бы он объявлен как width:max-content
Ну во первых by design элементы могут рисоваться поверх соседей.
А во вторых представим себе grid с такими вот columns:
grid-columns: 150px 1fr 200px;
и скажем в первой колонке оказался элемент с width:300px или min-width:300px.
Или юзер выставил шрифт поболее и content width стала больше чем 150px.
Результат будет не сильно привлекательный.
Основной недостаток(?) Grid Layout состит в том что он использует т.н. placeholder model — поверхность разбивается на placeholders — виртуальные прямоуголники в которых уже помещаются реальные элементы. Причем как-то совершенно грустно и не по CSS-овски. Скажем есть внутри элемент с width:100%. Этот width он отнсительно чего расчитывается? Про placeholder'ы CSS box model ничего не знает.
Таблицы же используют строго position:static layout. Вся поверхность конейнера заполнена реальными DOM элементами. При этом контент соседних ячеек друг на друга не залазит. Ибо каждая ячейка это BFC.
Мой flow:«template» использует table model. Собственно под капотом там table engine и используется. Т.е. layout и размеры определяются по правилам таблиц, это вот:
#container {
flow: "1 1"
"2 3";
}
Описывает таблицу в которй первый child занимает полный ряд (первую и вторую колонку) а второй и третий соответсвенно живут во втором ряду.
Размеры как я уже сказал — по принципу tables — с учетом min/max-width и пр.
Это к сожалению никак не таблицы. И воспроизвести «резиновость» таблиц не удастся.
Уникальность таблиц состоит в том что каждая ячейка это устанавливает так называемый BFC — block formatting context. Т.е. в условиях overflow:visible сродержимое ячеек друг на друга «не залазит». Здесь же — легко.
Стоит бы отметить что grid layout это не position:static размещение, а вариация position:absolute|fixed.
Собственно grid layout можно воспрозвести руками и сейчас задав position:fixed всем элементам. Управляя left/top/right/bottom можно воспроизвести start/end/stretch позиционирование. Но position:fixed хотя бы можно управлять z-index.
D есть метрика глубины самого DOM и используемых descendant selectors.
Если система стилей не использует descendant selectors, а имеет только два правила (S=2): #id {color:red}
.cls {color:blue}
то D в этом случае равно 1. Системе не требутеся просматривать parent chain на предмет ответа уволетворяет ли селектор или нет.
Если же мы имеем набор правил вида .super #id {color:red}
.super .cls {color:blue}
то для проверки таких селекторов нам нужно просмотреть весь parent chain каждого элемента. В худшем случае на полную глубину вплоть до root (html) элемента включительно. В этом случае метрика D есть средняя глубина элементов в DOM.
Т.е. метрика D не точная — зависит от конфигурации дерева.
Для определения полной картины нужно пройтись по всем N=10 элементам и последовательно проверить оба селектора (S=2).
Итого строго по формуле O(N*S*D) -> 10*2*1 = 20 операций проверки селекторов.
N2 с точки зрения computational complexity theory есть точная оценка сложности :has(...) селектора.
Представим себе такой документ:
<div>
<div>
<div>
<a>...</a>
</div>
</div>
</div>
и правило
div:has(a) { color:red }
Количество элементов внутри root элемента здесь N=3
Назначаем стили:
Для первого DIV (root) элемента требуется просмотр n=3 детей (пока найдем <a>).
Для второго DIV элемента n=2
Для третьего n=1
Итого 6 просмотров, что для данного случая N * (N + 1) / 2
Что и есть O(N2) сложность с точки зрения теории.
Индекс по ID нужен для эффективного исполнения функции getElementByID().
Если же у тебя есть, скажем, такие CSS правила
body.mode1 #one { color:red }
body.mode2 #one { color:green }
body.mode1 a { color:blue }
body.mode2 a { color:orange }
и ты меняешь класс у body c mode1 на mode2 то ты просто обязан пересчитать все стили внутри body. При этом есть у элемента ID или нет — не важно абсолютно.
Для того чтобы проверить элемент body на предмет соответствия body:has(a.cool) селектору нужно просмотреть все N-1 его детей. Т.е. не просто сам элемент и его D parents, а еще и детей.
Т.е. в общем случае сложность выражается как O(N*S*D*N) -> O(N2).
Ну во первых никто не гарантирует что элемент с данным id он один. Уникальность id это рекомендация. Не более.
С точки зрения CSS id это такой же атрибут как и любой другой. Просто #id селектор имеет больший вес. Все CSS имплементации раcсчитанны на «неуникальность» ID.
Про скорость. Представь себе документ в начальном состоянии. Расчет стилей в этом случае это все те же O(N*S*D). id никак не помогают.
Есть набор из S правил (selector/properties). Этот набор сортируется по selector specificity.
И для каждого DOM элемента n просматриваются все S правил в указаном порядке.
Для составных селекторов сначала проверяется самый правый селектор и далее справа налево по цепочке parents.
С точки зрения CPU эти вот два селектора:
td { color:red }
#id { color:red }
имеют одинаковую сложность (у меня это сравнение двух int).
А селектор: .cls1 { color:red }
несколько более сложен для определения(у меня это — поиск int в массиве int)
Именно так selector complexity и выражается если следовать спецификации.
По поводу оптимизаций… да они могут уменьшить нагрузку в некоторых случаях.
Скажем есть эвристика которая неким магическим образом исключает из просмотра половину style rules т.е.
можно записать O( N * (S*0.5) * D ) что c точки зрения теории равно всё тем же O( N * S * D ). Если есть сомнения то вот en.wikipedia.org/wiki/Big_O_notation
Собственно это проблема и есть основная причина по которой в CSS никогда не будет селекторов типа:
body:has(a.cool) { color:red }
Ибо в таком случае (has-something-inside selectors) сложность скачком возрастает до квадратичной — O(N2). Это вообще убьет Web.
В одном placeholder Grid Layout допускает несколько элементов. Как они будут подстраиваться? Или как грид их будет подстраивать? Как сказать
все элементы в этом placeholder должны иметь одинаковую ширину и эта ширина должна быть не меньше max-width самого широкого?
А вообще смыслов таблиц из одной ячейки может быть много.
Например иногда имеет смысл написать так:
тогда ширина pre будет равна самой широкой строки ибо table/cell фактически ведет себя как если бы он объявлен как
width:max-content
И у него пара-тройка children. Под какой контент и как оно будет подстраиваться?
А во вторых представим себе grid с такими вот columns:
grid-columns: 150px 1fr 200px;
и скажем в первой колонке оказался элемент с width:300px или min-width:300px.
Или юзер выставил шрифт поболее и content width стала больше чем 150px.
Результат будет не сильно привлекательный.
Основной недостаток(?) Grid Layout состит в том что он использует т.н. placeholder model — поверхность разбивается на placeholders — виртуальные прямоуголники в которых уже помещаются реальные элементы. Причем как-то совершенно грустно и не по CSS-овски. Скажем есть внутри элемент с width:100%. Этот width он отнсительно чего расчитывается? Про placeholder'ы CSS box model ничего не знает.
Таблицы же используют строго position:static layout. Вся поверхность конейнера заполнена реальными DOM элементами. При этом контент соседних ячеек друг на друга не залазит. Ибо каждая ячейка это BFC.
Мой flow:«template» использует table model. Собственно под капотом там table engine и используется. Т.е. layout и размеры определяются по правилам таблиц, это вот:
}
Описывает таблицу в которй первый child занимает полный ряд (первую и вторую колонку) а второй и третий соответсвенно живут во втором ряду.
Размеры как я уже сказал — по принципу tables — с учетом min/max-width и пр.
Уникальность таблиц состоит в том что каждая ячейка это устанавливает так называемый BFC — block formatting context. Т.е. в условиях overflow:visible сродержимое ячеек друг на друга «не залазит». Здесь же — легко.
Собственно grid layout можно воспрозвести руками и сейчас задав position:fixed всем элементам. Управляя left/top/right/bottom можно воспроизвести start/end/stretch позиционирование. Но position:fixed хотя бы можно управлять z-index.
Если система стилей не использует descendant selectors, а имеет только два правила (S=2):
#id {color:red}
.cls {color:blue}
то D в этом случае равно 1. Системе не требутеся просматривать parent chain на предмет ответа уволетворяет ли селектор или нет.
Если же мы имеем набор правил вида
.super #id {color:red}
.super .cls {color:blue}
то для проверки таких селекторов нам нужно просмотреть весь parent chain каждого элемента. В худшем случае на полную глубину вплоть до root (html) элемента включительно. В этом случае метрика D есть средняя глубина элементов в DOM.
Т.е. метрика D не точная — зависит от конфигурации дерева.
И набор правил
Для определения полной картины нужно пройтись по всем N=10 элементам и последовательно проверить оба селектора (S=2).
Итого строго по формуле O(N*S*D) -> 10*2*1 = 20 операций проверки селекторов.
Никакие индексы тут не помогут.
Представим себе такой документ:
и правило
Количество элементов внутри root элемента здесь N=3
Назначаем стили:
Для первого DIV (root) элемента требуется просмотр n=3 детей (пока найдем <a>).
Для второго DIV элемента n=2
Для третьего n=1
Итого 6 просмотров, что для данного случая N * (N + 1) / 2
Что и есть O(N2) сложность с точки зрения теории.
getElementByID()
.Если же у тебя есть, скажем, такие CSS правила
body.mode1 #one { color:red }
body.mode2 #one { color:green }
body.mode1 a { color:blue }
body.mode2 a { color:orange }
и ты меняешь класс у body c mode1 на mode2 то ты просто обязан пересчитать все стили внутри body. При этом есть у элемента ID или нет — не важно абсолютно.
Т.е. в общем случае сложность выражается как
O(N*S*D*N)
->O(N2)
.С точки зрения CSS id это такой же атрибут как и любой другой. Просто #id селектор имеет больший вес. Все CSS имплементации раcсчитанны на «неуникальность» ID.
Про скорость. Представь себе документ в начальном состоянии. Расчет стилей в этом случае это все те же O(N*S*D). id никак не помогают.
td { color:red }
и#id { color:red }
имеют в принципе одну и ту же сложность. Если представить что DOM элемент внутри выглядит как-то так:(symbol_t это int) то сравнение с id и сравнение с tag идентично.
Честно говоря не знаю откуда эта «мулечка» про "#id < .class < tag" появилась.
А наоборот это как? Что имеется ввиду?
Если FAILED то это значит что Safari пытается использовать некую оптимизацию которая ломает селекторы.
Есть набор из S правил (selector/properties). Этот набор сортируется по selector specificity.
И для каждого DOM элемента n просматриваются все S правил в указаном порядке.
Для составных селекторов сначала проверяется самый правый селектор и далее справа налево по цепочке parents.
С точки зрения CPU эти вот два селектора:
td { color:red }
#id { color:red }
имеют одинаковую сложность (у меня это сравнение двух int).
А селектор:
.cls1 { color:red }
несколько более сложен для определения(у меня это — поиск int в массиве int)
Именно так selector complexity и выражается если следовать спецификации.
По поводу оптимизаций… да они могут уменьшить нагрузку в некоторых случаях.
Скажем есть эвристика которая неким магическим образом исключает из просмотра половину style rules т.е.
можно записать
O( N * (S*0.5) * D )
что c точки зрения теории равно всё тем жеO( N * S * D )
. Если есть сомнения то вот en.wikipedia.org/wiki/Big_O_notationСобственно это проблема и есть основная причина по которой в CSS никогда не будет селекторов типа:
body:has(a.cool) { color:red }
Ибо в таком случае (has-something-inside selectors) сложность скачком возрастает до квадратичной — O(N2). Это вообще убьет Web.