Колись, роблячи нову тему для свого сайту, я довго бродив по форумах, як сліпе кошеня, у пошуках способу запам'ятати вибір відвідувача: темний дизайн чи світлий. Перепробував купу вбудованих методів WordPress, а закінчилося все маленьким скриптом на JavaScript. Відтоді браузери навчилися багато чого нового, тож розповім, як сьогодні просто і правильно записати, прочитати й видалити cookies на будь-якому сайті, без прив'язки до CMS.
Що таке cookies
Cookie (кука, «реп'яшок») – це маленький шматочок тексту на кшталт theme=dark, який сайт залишає у браузері відвідувача. Головна особливість: браузер сам відправляє всі куки сайту на сервер з кожним запитом. Тож сервер ще до того, як віддасть сторінку, знає, що ти обрав/ла темну тему, мову чи вже закрив/ла набридливе повідомлення.
Розмір у кук невеликий, близько 4 КБ на одну, тому зберігають у них лише короткі значення, а не цілі масиви даних.
Як записати cookie в JavaScript
З JavaScript до кук доступ через document.cookie. Виглядає воно трохи дивно: присвоєння не затирає всі куки, а додає чи оновлює одну:
document.cookie = 'theme=dark; max-age=31536000; path=/; SameSite=Lax; Secure';
Після назви й значення через крапку з комою йдуть параметри:
- max-age – скільки секунд жити куці. 31536000 – це рік. Якщо параметра немає, кука зникне, щойно відвідувач закриє браузер.
- path=/ – кука доступна на всіх сторінках сайту, а не лише в поточній теці. Без нього кука, записана на сторінці
/blog/post, не буде видна на головній, і ти довго шукатимеш, чому нічого не працює. Я шукав 🙂 - SameSite=Lax – браузер не надсилатиме куку, коли запит іде з чужого сайту (крім звичайного переходу за посиланням). Це захист від частини атак, і сучасні браузери й так ставлять
Laxза замовчуванням, але краще вказати явно. - Secure – кука передається лише через HTTPS. На робочому сайті ставлю завжди, а от на локальному сервері без HTTPS її доведеться прибрати, інакше кука не запишеться.
Три зручні функції
Щоразу писати такий рядок незручно, тому я тримаю під рукою три маленькі функції:
function setCookie(name, value, days = 365) {
document.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value)
+ '; max-age=' + days * 86400
+ '; path=/; SameSite=Lax; Secure';
}
function getCookie(name) {
const prefix = encodeURIComponent(name) + '=';
const found = document.cookie.split('; ').find(item => item.startsWith(prefix));
return found ? decodeURIComponent(found.slice(prefix.length)) : null;
}
function deleteCookie(name) {
document.cookie = encodeURIComponent(name) + '=; max-age=0; path=/';
}
Що тут варто знати:
encodeURIComponent()потрібен, щоб у значенні можна було зберегти пробіли, кому чи кирилицю, – без нього крапка з комою в тексті просто «зламає» куку.document.cookieпри читанні повертає всі куки одним рядком на кшталтtheme=dark; lang=uk, тож ми розбиваємо його і шукаємо потрібну.- Видалити куку можна лише одним способом – записати її з
max-age=0. Іpathмає бути той самий, що й під час запису, інакше браузер вважатиме це іншою кукою.
Користуватися ними просто:
setCookie('theme', 'dark'); // запам'ятати на рік
getCookie('theme'); // 'dark' або null
deleteCookie('theme'); // забути
Приклад: запам'ятати тему сайту
Повернімося до моєї старої задачі з темним і світлим дизайном. Кнопка в розмітці:
<button class="theme-switch" type="button">Змінити тему</button>
Скрипт перемикає клас dark на тезі <html> і записує вибір у куку:
document.querySelector('.theme-switch').addEventListener('click', () => {
const isDark = document.documentElement.classList.toggle('dark');
setCookie('theme', isDark ? 'dark' : 'light');
});
А тепер найцікавіше, заради чого тут варто брати саме куки. Оскільки браузер надсилає їх на сервер, сайт на PHP може одразу віддати сторінку з потрібним класом:
<?php $theme = ($_COOKIE['theme'] ?? '') === 'dark' ? 'dark' : ''; ?>
<html lang="uk" class="<?= $theme ?>">
І ніякого блимання світлою сторінкою перед тим, як спрацює скрипт. Зверни увагу: значення з куки я не вставляю в HTML як є, а лише порівнюю. Відвідувач може записати в куку що завгодно, тож довіряти їй сліпо не можна.
У своїх темах WordPress підключай такий скрипт через wp_enqueue_script() – як це робиться, я показував у статті про файл functions.php. А як працює classList.toggle(), детально розібрано в статті як змінити клас елемента в JavaScript.
Cookies чи localStorage?
Для того ж темного режиму можна взяти і localStorage – про це я писав у статті темний режим на сайті за допомогою localStorage. Як вибрати:
- Cookies – коли значення потрібне серверу: тема, мова, згода на щось. Але вони їдуть з кожним запитом, тож пхати туди багато даних не варто.
- localStorage – коли дані потрібні лише скрипту в браузері: налаштування інтерфейсу, чернетка форми, кеш. Місця там набагато більше, і на сервер нічого не відправляється.
Є й новіший спосіб працювати з куками – cookieStore, з нормальними методами get(), set() і delete(). Він асинхронний і значно зручніший, але старі браузери його не знають, тож для простих задач функцій вище цілком досить.
А що зі згодою на cookies?
Ті самі банери «Цей сайт використовує cookies» з'явилися через європейські правила приватності. Якщо коротко: кука, яка просто запам'ятовує вибір теми чи мови, потрібна для роботи сайту, і окремої згоди на неї зазвичай не просять. А от для аналітики, реклами й усіляких віджетів соцмереж згоду треба отримати до того, як вони запишуть свої куки. У будь-якому разі чесно опиши в політиці конфіденційності, які куки використовує твій сайт і навіщо.
І ще одна порада з безпеки: ніколи не зберігай у куках з JavaScript паролі чи токени входу. Куки для авторизації сервер ставить сам із прапорцем HttpOnly, і тоді скрипти на сторінці їх просто не бачать.
Що далі
Якщо в тебе тема на WordPress і хочеться перемикати цілі файли стилів, глянь кнопку перемикання стилю шаблона WordPress. Більше про це – за позначками JavaScript та Front-end розробка.
А ти зберігаєш налаштування відвідувачів у куках чи вже повністю перейшов/ла на localStorage? Пиши в коментарях 🙂


Прокоментувати
На сайті відображається лише твоє ім'я та коментар. Електронна пошта зберігається виключно для зв'язку з тобою за потреби та в жодному разі не передається стороннім особам.