Как изолировать div от общедоступных стилей CSS?
У меня есть код, например, здесь, в html
<html>
<body>
<img src='an image source'/>
<h1>Hi it test</h1>
<div id='mydiv'>
<img src='an image source'/>
<h1>Hi it test</h1>
</div>
</body>
</html>
если я использовал следующий код css для его стилизации:
img{
width:100px;
height:100px;
}
h1{
font-size:26px;
color:red;
}
возникает вопрос: как я могу предотвратить и изолировать теги внутри тега div mydiv от стиля в стиле общих тегов?
Ответы
Ответ 1
CSS Cascading и Inheritance Level 3 представляет сокращенное свойство all
и ключевое слово unset
, которое вместе позволит вам достичь этого удобно.
Например, если автор указывает all: initial
на элемент, он будет заблокировать все наследование и reset все свойства, как будто никаких правил появился на уровне автора, пользователя или пользователя-агента каскада.
Это может быть полезно для корневого элемента "виджета", включенного в страницу, которая не хочет наследовать стили внешней страницы. Обратите внимание, однако, что любой стиль по умолчанию, примененный к этому элементу (такой как, например, display: block
из таблицы стилей UA на блочных элементах как <div>
) также будет сбрасываться.
Вам нужно применить all: initial
к вашему div и all: unset
его потомкам:
#mydiv {
all: initial; /* blocking inheritance for all properties */
}
#mydiv * {
all: unset; /* allowing inheritance within #mydiv */
}
Вы можете использовать класс в своем div вместо id, так что любые правила, которые вы пишете для стилирования его потомков, не должны соответствовать или бить высокую специфичность, используемую в этом правиле.
Чтобы быть действительно безопасным, вы можете также заблокировать стили для потенциальных потомков псевдоэлементов:
#mydiv::before,
#mydiv::after,
#mydiv *::before,
#mydiv *::after {
all: unset;
}
В качестве альтернативы, для более широкой поддержки браузера вы можете вручную сделать то, что all
делает, установив все известные свойства CSS (не забудьте префиксные версии):
#mydiv {
/*
* using initial for all properties
* to totally block inheritance
*/
align-content: initial;
align-items: initial;
align-self: initial;
alignment-baseline: initial;
animation: initial;
backface-visibility: initial;
background: initial;
...
}
#mydiv::before,
#mydiv::after,
#mydiv *,
#mydiv *::before,
#mydiv *::after {
/*
* using inherit for normally heritable properties,
* and initial for the others, as unset does
*/
align-content: initial;
align-items: initial;
align-self: initial;
...
color: inherit;
...
}
Вы можете поощрять поддержку браузера для стенографического свойства all
и отслеживать его принятие с помощью этих ссылок на проблемы:
Текущая информация о поддержке браузера для all
сокращенного свойства доступна здесь.
Ответ 2
Вы не можете технически, как CSS должен работать. Если существует какой-либо стиль, определенный для
div в вашей таблице стилей, он будет применяться ко всем элементам div.
Несколько вещей, которые вы можете попробовать, это не использовать стиль с именем тега, а вместо этого дать имя класса и дать объявление стиля классу. так что вы можете убедиться, где все стили будут идти.
ИЛИ. если вы хотите, чтобы какой-то определенный тег Div не имел стиля, в то время как другие Divs имели. вы всегда можете reset дать несколько разных имен классов или id и reset объявления стилей
Ответ 3
Старый вопрос, но с момента принятого ответа все немного изменилось. Теперь для решения этой проблемы есть ключевое слово, рекомендованное CSSWG под названием revert
, которое лучше подходит, чем initial
и unset
, поскольку сбрасывает свойство элемента к значению, определенному в таблице стилей агента пользователя, а не к начальному значению свойства, независимо от того, какой элемент он использовал. Так, например, для div
внутри #mydiv
будет установлено отображение block
, как мы и ожидали, а не inline
.
Вы должны сделать это:
#mydiv,
#mydiv::before,
#mydiv::after,
#mydiv *
#mydiv *::before,
#mydiv *::after {
all: revert;
}
К сожалению, revert
не поддерживается ни одним браузером, кроме Safari (для Mac и iOS) на момент написания.
Есть также кое-что еще, чтобы принять во внимание относительно принятого ответа. Если вы хотите стилизовать что-либо внутри #mydiv
, вам нужно сделать это с помощью селектора, который, по крайней мере, столь же специфичен, как и тот, который вы использовали для отмены или отмены всего, в противном случае он будет переопределен этим правилом, даже если он появится после это в CSS.
Поэтому вам нужно сделать что-то вроде этого (обратите внимание на #mydiv
, который повышает специфичность правил):
#mydiv p {
margin-top: 20px;
}
#mydiv .bg-black {
background-color: black;
}
// etc.
Ответ 4
Одна вещь, которая может быть полезна, - это синтаксический селектор CSS, который доступен во всех браузерах, включая IE7+. Это позволяет применять стиль, который не каскадируется на детей. Например, в вашем коде вы можете использовать этот CSS:
body > img {
width:100px;
height:100px;
}
body > h1 {
font-size:26px;
color:red;
}
И этот CSS применим только к элементам непосредственно в элементе BODY.
Ответ 5
iframe также является хорошим решением для изоляции стилей, если оно не усложняет другую бизнес-логику. Кроме того, это может быть сделано в чистом JavaScript и может работать в старых браузерах.
const HTMLToIsolate = '...' // get your div tag as HTML string
const parentContainerRef = document.body; // or something else
const newIframe = document.createElement('iframe');
// set height & width to 100% and remove borders for newIframe
parentContainerRef.appendChild(newIframe)
newIframe.contentWindow.document.open('text/html', 'replace');
newIframe.contentWindow.document.write(HTMLToIsolate);
newIframe.contentWindow.document.close();
// bonus to remove scroll bars by setting proper iframe height
newIframe.addEventListener('load', function onIFrameLoad(e) {
const iframeBody = this.contentDocument.querySelector("body");
this.style.height = '${iframeBody.scrollHeight}px';
});
Это прекрасно сработало, когда мне пришлось встраивать сложный HTML файл в мою веб-страницу, извлеченную удаленно, без предупреждения MixedContent и без родительских стилей HTML, перекрывающих встроенный HTML. Спасибо https://benfrain.com/sandbox-local-htmlcss-code-snippets-inside-iframe-style-guidespattern-libraries/ за эту прекрасную идею!
Хотя хитрость CSS #mydiv * { all: unset }
, как предлагается в принятом решении здесь, работает, она перестала быть сложной операцией браузера, поскольку на моей странице было много узлов DOM.