Використання тегів <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 на сторінці і використовувати це для візуалізації?

Або він відображається, використовуючи інформацію про стиль у порядку, який він бачить?


2
Я б сказав, що це невизначена поведінка, оскільки це недійсний HTML. Для отримання додаткової інформації, які елементи є дійсними, а які не: en.wikipedia.org/wiki/HTML_element
Фелікс Клінг

2
Покидаючи цю проблему, погана практика змішувати CSSі HTML.
0x2D9A3

1
@ 0x2D9A3 Не обов'язково правда. <head>
Надіслати

@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.
Альберт Вірш

61

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

(Примітка. Це так "станом на сьогодні", але оскільки не існує версій, посилання можуть стати недійсними в будь-який момент без попередження або контролю. Якщо ви не бажаєте посилатися на його окремі джерела, які здійснюються в GitHub, ви, як правило, не можете довше робити стійкі посилання на новий офіційний стандарт HTML , AFAIK. Будь ласка, виправте мене, якщо існує канонічний спосіб зробити це правильно.)

ЗАБЕЗПЕЧЕНІ ДОБРІ НОВИНИ

Так, STYLEнарешті, діє в BODYHTML5.2! scopedпішов теж.)

З специфікацій W3C ( смакуйте останній рядок! ):

4.2.6. Елемент стилю

...

Контексти, в яких цей елемент можна використовувати:

Там, де очікується вміст метаданих.

В елементі елемента, що є дочірнім елементом голови.

В тілі, де очікується вміст потоку.


МЕТИЧНА БІЛОТА:

Сам факт, що, незважаючи на збитки від "війни в браузері", нам все-таки довелося продовжувати розвиватися проти двох смішно конкуруючих "офіційних" стандартів "HTML" (цитати 1 standard + 1 standard < 1 standard), означає, що підхід до "здорового глузду в траншеях" означає, що підхід до веб-розробка ніколи не перестала застосовуватись.

Це, нарешті, може змінитися зараз, але, посилаючись на загальноприйняту мудрість: веб-автори / розробники, а отже, в свою чергу, браузери повинні врешті вирішити, що має бути (а що не повинно) бути в специфікаціях, коли немає вагомих причин проти того, що вже зроблено в реальність. І більшість браузерів вже давно підтримується STYLEв BODY(в тій чи іншій формі , см , наприклад , в scoped. Attr) (який, незважаючи на властиві продуктивності (і , можливо , інші) штрафи ми . Повинні вирішити , платити чи ні, а НЕ специфікації). Отже, для одного я продовжую робити ставку на них, і не збираюся здавати надію. ;) Якщо WHATWG має таку ж повагу до реальності / авторів, як вони заявляють, вони можуть просто в кінцевому підсумку зробити тут те, що зробив W3C.


3
Я читаю характеристики, але не розумію. Чи можете ви навести приклад коду styleблоку у програмі, bodyщо підтверджує?
Френк Конійн

3
@FrankConijn: Добре, що все змінилось, відповідь оновлено! Це дійсно заплутано. Як характеристики 5.2, так і 5,3 W3C трактуються STYLEяк метадані та вміст потоку, але остання WHATWG "жива" специфікація розповідає стару, нудну "метадані" лише історію (дозволяючи це лише в HEAD). І, щоб додати образу шкоди, валідатор W3C, схоже, слідує за смаком WHATWG. Я ще не вирішив, чи слід сміятися чи плакати, але впевнено вирішив особисто "помилитися" зі справою "браузери + W3C - валідатор", і дозволити STYLE в тілі. (До речі, не забувайте: насправді ми повинні бути головним джерелом стандарту .)
Sz.

Я дійсно думаю, що вони стрибали акули за допомогою цього лайна, вони в основному не залишають іншого вибору, крім використання в стилях ліній, якщо ви хочете динамічно встановити властивість фонового зображення в шаблонній системі. Це було набагато менш інвазивно, щоб кинути програмно створений блок стилів трохи вище вашого HTML-виводу.
GovCoder

32

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

Перегляньте джерела сторінок із cnn.com, nytimes.com, huffingtonpost.com, вашої найближчої газети великого міста тощо. Усі вони роблять це.

Якщо є вагома причина помістити додатковий розділ <style> десь у тілі - наприклад, якщо ви включаєте () різні та незалежні елементи сторінки в режимі реального часу, і кожен має вбудований <style> власний та організація буде чистішою, модульнішою, зрозумілішою та більш досяжною - я кажу просто кулю кулі. Звичайно, було б краще, якби ми могли мати "локальний" стиль з обмеженою сферою дії, як локальні змінні, але ви працюєте з HTML, який у вас є, а не з HTML, який ви хочете або хочете мати згодом.

Звичайно, є можливі недоліки та хороші (якщо не завжди переконливі) причини слідувати православ’ю, як це пояснили інші. Але для мене це все більше схоже на продумане використання <style> в <body>, вже перейшло в мейнстрім.


1
Прагматизм FTW!
Варюяма

1
Так, ви праві. Як приклад, я використовую тег <style> в <body> всередині мого плагіна. Чому, тому що це найпростіший спосіб стильного вмісту плагінів. Але одного разу всі класи css - це унікальні дані для моїх плагінів.
Авіртум

7

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

Тестовано під останніми версіями FF та Google Chrome під Fedora, та FF, Opera, IE та Chrome під XP.


6

Я думаю, це залежатиме від браузера до браузера: правила глобального відображення, ймовірно, будуть оновлені, коли браузер проходитиме код.

Такі зміни в правилах глобального відображення можна побачити іноді, коли зовнішній аркуш стилів завантажується із затримкою. Щось подібне може трапитися тут, але за такої короткої послідовності, що насправді не вийде.

Це все одно не дійсний HTML, тому я б сказав, що думати про це марно. <style>Теги належать до headрозділу сторінки.


5

Як говорили інші, це неправдивий HTML, оскільки теги стилів належать до голови.

Однак більшість браузерів дійсно не застосовують цю перевірку. Замість цього, як тільки документ завантажується, стилі об'єднуються та застосовуються. У цьому випадку другий набір стилів завжди буде перекривати перший, оскільки вони були останніми визначеннями.


5

<style>Належить тег в <head>секції, окремо від всього вмісту.

Список літератури: W3C Specs та W3Schools


52
Не стосується питання. І ці жорсткі вказівки перекриті реальністю. Є МНОГО випадків, коли авторам неможливо визначити / включити їх стиль у голову html.
Хав'єр

3
Це могло бути правдою в 2010 році, але це далеко не прийнятна відповідь.
Ісаак Любов

3

У вашому прикладі браузер не повинен "робити" нічого. HTML недійсний. Або запускається відновлення помилок, або аналізатор робить його як слід.

У дійсному екземплярі кілька таблиць стилів просто трактуються як такі, що з’являються одна за одною, каскад обчислюється як нормальний.


2

Я думаю, це може бути проблемою щодо обмеженого контексту, наприклад, редакторів WYIWYG у веб-системі, що використовується користувачами , які не програмують , що обмежує можливості дотримання стандартів. Іноді (наприклад, TinyMCE), це lib, що вміщує ваш вміст / код всередині textareaтегу, який видається редактором як великий divтег. І іноді це може бути стара версія цих редакторів.

Я припускаю, що:

  1. ці непрограмістські користувачі не мають відкритого каналу з адміністраторами системи (або webdevs установи), щоб попросити включити деякі правила CSS у систему stylesheets. Власне, для адміністраторів (або webdevs) було б недоцільно, враховуючи кількість запитів у тому сенсі, які вони мали б.
  2. ця система застаріла і досі не підтримує новіші версії HTML.

У деяких випадках без styleправил використання це може бути дуже поганим дизайнерським досвідом. Отже, так, ці користувачі потребують налаштування. Гаразд, але які рішення були б у цьому сценарії? Розглядаючи різні способи вставлення CSS на htmlсторінку, я думаю, що ці рішення:


1-й варіант: запитайте свою систему

Попросіть свого системного адміністратора включити деякі правила 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 , як зазначено вище, щодо рішення 2-го варіанту. Буде створено новий 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 наступні статті:

  • Як працюють браузери: за кадром сучасних веб-браузерів
  • Візуалізація конструкції, макет і фарба
  • Що означає "візуалізація" веб-сторінки?
  • Як працює візуалізація браузера - поза кадром
  • Візуалізація - стандарт 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>

Я здогадуюсь, що браузер застосовує останній стиль, на який він стикається.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.