Текущая версия shadowDOM требует, чтобы вы разместили свой CSS внутри shadowDOM.
Большинство CSS довольно малы и добавляют всего несколько байтов к нескольким сотням байтов в каждом элементе. Некоторые из самых крупных, которые я видел, добавляют около 2 КБ CSS в каждую копию. Но это все еще очень мало по сравнению с данными, представленными в структуре DOM.
Есть несколько вещей, которые могут просочиться извне, например информация о шрифте, но их не так много.
Вот несколько способов повлиять на внешность:
1. Переменные CSS
CSS-переменная позволяет вам установить для переменной значение, которое используется в CSS, будь то в shadowDOM или нет.
2. Атрибуты
Атрибуты могут быть захвачены и перенесены в shadowDOM CSS. У меня есть несколько компонентов, которые используют атрибут для определения темы.
3. Свойства
Свойства также могут быть взяты и применены к внутреннему CSS.
Есть и другие способы обсуждения, но их придется подождать до V2.
class MyEL extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'}).innerHTML = `
<style>
.outer {
color: var(--myColor, 'black');
</style>
<div class="outer">
<h4>Title</h4>
<slot></slot>
</div>`;
}
static get observedAttributes() {
return ['bgcolor'];
}
attributeChangedCallback(attrName, oldVal, newVal) {
if (oldVal !== newVal) {
this.shadowRoot.querySelector('.outer').style.backgroundColor = newVal;
}
}
get border() {
return this.shadowRoot.querySelector('.outer').style.border;
}
set border(value) {
this.shadowRoot.querySelector('.outer').style.border = value;
}
}
customElements.define('my-el', MyEL);
setTimeout(() => {
document.querySelector('my-el').border = '2px dashed blue';
},1000);
const btn = document.getElementById('toggle');
let color = '';
btn.addEventListener('click', () => {
color = color === '' ? 'white' : '';
document.querySelector('my-el').style.setProperty('--myColor', color);
});
<my-el bgcolor="red"></my-el>
<hr/>
<button id="toggle">toggle</button>
ОБНОВЛЕНО
Как указано в моем комментарии ниже, есть несколько правил CSS, которые проникнут в shadowDOM, если они не будут перезаписаны. Вещи, которые проникают, - это color
, background
, font
и другие вещи, связанные с ними.
Этот код показывает пример того, как они проникают:
customElements.define('css-test', class extends HTMLElement {
constructor() {
super();
var shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = `<h1>Header</h1>
<p>This is a <strong>strong</strong> string</p>
<p>This is <em>emphasis<em>.`;
}
});
const styles = document.createElement('style');
styles.textContent = `
* {
background-color: #900;
border: 1px solid #9876;
border-radius: 5px;
box-sizing: border-box;
box-shadow: 0 0 4px #0005;
color: #fff;
font: 24px Tahoma;
margin: 20px;
padding 20px;
text-align: center;
text-decoration: #ffd wavy underline;
text-shadow: 3px 3px 3px #0008;
transform: rotate(30deg);
}`;
function toggleCss(evt) {
if(styles.parentElement) {
styles.remove();
}
else {
document.body.appendChild(styles);
}
}
const toggleEl = document.getElementById('toggle');
toggleEl.addEventListener('click', toggleCss);
<css-test></css-test>
<hr/>
<button id="toggle">Toggle CSS</button>
Когда вы нажмете на кнопку-переключатель, вы увидите, что все меняет цвет, цвет фона, шрифты и т. Д. Но что-то вроде поворота происходит только с компонентом, а не с подчиненными элементами внутри компонента. И это хорошо. Представьте, что пользователь может вращать элементы внутри вашего компонента ... Весь ваш компонент сломается.
Я искал хорошую статью, в которой рассказывалось бы обо всех вещах, которые проникают, но не мог ее найти. Я видел это раньше, но забыл добавить его в закладки. Так что, если кто-то найдет эту статью, добавьте ее в комментарии ниже.
Вот тот же код, приведенный выше, с несколькими переопределенными элементами, чтобы вы могли видеть, как ваш компонент может переопределить то, что делается снаружи:
customElements.define('css-test', class extends HTMLElement {
constructor() {
super();
var shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = `<style>
:host * {
background: white;
color: yellow;
font-size: 14px;
}
</style><h1>Header</h1>
<p>This is a <strong>strong</strong> string</p>
<p>This is <em>emphasis<em>.`;
}
});
const styles = document.createElement('style');
styles.textContent = `
* {
background-color: #900;
border: 1px solid #9876;
border-radius: 5px;
box-sizing: border-box;
box-shadow: 0 0 4px #0005;
color: #fff;
font: 24px Tahoma;
margin: 20px;
padding 20px;
text-align: center;
text-decoration: #ffd wavy underline;
text-shadow: 3px 3px 3px #0008;
transform: rotate(30deg);
}`;
function toggleCss(evt) {
if(styles.parentElement) {
styles.remove();
}
else {
document.body.appendChild(styles);
}
}
const toggleEl = document.getElementById('toggle');
toggleEl.addEventListener('click', toggleCss);
<css-test></css-test>
<hr/>
<button id="toggle">Toggle CSS</button>
person
Intervalia
schedule
17.04.2019