Я пытаюсь создать плавный переход для всех CSS правил, связанных с цветами (background-color, border-color, color ...), когда пользователь меняет тему моего сайта, добавляя transition
Править для всех элементов одновременно с помощью селектора *
, который я удаляю после завершения перехода, поэтому другие правила transition
остаются такими же, какими они должны быть после завершения перехода темы.
Отлично работает на Firefox, но в Google Chrome (v81) кажется, что правило color
, примененное к телу, немного задерживается (вы также можете увидеть это на событии transitionend
):
(Примечание: когда я ссылаюсь на переход color
, речь идет о правиле CSS color
, которое применяется к тексту, я не ссылаюсь на цвет тела или другие)
document.querySelector('button').addEventListener('click', () => {
if (document.documentElement.classList.contains('dark-theme')) {
document.documentElement.classList.remove('dark-theme');
}
else {
document.documentElement.classList.add('dark-theme');
}
});
document.addEventListener('transitionstart', (event) => {
if (event.propertyName === 'color') {
if (event.target.tagName === 'H1') {
document.querySelector('.h1-transition').textContent = 'start';
}
else if (event.target.tagName === 'BODY') {
document.querySelector('.body-transition').textContent = 'start';
}
}
});
document.addEventListener('transitionend', (event) => {
if (event.propertyName === 'color') {
if (event.target.tagName === 'H1') {
document.querySelector('.h1-transition').textContent = 'end';
}
else if (event.target.tagName === 'BODY') {
document.querySelector('.body-transition').textContent = 'end';
}
}
});
body {
padding: 0;
margin: 0;
background-color: #fff;
color: #000;
font-family: sans-serif;
text-align: center;
}
:root.dark-theme body {
background-color: #333;
color: #fff;
}
:root * {
transition: all 5s ease-in-out;
}
<h1>Some text</h1>
<button>Change theme</button>
<p>
Body's color transition :
<span class="body-transition">none</span>
</p>
<p>
H1's color transition :
<span class="h1-transition">none</span>
</p>
Вот мой окончательный код, в который я добавляю правило перехода, только когда нажимаю кнопку, а затем удаляю его, когда тело завершило свою работу. переход:
function themeTransitionEnd(event) {
if (event.target === document.body) {
document.documentElement.removeEventListener('transitionend', themeTransitionEnd);
document.documentElement.classList.remove('theme-transition');
}
}
function invertTheme() {
document.documentElement.addEventListener('transitionend', themeTransitionEnd);
document.documentElement.classList.add('theme-transition');
if (document.documentElement.classList.contains('dark-theme')) {
document.documentElement.classList.remove('dark-theme');
}
else {
document.documentElement.classList.add('dark-theme');
}
}
document.querySelector('button').addEventListener('click', invertTheme);
/* TRACK TRANSITIONS FOR DEBUG PURPOSE */
document.addEventListener('transitionstart', (event) => {
if (event.propertyName === 'color') {
if (event.target.tagName === 'BODY') {
document.querySelector('.body-transition').textContent = 'start';
}
else if (event.target.tagName === 'H1') {
document.querySelector('.h1-transition').textContent = 'start';
}
else if (event.target.tagName === 'H2') {
document.querySelector('.h2-transition').textContent = 'start';
}
}
});
document.addEventListener('transitionend', (event) => {
if (event.propertyName === 'color') {
if (event.target.tagName === 'BODY') {
document.querySelector('.body-transition').textContent = 'end';
}
else if (event.target.tagName === 'H1') {
document.querySelector('.h1-transition').textContent = 'end';
}
else if (event.target.tagName === 'H2') {
document.querySelector('.h2-transition').textContent = 'end';
}
}
});
/* LIGHT THEME */
body {
padding: 0;
margin: 0;
background-color: #fff;
color: #000;
font-family: sans-serif;
transition: none;
text-align: center;
}
h2 {
color: purple;
}
/* DARK THEME */
:root.dark-theme body {
background-color: #444;
color: #fff;
}
:root.dark-theme h2 {
color: red;
}
/* TRANSITIONS */
:root.theme-transition * {
transition: all 5s linear !important;
}
<h1>Some text using body's color rule</h1>
<h2>Some text using its own color rule</h2>
<button>Invert theme</button>
<p>
Body's color transition :
<span class="body-transition">none</span>
</p>
<p>
H1's color transition :
<span class="h1-transition">none</span>
</p>
<p>
H2's color transition :
<span class="h2-transition">none</span>
</p>
Переход 5s предназначен для лучшего понимания проблемы, и, как вы можете видеть, цвет Н2 медленно меняется с фиолетового на красный и наоборот , но из-за задержки на цвете тела цвет H1 внезапно меняется, и transitionend
никогда не срабатывает.
Меня не волнует, что transitionend
событие не сработает, это только для того, чтобы отладка, но я не использую его, но задержка цветового перехода тела довольно некрасива.
Это ошибка в Google Chrome, или она предназначена? И как я могу это исправить?