Использование тегов <style> в <body> с другим HTML

196
<html>
  <body>
    <style type="text/css">
      p.first {color:blue}
      p.second {color:green}
    </style>

    <p class="first">Hello World</p>
    <p class="second">Hello World</p>

    <style type="text/css">
      p.first {color:green}
      p.second {color:blue}
    </style>

    <p class="first">Hello World</p>
    <p class="second">Hello World</p>
  </body>
</html>

Как браузер должен отображать CSS, который не является смежным? Предполагается ли создать некоторую структуру данных, используя все стили CSS на странице, и использовать ее для рендеринга?

Или он использует информацию о стиле в том порядке, в котором он видит?

Gagan
источник
2
Я бы сказал, что это неопределенное поведение, так как это недопустимый HTML. Для получения дополнительной информации, какие элементы являются действительными, а какие нет: en.wikipedia.org/wiki/HTML_element
Феликс Клинг
2
Оставляя в стороне этой проблемы, это плохая практика , чтобы смешивать CSSи HTML.
0x2D9A3
1
@ 0x2D9A3 Не обязательно верно. Для запроса внешней страницы CSS требуется больше времени, чем для CSS, который определен в <head>теге
Kolob Canyon
@KolobCanyon Согласитесь, но, как правило, CSS должен быть в отдельном файле. Если у вас есть тонны CSS, им проще управлять (обслуживать, (после), обрабатывать, минимизировать, объединять) и работать как отдельный файл, и ваш контент (HTML) также может загружаться быстрее, что приводит к улучшению UX. Однако, как всегда в разработке, все зависит от контекста, поэтому YMMW :)
0x2D9A3
3
@KolobCanyon, это не проблема того, должен ли CSS быть в отдельном файле. В этом случае речь идет о CSS в, <body>а не в <head>.
Рэй Баттерворт

Ответы:

312

Как уже упоминали другие, HTML 4 требует, чтобы <style>тег размещался в <head>разделе (хотя большинство браузеров допускают <style>теги внутри body).

Однако HTML 5 включает в себя scopedатрибут (см. Обновление ниже), который позволяет создавать таблицы стилей, которые находятся в родительском элементе <style>тега. Это также позволяет вам размещать <style>теги внутри <body>элемента:

<!DOCTYPE html>
<html>
<head></head>
<body>

<div id="scoped-content">
    <style type="text/css" scoped>
        h1 { color: red; } 
    </style>

    <h1>Hello</h1>
</div>

    <h1>
      World
    </h1>

</body>
</html>

Если вы отобразите приведенный выше код в браузере с поддержкой HTML-5, который поддерживает scoped, вы увидите ограниченную область применения таблицы стилей.

Есть только одна серьезная оговорка ...

На момент написания этого ответа (май 2013 г.) почти ни один из основных браузеров в настоящее время не поддерживает этот scopedатрибут. (Хотя, видимо, сборки разработчика Chromium поддерживают его.)

ОДНАКО, есть интересное значение scopedатрибута, который относится к этому вопросу. Это означает, что будущие браузеры получают мандат через стандарт, чтобы разрешить <style>элементы внутри <body>(до тех пор, пока <style>элементы ограничены).

Итак, учитывая, что:

  • Почти каждый существующий браузер в настоящее время игнорирует scopedатрибут
  • Почти каждый существующий браузер в настоящее время допускает <style>теги в<body>
  • В будущих реализациях потребуется разрешить (ограничить) <style>теги внутри<body>

... тогда размещение тегов в теле буквально не вредно * <style>, если в будущем вы подтвердите их с помощью scopedатрибута. Единственная проблема заключается в том, что современные браузеры не будут на самом деле ограничивать область применения таблицы стилей - они будут применять ее ко всему документу. Но дело в том, что для всех практических целей вы можете включать <style>теги в том случае, <body>если вы:

  • Перспективный ваш HTML, включая scopedатрибут
  • Поймите, что на данный момент таблица стилей внутри <body>фактически не будет ограничена (потому что пока еще не поддерживается основной браузер)


* кроме, конечно, для того, чтобы разозлить валидаторы HTML ...


Наконец, что касается общего (кроме субъективного) утверждают , что вложение CSS в HTML является плохой практикой, следует отметить , что вся суть в scopedатрибуте для размещения типичных современных концепций развития , которые позволяют разработчик импорта куски HTML в виде модулей или синдицированного содержания , Очень удобно иметь встроенный CSS, который применяется только к определенному фрагменту HTML, чтобы разрабатывать инкапсулированные, модульные компоненты со специфическими стилями.


Обновление по состоянию на февраль 2019 г., согласно документации Mozilla , scopedатрибут устарел. Chrome прекратил поддерживать его в версии 36 (2014) и Firefox в версии 62 (2018). В обоих случаях эта функция должна была быть явно включена пользователем в настройках браузера. Ни один другой крупный браузер никогда не поддерживал его.

Чарльз Сальвия
источник
3
@RobertMcKee: ты действительно проверял это? Я ожидаю, что обычно вся html-страница (включая все встроенные стили) анализируется перед рендерингом, поскольку обычно она невелика, и браузеры ждут (очень короткий) времени перед тем, как выполнить рендеринг точно, чтобы избежать появления внезапного непростого содержимого. из-за css, связанного в head. Если это ваш единственный CSS, и если страница является большой и если сетевое соединение не очень быстро, то , возможно , вы увидите вспышку контента без стилей, но это бы меня удивить в большинстве практических ситуаций.
Имон Нербонн
4
На сегодняшний день только Firefox поддерживает элемент стиля с заданной областью (согласно caniuse.com/#feat=style-scoped ). А поскольку обычные браузеры просто поддерживают элемент STYLE внутри BODY, я бы просто использовал его, если это необходимо. Если CSS должен быть применен в области видимости, вы можете просто поставить перед каждым селектором в источнике CSS идентификатор / класс оболочки. Я на самом деле сделал это в веб-приложении, которое загружало HTML-отчеты на сервер и отображало их через AJAX. CSS может быть затем префикс с простым регулярным выражением в JavaScript: cssString.replace (/ (^ | \}) ([^ {] +) (\ {) / g, '$ 1' + префикс + '$ 2 $ 3')
Адам Хошек
5
Поддержка @scopedили, scopedкажется, вымирает: здесь и здесь
Киран Суббараман
51
Поддержка @KiranSubbaraman: я только что (июль 2016 года) прочитал на mozilla dev: « Атрибут scoped был удален из спецификации только после ограниченного и экспериментального принятия Chrome и Firefox. Вам следует избегать его использования , так как он почти наверняка будет удалены из этих браузеров в ближайшее время. " >> developer.mozilla.org/en-US/docs/Web/HTML/Element/…
jave.web
9
scopedАтрибут был удален из текущей спецификации HTML5.
Альберт Верш
62

Плохие новости для «стиль тела» любителей: W3C недавно потерял HTML войну против WHATWG, чьи versionless HTML «Уровень жизни» теперь стал официальным один, который, увы, никак не позволяет STYLE в BODY. Недолгие счастливые дни закончились. ;) Валидатор W3C также работает по спецификациям WHATWG. (Спасибо @FrankConijn за хедз-ап!)

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

СОБСТВЕННЫЕ ХОРОШИЕ НОВОСТИ:

Да, STYLEнаконец-то действует в BODYHTML5.2! scopedушел тоже.)

Из спецификации W3C ( смакуйте последнюю строчку! ):

4.2.6. Элемент стиля

...

Контексты, в которых этот элемент может быть использован:

Где ожидается содержание метаданных.

В элементе noscript, который является дочерним элементом элемента head.

В теле, где ожидается поток.


META SIDE-NOTE:

Тот факт, что, несмотря на убытки от «войны браузеров», нам все равно приходилось развиваться против двух смехотворно конкурирующих «официальных» HTML-стандартов (цитат для 1 standard + 1 standard < 1 standard), означает, что подход «отступления к здравому смыслу» веб-разработка действительно никогда не прекращала применяться.

Это может, наконец, измениться сейчас, но, ссылаясь на общепринятую точку зрения: веб-разработчики / разработчики и, следовательно, браузеры, в свою очередь, должны в конечном итоге решить, что должно (и не должно) быть в спецификациях, когда нет веских оснований против того, что уже было сделано в реальность. И большинство браузеров уже давно поддерживается STYLEв BODY(в той или иной форме , см , например , в scoped. Attr) (который, несмотря на присущие производительности (и , возможно , другие) штрафы мы . Должны решить , платить или нет, а не спецификации). Так что, во-первых, я буду продолжать делать ставки на них, и не собираюсь терять надежду. ;) Если WHATWG имеет такое же уважение к реальности / авторам, как они утверждают, они могут просто сделать здесь то, что сделал W3C.

Sz.
источник
3
Я читаю спецификации, но не понимаю. Можете ли вы привести пример кода styleблока, bodyкоторый проверяет?
Фрэнк Конейн
3
@FrankConijn: Хороший вопрос, все изменилось, обновил ответ! Это действительно сбивает с толку. Как спецификации W3C 5.2, так и 5.3, W3C рассматривают STYLEкак метаданные и контент потока, но последняя «живая» спецификация WHATWG рассказывает старую, скучную историю «только метаданные» (разрешив ее только в HEAD). И, чтобы добавить оскорбление травме, валидатор W3C, похоже, следует духу WHATWG. Я еще не решил, смеяться или плакать, но уверен, что лично решил «ошибиться» с делом «браузеры + W3C - валидатор» и разрешить STYLE в BODY. (Кстати, не забывайте: мы должны быть основным источником стандарта , на самом деле.)
Sz.
1
Я действительно думаю, что они прыгнули на акулу с этим дерьмом, они в основном не оставляют иного выбора, кроме как использовать стили линий, если вы хотите динамически установить свойство фонового изображения в шаблонной системе. Было гораздо менее инвазивно отбрасывать программно сгенерированный блок стилей прямо над выводом html.
GovCoder
К счастью, кажется маловероятным, чтобы браузеры прекратили поддерживать возможности, от которых зависят многие веб-сайты. Было бы неудобно в CMS или сторонних плагинах не иметь встроенных стилей. Лично, когда прагматично (когда у меня нет легкого доступа <head>), я буду продолжать использовать эту функцию, поддерживаемую браузером, пока она не сломается.
ToolmakerSteve
33

Когда я вижу, что системы управления контентом большого сайта обычно помещают некоторые элементы <style> (некоторые, не все) близко к контенту, который опирается на эти классы, я делаю вывод, что лошадь находится вне сарая.

Посмотрите источники на страницах cnn.com, nytimes.com, huffingtonpost.com, ближайшей газеты большого города и т. Д. Все они делают это.

Если есть веская причина поместить дополнительный раздел <style> где-нибудь в теле - например, если вы включаете () разнообразные и независимые элементы страницы в реальном времени, и у каждого есть свой собственный встроенный <style>, и организация будет чище, более модульной, более понятной и более удобной в обслуживании - я говорю, просто откусите пулю. Конечно, было бы лучше, если бы у нас был «локальный» стиль с ограниченной областью действия, например локальные переменные, но вы переходите к работе с имеющимся у вас HTML, а не с HTML, который вы захотите или захотите иметь позднее.

Конечно, есть потенциальные недостатки и веские (если не всегда убедительные) причины следовать ортодоксальности, как это разработали другие. Но мне кажется, что вдумчивое использование <style> в <body> уже стало мейнстримом.

верхняя граница распространения леса
источник
2
Прагматизм FTW!
Варуяма
2
Да, ты прав. В качестве примера я использую тег <style> в <body> внутри своего плагина. Почему, потому что это самый простой способ стильного контента плагина. Но один момент, все классы CSS являются уникальными для моих данных плагинов.
Avirtum
7

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

Протестировано в последних версиях FF и Google Chrome под Fedora, а также FF, Opera, IE и Chrome под XP.

Nico
источник
6

Я предполагаю, что это будет варьироваться от браузера к браузеру: глобальные правила отображения, вероятно, будут обновляться по мере прохождения браузером кода.

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

В любом случае, это недействительный HTML, поэтому я бы сказал, что об этом думать бесполезно. <style>теги принадлежат в headразделе страницы.

Пекка
источник
5

Как уже говорили другие, это недопустимый html, так как теги стиля принадлежат заголовку.

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

Не я
источник
5

<style>Принадлежит тег в <head>секции, отдельно от всего содержимого.

Рекомендации: спецификации W3C и W3Schools

Джош Стодола
источник
52
Не решает вопрос. И эти жесткие ориентиры переполнены реальностью. Есть МНОГИЕ случаи, когда авторы не могут определить / включить свой стиль в заголовок HTML.
Хавьер
3
Возможно, это было правдой в 2010 году, но сегодня это далеко от приемлемого ответа.
Исаак Любов
3

В вашем примере браузер не «должен» ничего делать. HTML-код недействителен. Либо происходит восстановление после ошибки, либо анализатор делает это так, как будет.

В допустимом случае несколько таблиц стилей просто обрабатываются как появляющиеся одна за другой, каскад рассчитывается как обычно.

Quentin
источник
2

Я предполагаю, что это может быть проблемой ограниченного контекста, например, редакторов WYIWYG в веб-системе, используемой пользователями, не являющимися программистами , что ограничивает возможности соблюдения стандартов. Иногда (например, TinyMCE), это библиотека, которая помещает ваш контент / код в textareaтег, который редактором представляется как большой divтег. А иногда это может быть старая версия этих редакторов.

Я полагаю, что:

  1. эти пользователи , не являющиеся программистами , не имеют открытого канала с системными администраторами (или веб-сайтами организации), чтобы попросить включить некоторые правила CSS в систему stylesheets. На самом деле, это было бы нецелесообразно для администраторов (или веб-разработчиков), учитывая количество запросов в том смысле, что они будут иметь.
  2. эта система является устаревшей и до сих пор не поддерживает более новые версии HTML.

В некоторых случаях, без использования styleправил, это может быть очень плохой опыт проектирования. Так что да, эти пользователи нуждаются в настройке. Хорошо, но каковы будут решения в этом сценарии? Учитывая различные способы вставки CSS на htmlстраницу, я предполагаю, что эти решения:


1-й вариант: спросите у своего сисадма

Попросите вашу систему adm для включения некоторых правил CSS в систему stylesheets. Это будет внешнее или внутреннее решение CSS . Как уже было сказано, это может быть невозможно.


2-й вариант: <link>вкл<body>

Используйте внешнюю таблицу стилей для bodyтега, т. Е. Используйте linkтег внутри области, к которой у вас есть доступ (то есть на сайте, внутри bodyтега, а не в headтеге). Некоторые источники говорят, что это нормально, но «не очень хорошая практика», как MDN :

<link>Элемент может происходить либо в <head>или <body>элементе, в зависимости от того, имеет ли он тип связи, которое тело-ки . Например, stylesheetтип ссылки body-ok, и поэтому <link rel="stylesheet">разрешен в теле. Тем не менее, это не очень хорошая практика для подражания; имеет больше смысла отделять ваши <link>элементы от содержимого вашего тела, помещая их в <head>.

Некоторые другие ограничивают его <head>разделом, например, w3schools :

Примечание. Этот элемент присутствует только в разделе заголовка, но может появляться любое количество раз.

тестирование

Я проверил это здесь (окружение рабочего стола, в браузере), и оно работает для меня. Создать файл foo.html:

<!DOCTYPE html>
<html>
<head></head>
<body>
    <link href="bar.css" type="text/css" rel="stylesheet">
    <h1 class="test1">Hello</h1>
    <h1 class="test2">World</h1>
</body>
</html>

Затем CSS-файл в том же каталоге называется bar.css:

.test1 { 
    color: green;
};

Что ж, это выглядит просто возможным, если у вас есть способ загрузки файла CSS где-нибудь в системе учреждения. Может быть, это будет так.


3-й вариант: <style>вкл<body>

Используйте таблицу стилей Интернета для bodyтега, т. Е. Используйте styleтег внутри области, к которой у вас есть доступ (то есть на сайте, внутри bodyтега, а не в headтеге). Это то, о чем здесь отвечают Чарльз Сальвия и Сз . Выбирая этот вариант, учитывайте их опасения.


4-й, 5-й и 6-й варианты: JS способы

Оповещение Это относится к изменению <head>элемента страницы. Может быть, этого не допустят системные администраторы учреждения. Поэтому рекомендуется сначала спросить их разрешение.

Хорошо, если разрешение предоставлено, стратегия заключается в доступе к <head> . Как? Методы JavaScript.

4-й вариант: новый <link>на<head>

Это еще одна версия 2-го варианта. Используйте внешнюю таблицу стилей для <head>тега, т. Е. Используйте <link>элемент вне области, к которой у вас есть доступ (то есть на сайте, а не внутри bodyтега и да внутри headтега). Это решение соответствует рекомендациям MDN и w3schools , как указано выше, по второму варианту решения. Новый Linkобъект будет создан.

Чтобы решить эту проблему с помощью JS, есть много способов, но в следующих разделах кода я демонстрирую один простой.

тестирование

Я проверил это здесь (окружение рабочего стола, в браузере), и оно работает для меня. Создать файл f.html:

<!DOCTYPE html>
<html>
<head></head>
<body>
    <h1 class="test1">Hello</h1>
    <h1 class="test2">World</h1>
    <script>
        // JS code here
    </script>
</body>
</html>

Внутри scriptтега:

var newLink = document.createElement("link");
newLink.href = "bar.css";
newLink.rel = "stylesheet";
newLink.type = "text/css";
document.getElementsByTagName("head")[0].appendChild(newLink);

И затем в файле CSS, в том же каталоге, называется bar.css(как в 2-й вариант):

.test1 { 
    color: green;
};

Как я уже сказал: это будет выглядеть просто возможно, если у вас есть способ загрузки файла CSS где-нибудь в системе учреждения.

5-й вариант: новый <style>на<head>

Используйте новую внутреннюю таблицу стилей для <head>тега, т. Е. Используйте новый <style>элемент вне области, к которой у вас есть доступ (то есть на сайте, а не внутри bodyтега и да внутри headтега). Новый Styleобъект будет создан.

Это решается через JS. Один простой способ демонстрируется следующим.

тестирование

Я проверил это здесь (окружение рабочего стола, в браузере), и оно работает для меня. Создать файл foobar.html:

<!DOCTYPE html>
<html>
<head></head>
<body>
    <h1 class="test1">Hello</h1>
    <h1 class="test2">World</h1>
    <script>
        // JS code here
    </script>
</body>
</html>

Внутри scriptтега:

var newStyle = document.createElement("style");
newStyle.innerHTML = 
    "h1.test1 {"+
        "color: green;"+
    "}";
document.getElementsByTagName("head")[0].appendChild(newStyle);

6-й вариант: использование существующего <style>на<head>

Использовать существующую внутреннюю таблицу стилей для <head>тега, т. Е. Использовать<style> элемент вне области, к которой у вас есть доступ (то есть на сайте, а не внутри bodyтега и да внутри headтега), если таковой существует. StyleБудет создан новый объект или будет использован CSSStyleSheetобъект (в принятом здесь коде решения).

Это в какой-то момент рискованно. Во-первых , потому что не может существовать какой-то <style> объект. В зависимости от способа реализации этого решения вы можете получить undefinedвозврат (система может использовать внешнюю таблицу стилей ). Во-вторых , потому что вы будете редактировать дизайн системы авторской работы (вопросы авторства). В-третьих , потому что это не может быть разрешено политикой безопасности вашего учреждения. Итак, попросите разрешения сделать это (как в других решениях JS) .

Предположим, опять же, разрешение было предоставлено:

Вам нужно будет рассмотреть некоторые ограничения метода , доступного таким образом: insertRule(). Предлагаемое решение использует сценарий по умолчанию и операцию на первомstylesheet , если таковая существует.

тестирование

Я проверил это здесь (окружение рабочего стола, в браузере), и оно работает для меня. Создать файлfoo_bar.html:

<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <h1 class="test1">Hello</h1>
    <h1 class="test2">World</h1>
    <script>
      // JS code here
    </script>
  </body>
</html>

Внутри scriptтега:

function demoLoop(){ // remove this line
    var elmnt = document.getElementsByTagName("style");
    if (elmnt.length === 0) {
        // there isn't style objects, so it's more interesting create one
        var newStyle = document.createElement("style");
        newStyle.innerHTML =
            "h1.test1 {" +
                "color: green;" +
            "}";
        document.getElementsByTagName("head")[0].appendChild(newStyle);
    } else {
        // Using CSSStyleSheet interface
        var firstCSS = document.styleSheets[0];
        firstCSS.insertRule("h1.test2{color:blue;}"); // at this way (without index specified), will be like an Array unshift() method
    }
} // remove this too
demoLoop(); // remove this too
demoLoop(); // remove this too

Другой подход к этому решению - использование CSSStyleDeclarationобъекта (документы в w3schools и MDN ). Но это может быть неинтересно, учитывая риск переопределения существующих правил в CSS системы.


7-й вариант: встроенный CSS

использование встроенный CSS . Это решает проблему, хотя в зависимости от размера страницы (в строках кода) поддержание (самим автором или другим назначенным лицом) кода может быть очень трудным.

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

тестирование

Создать файл _foobar.html:

<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <h1 style="color: green;">Hello</h1>
    <h1 style="color: blue;">World</h1>    
  </body>
</html>

Отвечая строго на вопрос, заданный Гаганом

Как браузер должен отображать CSS, который не является смежным?

  1. Предполагается ли создать некоторую структуру данных, используя все стили CSS на странице, и использовать ее для рендеринга?
  2. Или он использует информацию о стиле в том порядке, в котором он видит?

(цитата адаптирована)

Для более точного ответа я предлагаю Google эти статьи:

  • Как работают браузеры: за кулисами современных веб-браузеров
  • Render-Tree Строительство, макет и краски
  • Что значит «визуализировать» веб-страницу?
  • Как работает рендеринг в браузере - негласно
  • Рендеринг - Стандарт HTML
  • 10 рендеринга - HTML5
Игорь Сантос
источник
+1 Хорошая идея, включая теги сценария и использование javascript для добавления CSS, совершенно законного HTML для тупых редакторов WYSIWYG CMS
djolf
1

Поскольку этот HTML-код недействителен, он никак не влияет на результат ... это просто означает, что HTML-код придерживается стандарта (только для организационных целей). Ради достоверности это можно было бы написать так:

<html>
<head>
<style type="text/css">
  p.first {color:blue}
  p.second {color:green}
</style>
</head>
<body>
<p class="first" style="color:green;">Hello World</p>
<p class="second" style="color:blue;">Hello World</p>

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

Г. Бикхэм
источник