Перемикач стилів на чистому CSS за допомогою :checked

1

Від автора: ще кілька років тому розробники вже могли створювати безліч проектів з допомогою одного лише CSS без застосування JavaScript. Але сьогодні CSS настільки зміцнів, що можна писати справді дивовижні речі без єдиної рядки JavaScripta’а. Швидше за все ви вже читали статті на тему «способи на чистому CSS», в яких демонструється міць каскадних таблиць стилів.

Коли справа стосується чисто CSS методів, ми не можемо ігнорувати псевдоклас :checked, його я і буду використовувати в цій статті. Звичайно, я не перший, хто пише про цей спосіб, вже велися досить великі суперечки з приводу використання елементів форми в якості заміни JavaScript’у. Наприклад, стаття з Adobe Louis Lazaris і це чудове слайд шоу від Ryan Seddon.

Застосування :checked

Якщо коротко, то :checked застосовується до будь радиокнопке або чекбоксу і позначає стан обраного елемента. Користувач може змінити стан елементів, поставивши галочку на інший чекбокс або вибравши іншу радіокнопку.

Перед тим, як піти далі, давайте подивимося на демо, щоб зрозуміти, що ми будемо створювати у цьому уроці:

А тепер можна продовжувати.

Створення блоку налаштувань

У демо ви повинні були помітити іконку шестерні і те, як при натисканні на неї з’являється блок з параметрами. Перед поясненням того, який HTML і CSS код лежить за цим, погляньте на наступний код:

/* нам не потрібно, щоб input’и було видно, потрібні тільки лейбли */
input[type=»checkbox»], input[type=»radio»] {
position: absolute;
visibility: hidden;
}
.settings-box-element {
z-index: 10;
}

Оскільки нам необхідно відображати тільки лейбли, код вище якраз і ховає чекбокси і радіокнопки. Більше того, всім лейблам присвоєно клас settings-box-element властивості z-index , нам потрібно, щоб ці поля завжди залишалися поверх сторінки.

Тепер ми можемо розібратися в коді блоку налаштувань. Почнемо з кнопки-шестерні. Її код:

HTML

CSS

.settings-btn + label {
position: fixed;
top: 130px;
right: 0;
display: block;
width: 35px;
color: #e83737;
text-align: center;
background: #fff;
cursor: pointer;
}

Якщо ви читали хоч одну або навіть дві статті про те, як використовувати елементи форми, щоб не застосовувати JavaScript, то ви вже знаєте, що потрібно використовувати input’и разом з лейблами. А значить, якщо хоч один видалити, то нічого не спрацює. У нас є чекбокс з id=»settings-btn» і лейбл з атрибутом for, що вказує на значення id. Також я додав клас settings-btn, щоб використовувати його потім.

В CSS лейбл пропонується фіксовано position: fixed з відповідними значеннями top, right. Слідом йде білий бокс, нібито містить кнопки:

HTML

CSS

.buttons-wrapper {
position: fixed;
top: 130px;
right: -200px; /* має збігатися зі значенням ширини */
width: 200px;
height: 240px;
background: #fff;
}

Наш бокс це порожній DIV з класами «buttons-wrapper» і «settings-box-element». Як я вже говорив вище, останній клас в основному використовується для додавання z-index. «buttons-wrapper» потрібен щоб стилізувати сам DIV. І, як ви можете помітити, боксу задана ширина в 200px і висота в 240px. Це щоб вмістилися 5 кнопок, можете подивитися демо. Також задано позиціонування fixed і відповідні значення top right. Єдине, що варто відзначити, що значення властивості right повинна збігатися з шириною блоку, але з від’ємним значенням (щоб блок зник з поля зору).

Тепер поглянемо на код залишилися 5 кнопок. В коментарях вказаний фон, до якого відноситься кнопка:

Light Background
Dark Background
Background Image
Pattern Background
Hide/Show content
.layout-buttons {
display: block;
width: 150px;
padding: 10px 0;
text-align: center;
border: 2px solid black;
box-sizing: border-box;
font-size: 0.875 em;
cursor: pointer;
}
.light-layout + label {
position: fixed;
top: 140px;
right: -150px;
}
.dark-layout + label {
position: fixed;
top: 185px;
right: -150px;
}
.image-layout + label {
position: fixed;
top: 230px;
right: -150px;
}
.pattern-layout + label {
position: fixed;
top: 275px;
right: -150px;
}
.hide-show-content + label {
position: fixed;
top: 320px;
right: -150px;
}

Зверніть увагу на те, що перший чекбокс вже відзначений атрибутом «checked». Ми використовуємо його за замовчуванням.
Кожен инпут має свій id, а кожен свій лейбл for, і вони збігаються між собою. І ви можете знати, а може і ні, але весь секрет з атрибутом for в тому, що, якщо ми його використовуємо, то при натисканні на лейбл з атрибутом for автоматично вибирається чекбокс або радіокнопка. Ось чому ми можемо використовувати псевдоклас :checked.

Всім лейблам присвоєний клас «layout-buttons». Він використовується для додавання базових і загальних стилів, як ширина, padding, border і т. д. Інші класи використовуються для індивідуальної стилізації. Як ви могли помітити, іконки для шестерні і для білого боксу використовується фіксоване позиціонування з певними значеннями top, right. А значення top для кожного лейблу більше на 45px, ніж у попереднього; це потрібно, щоб кнопки стали в стовпець, не налягаючи один на одного. Також зверніть увагу на те, що значення right дорівнює ширині кнопок, тільки з від’ємним значенням.

Залишилася остання частина CSS коду:

input[type=»radio»]:checked + label {
background: #e83737;
color: #fff;
border-color: #e83737;
}

Ці стилі використовуються для заміни стилів за замовчуванням для лейблів з вибраними радіокнопками (у нас їх 4). Я використовував суміжні селектори, щоб визначити з усіх инпутов радіокнопки. Властивостями присвоєно значення #e83737, колір #fff.

Нічого понад складного. Елементи, що залишилися, обгорнуті DIV ом.

Cool stuff with CSS only!

Lorem ipsum dolor sit amet…

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

Отже, основний контент обгорнутий у div з класом class=»main-wrapper». І, як ви побачите пізніше, щоб змінити стилі цього DIV а, нам потрібно буде написати щось схоже:

input[type=»checkbox»]:checked ~ main-wrapper {
/* стилі */
}

Щоб вибрати головний DIV ми використовуємо селектор ~.

Клік по іконці налаштувань

По кліку повинен з’являтися блок налаштувань. Наступний Код дозволяє це зробити:

.settings-btn:checked + label {
right: 200px; /* співпадає з шириною .buttons-wrapper */
}
.settings-btn:checked ~ .buttons-wrapper {
right: 0;
}
.settings-btn:checked ~ .layout-buttons {
right: 30px;
}

Коли користувач клікає на іконку налаштувань, буде обраний чекбокс з id=»settings-btn». Після натискання відбувається наступне:

Селектор суміжних елементів (+) змушує лейбли виїжджати на 200px після того, як будуть обрані чекбокси.

Селектор ~ змушує виїжджати елементи з класами «buttons-wrapper» і «layout-buttons» до значень 0 і 30px відповідно з правого краю.

Обидва селектора в нашому прикладі незамінні, і без них нічого б не працювало.

Заміна фону

Я нагадаю вам HTML радіо кнопок:

Light Background

Ми будемо змінювати фон у елемента .main-wrapper. CSS код:

.light-layout:checked ~ .main-wrapper {
background: #eaeaea;
}
.dark-layout:checked ~ .main-wrapper {
background: #494949;
}
.image-layout:checked ~ .main-wrapper {
background: url(image url) no-repeat center 0 fixed;
}
.pattern-layout:checked ~ .main-wrapper {
background: url(images/pattern1.png) repeat;
}

По HTML коду ми маємо 4 набору инпутов типу type=»radio» і 4 лейблу. По кліку на будь лейбл буде обраний пов’язаний з ним инпут, а значить спрацює псевдоклас :checked. Потім в залежності від обраного лейблу буде застосований один з чотирьох стилів до блоку-обгортці.

Ховаємо/показуємо контент

Я використовую чекбокс для відображення та приховання контенту:

Hide/Show content
.hide-show-content:checked ~ .main-wrapper .content {
display: none;
}

В цьому випадку, коли користувач клацає на відповідний лейбл, тим самим вибираючи чекбокс, ми даємо команду браузеру вибрати елемент з класом class=»content» і встановити значення display: none.

Висновок

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