CSS-live.ru

«Блочных и строчных элементов» в HTML больше нет

Для тех, кому лень читать всю статью: в современном HTML нет «блочных» и «строчных» элементов. Это деление — историческая ошибка, условность и анахронизм времен конца 90-х. Что во что можно вкладывать, а что нет, определяется не тем, как элементы выглядят, а тем, что они делают. А «блочностью», «инлайновостью», любыми их комбинациями и др. чисто внешними чертами заведует только CSS.

Остальное — для тех, кто до сих пор не верит или просто желает разобраться до конца.

Немало мифов ходит о «блочных» и «строчных» элементах. Даже верстальщики с опытом больше года порой верят в то, что «блочные элементы нельзя вкладывать в строчные, но можно в другие блочные» или что «с помощью CSS можно превратить одни в другие и наоборот». Некоторые, больше того, рассуждают о «блочных и строчных тегах». Как тут не запутаться новичку?

Так вот, на наш век выпала большая радость: «блочных» и «строчных» элементов в HTML больше нет. Теперь и формально. Актуальная спецификация HTML (она же «HTML5») классифицирует элементы HTML исключительно по их логической роли, по их смыслу.

Чтобы убедиться, что так и должно было быть, предлагаю немного оглянуться назад (в историю), в сторону (смежные технологии) и просто в объективную реальность.

Взгляд в прошлое

Откуда вообще пошли эти «блочные» и «строчные»? В самой первой версии HTML (1992) их не было. В первой версии, более-менее похожей на стандарт (HTML 2.0, 1995) появляются «Block structuring elements» (абзацы, списки, листинги кода и т.п.) и «Phrase elements» (выделения в тексте идиоматических выражений, ссылок и т.п.), различия между ними сугубо семантические (характерно, что заголовки стоят особняком от этого деления, причем «блочным структурным элементам» явно запрещается содержать заголовки!). Так что нынешние «фразовый» и «потоковый» контент — не что-то новое, а скорее «возврат к истокам».

В HTML 3.2, утвержденном в начале 1997 г. — уже после первых «столкновений» в «браузерной войне» Нетскейпа с IE — деление элементов на блочные и текстовые (!) стало более явным:

Большинство элементов, которые могут находиться в теле документа, попадают в одну из двух групп: элементы уровня блока, которые вызывают разрыв абзаца, и элементы уровня текста, которые этого не делают. Основные элементы уровня блока включают H1H6 (заголовки), P (абзацы) LI (пункты списка) и HR (горизонтальные черты). Основные элементы уровня текста включают EM, I, B и FONT (акцент на символах), A (гипертекстовые ссылки), IMG и APPLET (внедрение объектов) и BR (разрыв строки). Заметьте, что блочные элементы обычно выступают как контейнеры для элементов уровня текста и других элементов уровня блока (исключая заголовки и элемент address), тогда как элементы уровня текста могут содержать лишь другие элементы уровня текста. Точная модель зависит от конкретного элемента.

Как видно, наплыв презентационного (оформительского) подхода к разметке дал свои плоды: одним из критериев классификации стало то, вызывает ли элемент «разрыв абзаца» (и по этому критерию заголовки стали блочными). Но логика элемента, его структурная роль, пока на первом месте (причем подчеркивается, что эта роль, а значит, и возможное содержимое, у разных элементов может различаться).

В 1998 г. появляется HTML 4.0, который (в виде HTML 4.01 — результата мелких правок в 1999-м, и XHTML 1.0 — результата перевода той же семантики на др. синтаксис в 2000-м) становится де-факто единственным языком веб-разметки на целое десятилетие с лишком. Именно он принес то деление элементов на блочные и «инлайновые» (вместе с самим этим термином), к которому мы привыкли. С этого момента критериев такого деления три (они же в переводе):

  1. Модель содержимого (блочные могут содержать и инлайны, и другие блоки, а инлайны — только другие инлайны, т.е. блоки — это более крупные структурные единицы);
  2. Форматирование по умолчанию (блоки начинаются с новой строки, инлайны — нет);
  3. Особенности наследования направления текста в двунаправленном письме.

Чем плоха эта классификация? Во-первых, она неполна: как минимум два элемента — INS и DEL — были «хамелеонами», попадающими то в одну, то в другую категорию в зависимости от их собственного содержимого. Во-вторых, она никак не объясняет, почему часть «блочных» элементов может содержать другие блоки (как DIV, LI и DD), а часть  — нет (как заголовки, P и DT). И главное: ее второй пункт, форматирование (пусть и по умолчанию) явно зависит от другой технологии — CSS.

Вот ведь ирония судьбы: HTML 4.0 как раз пытался вернуть разметке семантическую чистоту, избавиться от презентационных пережитков — а в самых основах породил такую путаницу между семантикой и оформлением, какая и не снилась предшественникам!

Взгляд в CSSторону

Первая спецификация CSS была утверждена в конце 1996 г. — чуть раньше HTML 4. Так что само понятие «блочных» и «инлайновых» элементов тянется именно из CSS. В нем изначально «блочными» считались элементы с display:block или list-item, которые форматируются как единый неделимый прямоугольник и занимают всё доступное пространство контейнера по горизонтали (кроме float-элементов, те особый случай), а «инлайновыми» — все остальные, которые делят место в строке с соседями и могут разрываться на несколько прямоугольников при переносе строки. Для элемента BR пришлось прописывать отдельное исключение: описать его поведение в терминах CSS1 было невозможно (в строку он не вписывался, но и блок не создавал), так что и эта классификация была неполной.

Почти одновременно с HTML4, в том же 1998-м, начал свой долгий и непростой путь CSS2, лишь к июню 2011-го дозревший до стандарта CSS2.1. Все эти годы он продолжает традицию деления визуальной модели на «блочные» и «инлайновые»… но уже не элементы, а специально придуманные штуковины — управляющие боксы (прямоугольники). Между «боксом» и элементом больше нет однозначной связи: один элемент может порождать несколько боксов, может не порождать ни одного (при display: none), и больше того — бокс может возникать сам собой, без всякого элемента (безымянные, или анонимные, боксы — об этих «мистических» незнакомцах стоит рассказать отдельно). Хотя формулировки в спецификации остались изрядно запутанными, основная суть тут достаточно проста.

Вся страница «набирается» из прямоугольников. Каждая строка текста заключается в особый виртуальный прямоугольник, охватывающий всё ее содержимое (в т.ч. картинки и т.п.) по габаритам — контейнер строки (line box). То, что встраивается внутрь этого контейнера строки — это in-line (т.е. буквально «в-строке», «внутристрочные», они же «встроенные») боксы. А контейнеры, в которые «упакованы» сами line box-ы, их «подшитые вместе стопки» — это блоки строк, блочные боксы. Эти контейнеры могут сами дополнительно «паковаться» в другие блоки, покрупнее.

Заметьте, что «line box» и «inline» («внутристрочные») боксы в CSS — не синонимы, а принципиально разные вещи!

На первый взгляд структура та же, что в HTML-документе: крупные структурные блоки, в них структурные блоки помельче, а уже в них — текст и его отдельные выделенные фрагменты. Так-то оно так, но в HTML описывается логическая структура, а в CSS — чисто визуальная. И элементы с «блочной» моделью содержимого больше не обязаны иметь блочное отображение, и наоборот. Да и сами способы отображения не ограничиваются блочностью и строчностью — есть еще таблицы, позже к ним добавятся флексбоксы и гриды…

Неспроста в HTML4 визуальный критерий «блочности» и «неблочности» уточнялся оговоркой «по умолчанию». Долгое время браузеры, действительно, были солидарны в отображении «блочных» элементов HTML 4/XHTML 1 блочными же CSS-боксами, а «инлайновых» (текстовых) элементов — инлайновыми боксами (именно такие значения были «зашиты» во встроенный браузерный CSS, который и используется для отображения страниц при отсутствии/отключении авторских стилей). Но с приходом HTML5 это стало не всегда так. Особенно явно это стало с приходом кастомных элементов (веб-компоненты) — их роль в структуре компонента может быть любой, в т.ч. и контейнером целого блока, но браузеры по умолчанию отображают их все как «инлайновые».

Так нужно ли вообще любой ценой увязывать модель содержимого и дефолтное отображение?

Взгляд в реальность

Итак, давайте запомним несколько простых фактов (и вытекающих из них правил):

  • В HTML никаких «блочных» и «строчных» элементов нет. И не нужно. От этого искусственного деления было больше путаницы, чем пользы.
  • Модель содержимого у разных HTML-элементов разная, и (как правило) явно диктуется их логическим, структурным предназначением. Не всегда она сводится к делению «блок/текст» (например, та же ссылка в HTML5 может содержать практически любые структурные элементы — но не другие ссылки). Если есть сомнение, можно ли вкладывать что-то во что-то или нет, лучше свериться со спецификацией.
  • Визуальная структура оформления, в которой есть «блочные», «строчные» и «внутристрочные» (инлайновые) боксы, относится исключительно к CSS! Не надо путать отображение и разметку созвучными терминами.

CSS действительно может изменить представление элемента до неузнаваемости, но повлиять на модель содержимого он не может. Ведь CSS применяется к элементам DOM, построенной из уже распарсенной разметки. А модель содержимого важна как раз при построении этой DOM, самому парсеру, до вступления CSS в игру.

Кстати, выражение «блочные и строчные теги» — бессмыслица вдвойне. Потому что «блочное» и «инлайновое» — это CSS, который применяется к DOM, а не к разметке. DOM может быть построена вообще не тегами в разметке, а скриптом (document.createElement и т.п.). Теги же разбирает парсер — ничего не знающий о CSS, но имеющий представление о допустимой модели содержимого. Например, о том, что внутри абзаца текста не может быть ни заголовка, ни списка. Интересно, что в вышеупомянутых первых двух версиях HTML закрывающий тег для абзаца вообще не предполагался — авторам HTML и в голову не приходило, что абзац может закончиться где-то еще, кроме начала следующего абзаца или др. блока. Тег нового абзаца рассматривался как своего рода знак пунктуации — символ «красной строки» (он же ^p или в MS Word). Лишь с приходом XML, с его обязательным явным закрытием всего, абзац начали рассматривать как контейнер (и сразу стали появляться вопросы, почему этот контейнер «не хочет» содержать то да сё).

Вообще, на мой взгляд, при работе со страницей полезно думать именно о DOM-структуре — логична она или нелогична. А не о тегах — «блочные» они или «строчные», «закрыты» ли они и т.п. Именно с DOM-структурой работают и оформление, и скрипты. А теги могут быть любыми, разрешенными спецификацией — главное, чтобы они были одинаково понятны и разработчику, и парсеру. И имели для них обоих (ну и для поисковиков, конечно) один и тот же смысл.

Актуальная спецификация, судя по всему, тоже придерживается такого взгляда.

Взгляд в будущее (вместо заключения)

Кому-то может показаться, что уход в историю деления HTML-элементов по дефолтному отображению усложнит жизнь верстальщика. Мол, раньше было простое правило «блочное в строчное не пихай», а теперь «по каждому поводу надо в спецификацию лазить». Но мы ведь только что увидели, что простота этого «правила» и раньше была обманчивой. Так что, на мой взгляд, жизнь стала наоборот проще: исчез избыточный уровень обобщения, улучшилось разделение ответственности (визуальная модель — только CSS, а HTML — только логическая структура), термины стали определенными и однозначными: «блочными» и «инлайновыми» отныне бывают только CSS-боксы, и ничто иное. Но проще — не значит скучнее! Структура HTML за 20 лет его истории закономерно усложнилась, типов содержимого в нем уже не 2-3, а целых 7, и логика взаимоотношений между ними не всегда очевидна с первого взгляда. Да и новые модули CSS вот-вот порадуют нас новыми типами CSS-боксов. Поэтому учиться чему-то новому нам придется обязательно, и еще не раз. Но разве это — не неизбежный спутник любого прогресса, в любой сфере? И, в конце концов, узнавать что-то новое — жутко интересно, само по себе, не правда ли?

P.S. Это тоже может быть интересно:

54 комментария

  1. «Так нужно ли вообще любой ценой увязывать модель содержимого и дефолтное отображение?»

    Скорее нужно, если не браузеры определяют новые HTML5 теги блочными по умолчанию, так мы сами ресетами определяем, что бы не возникало бардака и иметь предсказуемое поведение, не зря же почти все используют ресет/нормалайз css из проекта в проект.

    Да и если откинуть css вообще, то в plain HTML будут актуальны инлайновые и блочные элементы, документ должен быть построен так, что бы убрав свой CSS, содержимое оставалось понятным и доступным только на основе базовых стилей.

    1. Ресет и нормалайз — это хорошо, но потому они и востребованы, что дефолтным браузерным стилям уже нет полного доверия. А уж такого, чтобы на его основе классифицировать элементы самого HTML — и подавно. О чем и речь.

      Сегодня у нас есть две структуры: логическая в HTML и визуальная в CSS (даже в чисто текстовом режиме, в каком-нибудь @media tty). Естественно, обе структуры должны быть логичны. За логичностью структуры в разметке более-менее следит сам парсер (который просто не позволит вставить более крупный структурный блок, напр. div, в более мелкий, типа многострадального абзаца, даром что оба «блочные»!) и валидатор. С CSS-структурой сложнее, механизма, запрещающего заставить рендерер впихивать блочный бокс в инлайновый, нет (рендереру приходится выкручиваться через анонимные боксы), поэтому о логичности визуальной структуры должен думать сам верстальщик. Но логика этих структур может быть обоснованно разной (меню на списках в дизайне визуально может быть представлено как строка, а label-ы полей формы вполне могут быть отформатированы как блоки), более того — визуальное представление одной и той же логической структуры может динамически и адаптивно меняться.

      И деление самих элементов по их дефолтному отображению не только не предотвращает бардак, а наоборот, усиливает его (напр. подпитывая мифы, что «CSS позволяет менять модель содержимого» и т.п.).

      Что содержимое должно быть доступно при дефолтных стилях — я полностью согласен. Только вот деление элементов на «блочные и строчные» этому мало помогает. Деление на «фразовые», «группирующие», «секционные» и т.п. — которое предлагает новая спецификация — во-первых, гораздо информативнее, а во-вторых, уменьшает бардак уже тем, что не пересекается с терминологией CSS-оформления.

      1. Чисто теоритически, можно себя как то успокоить мыслью что больше нету блочных и инлайновых, что бы сильно не тревожится о разноглассии терминологий.

        Но практически, прочитыв и осознав суть статьи, ничего ведь не поменяеться, будем использовать те же ресеты и делать нативно блочные элементы инлайновыми, как раньше.

        1. Смысл статьи — именно в том, чтоб не запутывать себя созвучной терминологией. Что вообще неважно, какое у элемента дефолтное, или «нативное» представление (сегодня это может быть CSS-блок, завтра внезапно станет CSS-регион или еще какое-нибудь новшество) — важно лишь для чего элемент предназначен (для выделения текста, для группировки фраз или абзацев, для выделения секции и т.п.). А ресеты и т.п. — лишь для удобства и поддержания единообразия визуальной структуры, у которой своя логика, которая не должна сбивать с толку логику разметки…

  2. Отличный и мощный экскурс. Читал на одном дыхании. Действительно, многого не знал, хотя знаком с html уже примерно 10 лет. И понял, что да, действительно нужно взять новый стандарт и повнимательнее его почитать — это будет не просто не лишним, а очень даже полезным делом.

  3. >>> DOM может быть построена вообще не тегами, а скриптом (document.createElement и т.п.).

    Вы в своем уме? document.createElement создает именно ЭЛЕМЕНТ, который в последствии можно вставить в любое место DOM.

    Исправьте.

    1. Не вижу противоречия. Смысл пассажа именно в том, что элемент DOM может быть создан не только тегами в разметке.

  4. Какая откровенная ерунда! Откройте такой код с любом браузере
    Следующий пример: alert(«Привет, мир!») выводит окно с приветствием
    и посмотрите во что он превратится:
    Следующий пример: alert(«Привет, мир!») выводит окно с приветствием
    Особенно это вызывает проблемы, когда мы имеем стили вроде таких
    body {
    color: green;
    font-size: 8pt;
    }
    p {
    text-indent: 2em;
    font-size: 16pt;
    color: #444;
    }

  5. Какая откровенная ерунда! Откройте такой код с любом браузере
    <p>Следующий пример: <pre>alert(«Привет, мир!»)</pre> выводит окно с приветствием</p>
    и посмотрите во что он превратится:
    <p>Следующий пример:</p> <pre>alert(«Привет, мир!»)</pre> выводит окно с приветствием
    Особенно это вызывает проблемы, когда мы имеем стили вроде таких

    body {
    color: green;
    font-size: 8pt;
    }
    p {
    text-indent: 2em;
    font-size: 16pt;
    color: #444;
    }

    1. Именно! И об этом вскользь упомянуто в статье (правда, не конкретно про pre):

      Теги же разбирает парсер — ничего не знающий о CSS, но имеющий представление о допустимой модели содержимого. Например, о том, что внутри абзаца текста не может быть ни заголовка, ни списка

      Если оперировать понятиями «блочного и строчного», это поведение выглядит абсолютно нелогичным — ведь p такой же, казалось бы, блочный элемент, как и pre. А вот если смотреть на допустимую модель содержимого, да вспомнить, что закрывающий тег для p необязателен — по-моему, риск столкнуться с такой ошибкой намного меньше.

      Так что ерунда — как раз деление на «блочные и строчные»:)

  6. Ваши доводы оспоримы, чего только стоит засунуть в спан дин, и валидатор разорвет в пух и прах, как вариант, прочитайте примечания w3c.

    1. Какие именно доводы это оспаривает? Да, поточные элементы нельзя вставлять в текстовые (и ещё много ограничений), об этом сказано и в спецификации, и в последнем абзаце статьи. Но это не связано (по крайней мере, однозначно) с дефолтным отображением. Вот если бы в span с display:block засунуть див было внезапно можно, это было бы опровержением — но увы…

  7. Я конечно задам коммент не в тему. Тапками не кидайте. Но где можно что то путное прочитать по DOM? Ибо я вижу автор искушенный верстальщик.

    1. Вот здесь я сам не до конца улавливаю логику авторов спеки: чем label так уж радикально отличается, например, от a, что у второго может быть потоковый контент (по-старому — и «строчный», и «блочный»), а у первого — только фразовый (по-старому «строчный»)? Но решили вот так. Возможно, исходили из того, что поле формы с подписью по логике почти всегда бывает частью «параграфа» (точнее, скорее абзаца) документа, а не наоборот, а вложенных «параграфов» быть не должно.

      В общем, прямой ответ на сегодня — увы, никак. Но можно придать самому label и любому его разрешенному содержимому блочный вид — c помощью CSS.

      1. Насчёт a не очень понятно: я, конечно, переводчик тот ещё, но если понимать буквально написанное, то у «прозрачного» контента, на его поведение влияет родитель. Как это?
        И каким образом из этого следует, что в a можно класть div?
        При этом a обязательно в стилях задач блочный статус? Поясните пожалуйста…

        1. У элемента с «прозрачной» моделью контента может быть то же содержимое, что у его предка. Если a вложен в span, то и внутри самого a может быть только фразовый контент, а вот если он вложен в div, то и содержимое у него может быть таким же, как у div — включая другой div.

          А вот в label вкладывать a (это к следующему вопросу) нельзя, но не из-за «блочности/строчности», а из-за того, что нельзя вкладывать один интерактивный контент в другой. Иначе браузер запутается, какое действие ему выполнять по клику: переходить по ссылке, фокусировать поле формы, всё сразу (что невозможно)?

          Задавать блочный стиль «прозрачным» элементам не обязательно, но желательно, иначе браузер сам достроит анонинмную блочную обертку, которой будет трудно управлять.

          1. Что касается прозрачного контента, то всё это очень интересно… Нужно учить html! Заново :) А для этого читать спеку на английском. Чтение на английском сродни чтению CSS ещё, наверное, полгода назад — когда отдельные слова понимаешь, а в предложения они не складываются :-)
            Что же касается интерактивного контента, то с точки зрения спецификации — понятно, но с точки зрения логики — не совсем :) Ведь действие по клику может быть в разных отношениях к своим ссылкам, скажем, не вижу противоречия, если мы одновременно ставим чекбокс и переходим по ссылке. Но, понятно, что видимо, если разрешить, то придётся прописывать куда что можно, а что нельзя, это может сильно усложнить правила и сказаться на надёжности… Поэтому и нельзя. Но… работает :) (код не очень причёсывал, всё равно не валидно…)
            А вообще, конечно, интересная задача связать два участка документа, что задаёт некую сквозную логику… Но, опять же понятно, почему такое не приветствуется — поведение — это JS, у CSS задача — отобразить, а значит логика каскада — иерархичная, как наиболее подобная мазкам кисти — вот шапочка, а вот на ней звёздочка :) Но всё-таки бывают и исключения, и с точки зрения отображения — динамика сцены, и с точки зрения логики — CSS3, во многом, даёт простейшие динамические элементы, да и адаптивность не всегда за счёт медиа-запросов делается, определённая логика заложена и в самой раскладке…
            Вот я медитировал, как можно связать ссылки a с внешним элементом. Получается, если a и label не может быть друг в друге, то, по крайней мере, label, по логике, может ссылаться на a (хотя, по спеке, он, конечно, этого делать не может, также как и у label может быть только один for).
            Так, вот, если бы label мог ссылаться на a, то мы, по крайней мере, могли бы часть пуктов меню вытащить из контейнера и поместить вовне, а изнутри ссылаться бы на них через label. Но и такое невозможно, поскольку в CSS потребовалась бы конструкция вида:
            (div a:hover) + .menu
            а такое группирование скобками тоже не предусмотрено.
            И тоже не удивительно — поскольку нарушает некую каскадность — и требует от браузера движений вверх по дереву, что опять-таки усложняет раскладку. Но ведь была же статья у Вас про display: context (или как там?), а значит вопрос, в ряде случаев актуальный, и не только я ощущаю потребность в инструменте, позволяющим задавать некую сквозную логику в документе и делать это так, чтоб браузеру было понятно, где что.
            А вообще, может назрела уже необходимость в поддержке селектора :has, который позволит не прибегая к таким изощрениям, сделать зависимость родительского элемента от дочернего (впрочем при группировании скобками движение вверх по течению тоже возникает).
            С другой стороны — не противоречит ли это самой логике каскада? Но если да, то как быть в подобных неоднозначных ситуациях?
            Это вопрос к Вам, как людям хорошо понимающим не только CSS, но и его место в построение веб-документа.
            Спасибо!

            1. не вижу противоречия, если мы одновременно ставим чекбокс и переходим по ссылке.

              Ну как же, ведь переход по ссылке фактически уничтожает текущую страницу и целиком заменяет ее новой! Какая разница, поставлен или снят чекбокс на странице, которая через миг исчезнет и останется лишь воспоминанием в history?

              назрела уже необходимость в поддержке селектора :has

              Назрела. Причем :has не ограничен родительским элементом, он мог бы выбирать и последующих соседей, и много чего еще. Но да, опасения насчет его скорости и связанная с ними странная мысль ограничить его сферу действия лишь статикой… это не радует. Будем надеяться, что хоть кто-то из браузеров (хоть тот же Edge) всё-таки реализует его по-человечески, для всех случаев, и подаст пример другим.

              1. Какая разница, поставлен или снят чекбокс на странице, которая через миг исчезнет и останется лишь воспоминанием в history?

                Ну я до веб-программирования не дошёл ещё, но, навскидку, что мешает, чтоб пометочка была использована в скрипте, а страничка спокойно себе загрузилась какая нужно?

                Причем :has не ограничен родительским элементом, он мог бы выбирать и последующих соседей, и много чего еще.

                Проголосовал по ссылке, правильно ли я понимаю, что по сути этот селектор, позволяет осуществлять, как я говорил в предыдущем сообщении, некую сквозную логику, полноценно связывать разные элементы документа, навроде того, как я пытаюсь тут извратится с label?
                Вообще сквозная логика очень естественна, поскольку ЛЮБОЙ объект находится во МНОЖЕСТВЕ взаимоотношений с другими объектами (и логика будет зависеть от контекста тех или иных взаимоотношений), другой вопрос, как реализовать это так, чтоб, по возможности, избежать цикличности?
                А так вообще да здравствует теория графов, где бы её выучить, чтоб понимать…

                1. чтоб пометочка была использована в скрипте, а страничка спокойно себе загрузилась какая нужно?

                  Опять же — чей скрипт и где страничка? Если всё происходит в главном окне браузера (по умолчанию) — при загрузке новой странички уничтожаются и все скрипты, жившие на предыдущей. У новой странички могут быть свои скрипты, но они никак не могут знать о «пометочках» старой. Передавать информацию между страницами можно лишь специальными средствами типа куков и localStorage.

                  Другое дело, если страничка открывается в новом окне/табе, или, допустим, в iframe — там такое возможно. Но по-моему такие вещи рациональнее открывать скриптом же. Тогда логикой зависимостей между окнами управляет программист, и браузеру не приходится выполнять взаимоисключающие команды. Да и вообще «размножающиеся» при кликах окна — мягко говоря, очень спорное решение)

                  1. Ну, как я уже писал — всё это некие хаки, попытка решить две задачи средствами для этого не созданными — первое, и основное — задать стиль родителя, по состоянию потомка. Замена селектору :has, у которого плохо с поддержкой. И вторая задача, служебная для первой, но интересная и сама по себе — это связать два (и более?) различных элемента, лежащих в произвольных местах документа. Мне сложно, навскидку, придумать хороший пример, зачем это может быть нужно, но это не просто возможность, это некое «поле возможностей», а значит вариантов применения может быть много, что и усложняет их оценку… Впрочем, при наличии опыта, это, наверное, проще, сталкивались ли Вы с задачами, где такое решение могло бы пригодится? Правда, и у опытных разработчиков тоже могут быть сложности с ответом на подобные вопросы — из-за обилия вполне надёжно работающих решений, не всегда может ощущаться необходимость чего-то такого, что не ведёт к очевидному улучшению существующих решений. Пока возможность не стала задачей — оценить её сложно, а чтоб подобные задачи формулировались — нужна возможность :-)
                    И тем не менее, вопрос есть ли потребность в подобном, актуален в любом случае…
                    Прямых примеров, как, иными средствами (не label, созданный, кстати, для довольно узких целей — связи формы с подписью), можно реализовать подобную сквозь-иерархическую взаимосвязь как-то особо не наблюдается, впрочем, немного похожим образом, Вы использовали display: context в примерах из своей статьи, но, всё же повысить уровень иерархии на один этаж (или не на один, если повторить тоже, для потомков), это всё же, упрощает взаимосвязь для элементов с разными предками, и даёт возможность через различные селекторы менять состояние одного, по состоянию другого. Но всегда ли этот инструмент достаточно гибок?
                    С другой стороны, возможно, я не совсем понимаю, всех последствий подобного связывания (хотя ясно, что чем больше зависимостей, тем сложней отрисовка и может оказаться, неожиданно, значительно сложнее). Ведь наверняка разработчикам приходили в голову подобные идеи, которые они, вероятно, решали через скрипты.

                  2. Ну тогда можно попробовать пойти другим путём — связать label с чем-то таким, что может одновременно стать ссылкой, оставаясь при этом input-ом :-) Такой элемент не будет дочерним лейблу, а лейбл — дочерним элементу, они просто будут связаны, что по-идее, не запрещено. Насколько я понимаю, лейблу разрешено ссылаться на элемент формы, коих — зоопарк со своими атрибутами, нам нужен работающий атрибут href. По-идее, кнопки, по своему назначению, похожи на ссылки… Может ли какой-то элемент формы, каким-либо образом, стать чем-то вроде ссылки-в-законе? %)
                    Если предположить что такое возможно, то связка label с этим элементом формы, заметно усложнит, этот, несмотря на противоречивость, работающий пример:
                    придётся всю структуру ссылок, которые должны влиять на родительский элемент выносить ЗА блок. А поскольку, по логике, это способ расширения одной панели, то логично их поместить в один родительский контейнер, то есть, прибавить ещё один уровень иерархии.
                    Для влияния на UL, через ссылки находящиеся перед ним, как в примере, вместо соседнего селектора + UL(применив, который, придётся вручную считать количество ссылок, чтоб попасть в наш аUL) нужно использовать родственный селектор ~ ul.
                    Если же мы эти «ссылки» запихнём в отдельный бокс (например в form, что логично для элементов формы), то этой форме можно поставить display: context, чтоб ul стал для элементов формы «родственником», лежащим на одном уровне иерархии и его состояние могло меняться, в зависимости от их состояния.
                    На вопрос, на фига козе баян, если есть хоть и не валидный, и хуко-образный, но работающий код, могу сказать только одно: цель подобных поисков не в том, чтоб решить конкретную задачу, а лучше понять возможности CSS, увидеть какие связи в нём применимы и как, и, тем самым, расширить спектр решаемых задач…

              2. Кстати, опять же по-поводу противоречий, и, рискуя продемонстрировать некомпетентность, всё же приведу пример, который, на мой взгляд, иллюстрирует то, что однотипные свойства могут быть применимы, если они находятся в разных отношениях: в форме у поля может быть одновременно И имя, И идентификатор (name=»password» id=»passField» ну и type=»password» для комплекта).
                И то, и другое, однозначно харрактеризует именно это поле (насколько я понимаю), но, всё же, сосуществуют вместо, поскольку дополняют друг друга.
                Я понимаю, что против спеки не попрёшь, но то, что подобный подход имеет место быть говорит о том, что он может быть востребован и в других ситуациях, что, в контексте разговоре об интерактивном контенте, говорит о том, что ссылки могут быть по отношению к исходному элементу в разных отношениях, как собственно ссылка, и как взаимосвязь с другой частью документа, а зачем нужна эта взаимосвязь — это уже вопрос к разработчику, который может её создать исходя из логики выполняемой задачи.

                1. Пример отличный! Но всё же name и id — не совсем однотипные свойства. Id любого элемента именно однозначно идентифицирует его на странице, а name элемента формы в основном отвечает за поле в запросе, которым эта форма отправит данные на сервер. И name не обязан быть уникальным, в случае одноименных полей формы браузер обязан отправить их все (а уже сервер решит, что сделать с ними дальше — собрать в массив, как когда-то делал классический ASP, оставить только последнее, как по умолчанию делает PHP, или еще что-нибудь).

                  1. Ну, в общем, нужно изучать возможности не только CSS, но и других front-end технологий, для того, чтоб понимать, что, и каким образом, можно и стоит делать…
                    Спасибо за разъяснения!

          2. Да, кстати, я тут подумал, а ведь «рычагов» перед контейнеров может быть несколько, и это тоже даёт некое пространство для манёвра :)
            Другой вопрос, что всё равно всё это не валидно.
            Для связи с элементом формы воздействие должно быть непосредственно на label (а не на его предка), а для перехода по ссылке — непосредственно на a, и это нужно сделать одновременно. Получается, нужно обернуть ссылку в label, а делать этого нельзя. А другие варианты html, к сожалению, не просматриваются…

      2. можно придать самому label и любому его разрешенному содержимому блочный вид — c помощью CSS

        Ну вот я немного попробовал это использовать для меню, пока что-то не очень работает…
        89 строчка CSS-кода: для label задан блочный статус.
        Тег а, как «фразовое содержимое», спокойно может помещаться в label.
        У a также задан блочный статус и в 37 строчке кода заданы паддиги.
        Получается, оборачиваем a в label и паддинги съезжают.
        Почему? Можно ли как-то сделать чтоб не съезжали?

        1. в 37 строчке кода заданы паддиги

          Там же селектор li > aa непосредственный потомок li . А в этом коде он уже не непосредственный.

  8. А также как сделать невидимым элемент вроде button или input и чтоб он совсем не занимал место, но, при этом, не исчезал из потока?

    1. В принципе, есть вот такой способ. Правда, формально из потока он всё-таки вырывает (раз absolute), но фактически элемент остается на том же месте страницы, где был бы без скрытия (координаты не меняются), и скринридеры и т.п. его тоже видят.

      1. Спасибо, то что нужно!
        Как раз ни видно, не слышно, но элемент есть.
        https://jsfiddle.net/Launder/mp9bevy4/3/ — чекбокс работает как ни странно и при display: none. А вот при наведении webkit уже не хочет реагировать.

  9. Здравствуйте, что от этого меняется? Ведь для flex-box по любому придется указывать кучу див. Мне кажется в моей верстке ничего не изменится. если я не прав пожалуйста напишите, смотрю стримы опытных верстальщиков. Ни разу не видел чтоб «блочный тег» вкладывали в «строчный». И вообще, они же до сих пор как бы. Блочные занимают всё пространство, а строчные нет. Разве нельзя просто называть теги которые занимают всю линию блочными, а те которые не занимают всё пространство, строчными? Что от этого меняется?

    1. Называть можно, но в том-то и дело, что эта информация сейчас не дает особой пользы. У каждого элемента есть модель содержимого (Content model), указанная в спецификации, всё. Других критериев, что куда можно вкладывать, нет. Например, в многострадальную ссылку при необходимости можно вкладывать дивы (валидатор ругаться не будет), но нельзя вкладывать другие ссылки или input-ы, потому что они — интерактивные элементы, а интерактивные элементы вложенными быть не должны (иначе браузер запутается, чье действие отрабатывать по клику — внешнего элемента или внутреннего). А вот блочный <div> в вроде бы блочный же <p> вкладывать нельзя — модель содержимого у абзаца «строчная». Кастомные элементы все «строчные» по дефолтным стилям, но в компоненте могут играть роль контейнера. Ну и на мой взгляд как-то странновато называть элементы типа <video>, <textarea> или <iframe> строчными (хотя по старой классификации они именно таковы). Так что оглядка на дефолтные стили не особо помогает, а иногда только сбивает с толку. Ну а во флексбоксах или гридах любой элемент (хоть заголовок, хоть ссылка, хоть инпут) может быть равноправным флекс- или грид-элементом и занимать сколько нужно, и на вкладываемость этих элементов друг в друга это никак не влияет.

      И вообще, в чем плюс размытых устаревших терминов, которых нет в спецификации, не лучше ли сразу привыкать к строгости и однозначности современных определений?

      Вот в CSS детали визуальной структуры (боксы) бывают блочными и строчными (и много какими еще), и там как раз есть смысл следить, чтобы у родителя с display:inline случайно не оказался потомок с display:block, иначе возможны сюрпризы. Но дефолтные стили элементов с этим тоже связаны лишь косвенно.

  10. Что меняет отсутствие строчных и блочных тегов в html?
    То что теперь блочные теги можно вкладывать в строчные? Или нафига их вообще убрали? Что-нибудь изменилось вообще???

    1. Теперь не надо смотреть на то, как элементы выглядят (да еще с оговоркой «по умолчанию»). Надо задумываться только о том, что они делают.

      1. Теперь всё стало на свои места) Кстати советую так и написать в начале статьи, потому что мне как новичку было не понятно(

          1. То есть это потому что в css можно из строчного сделать блочный и наоборот?

      2. То есть это потому что в css можно из строчного сделать блочный и наоборот?

        1. Да, в CSS можно из (почти) чего угодно сделать (почти) что угодно. Но это не влияет на роль, смысл, функцию и действие элементов и на то, что во что можно вкладывать.

          Объективности ради, бывают редкие исключения, когда CSS вмешивается в функцию элемента (напр. некоторые скринридеры переставали воспринимать таблицы как таблицы, если поменять их родной display:table на что-то другое), но их немного, и чаще всего они на поверку оказываются просто багами.

  11. А изначально же в  css даётся тип блоку. Ну то что мне не обязательно писать диву displey:block; потому-что он по дефолту стоит displey:block; а у span по дефолту стоит displey:inline. Правильно?

     

    1. У браузеров есть свои встроенные стили для элементов (по этой ссылке их можно посмотреть). Там есть и дефолтный display. Но по сути это обычные CSS-стили, к тому же с наименьшим приоритетом. Поэтому даже минимально специфичный * { display: initial } перекроет эти дефолтные стили и сбросит их display на начальное значение по спецификации CSS, т.е. на display: inline.

      1. Спасибо, теперь абсолютно всё стало на свои места)  Уважение вам за отклик, побольше бы таких специалистов:)

  12. То есть я могу спокойно положить в ссылку «a» тег «div», и ни о чем не париться? А валидатор кстати будет ругать за такое?

      1. Да, валидатор уже давно это разрешает, о валидности париться не нужно. Но, возможно, придется попариться о правильных стилях для такой конструкции (чтобы не пришлось бороться с непонятно откуда берущимися анонимными боксами) и с доступностью ее для скринридеров (по умолчанию всё содержимое ссылки считается ее названием, и если оно слишком длинное, пользователю будет неудобно выслушивать его целиком, это можно поправить с помощью aria-label, но у него свои издержки). Так что общее правило, что содержимое ссылки лучше делать по возможности более лаконичным, всё еще актуально. Просто диктуется оно исключительно здравым смыслом и соображениями удобства для пользователей, а не формальной «прихотью» валидатора.

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.