Свежие статьи

Иммутабельные методы массивов: with, toSorted, toReversed, toSpliced

Классические методы sort, reverse и splice меняют массив на месте. В мире React, Vue и других подходов с иммутабельным состоянием это источник коварных багов: вы случайно мутируете исходные данные, и UI не обновляется или ломается непредсказуемо. Четыре метода — with, toSorted, toReversed и toSpliced — делают то же самое, но возвращают новый массив, не трогая оригинал.

toSorted и toReversed — иммутабельные двойники sort и reverse. toSpliced — версия splice, возвращающая копию с изменениями. А with(index, value) заменяет один элемент по индексу — раньше для этого приходилось писать map с проверкой индекса или копировать через спред и присваивать.

const nums = [3, 1, 2];

const sorted = nums.toSorted();     // [1, 2, 3]
const reversed = nums.toReversed(); // [2, 1, 3]
const replaced = nums.with(0, 99);  // [99, 1, 2]
const spliced = nums.toSpliced(1, 1, 'x'); // [3, 'x', 2]

console.log(nums); // [3, 1, 2] — исходный массив не тронут
[3,1,2].toSorted()[1, 2, 3]
[3,1,2].toReversed()[2, 1, 3]
[3,1,2].with(0, 99)[99, 1, 2]
[3,1,2].toSpliced(1,1,'x')[3, 'x', 2]

Ну и вообще, раньше «заменить элемент по индексу без мутации» выглядело многословно:

state.map((item, i) => i === idx ? newItem : item)

Теперь это выглядит так

state.with(idx, newItem)

Согласитесь, так гораздо короче и понятнее. То же с сортировкой списка для отображения: items.toSorted(byDate) не испортит исходный массив, а значит, не вызовет неожиданных ре-рендеров или гонок данных.

Все четыре метода поддерживаются в Chrome 110+, Firefox 115+, Safari 16+ и в Node.js 20+. К 2026 году это полностью безопасно использовать без полифилов в любом современном проекте. Для совсем старых окружений эти методы легко полифилятся, поскольку выражаются через копирование и существующие операции.

CSS
  • 28 июня 2026

Неужели Temporal API избавит нас от боли работы с датами в JS?

Объект Date в JavaScript считается одной из худших частей языка: месяцы нумеруются с нуля, парсинг строк непредсказуем, объект мутабельный, а работа с таймзонами — отдельная боль. Поэтому многие проекты тянут библиотеки вроде date-fns или Luxon. Temporal — это новый встроенный API дат, который проектировали с нуля, учтя все ошибки Date.

Читать дальше
JS
  • 27 июня 2026

CSS Scroll Snap: делаем карусели и слайды с прилипанием без JS

Карусели, ленты сторис, постраничные слайдеры — всё это обычно делали на JavaScript: вешали обработчики, считали смещения, программно докручивали до ближайшего элемента. CSS Scroll Snap переносит «прилипание» прокрутки на уровень браузера: контейнер сам останавливается ровно на границах элементов, плавно и с учётом инерции.

Настройка Scroll Snap состоит из двух частей. На контейнере задаётся scroll-snap-type — ось прокрутки и строгость прилипания (mandatory всегда докручивает до точки, proximity — только если близко). На дочерних элементах указывается scroll-snap-align — какой их край прилипает к контейнеру.

.carousel {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  gap: 12px;
}

.slide {
  flex: 0 0 80%;
  scroll-snap-align: center;
}

Теперь горизонтальная прокрутка ленты сама центрирует каждый слайд — без единой строки JavaScript. Попробуйте поскроллить эту импровизированную ленту вправо-влево.

1
2
3
4

Поведение можно дошлифовать дополнительными свойствами. scroll-padding на контейнере сдвигает точку прилипания внутрь — полезно, когда сверху есть фиксированная шапка. scroll-snap-stop: always запрещает «проскакивать» несколько слайдов одним резким свайпом, заставляя останавливаться на каждом. Этого набора хватает для большинства каруселей и постраничных лент без скриптов.

CSS Scroll Snap поддерживается во всех современных браузерах: Chrome, Firefox и Safari давно реализовали спецификацию. На 2026 год это полностью стабильная технология для продакшена. В крайне старых браузерах прокрутка останется обычной, без прилипания, что является безопасной деградацией — лента всё равно листается.

CSS
  • 27 июня 2026

light-dark(): включаем тёмную тему в одну строку CSS

Поддержка тёмной темы обычно требует дублирования: вы пишете цвета для светлой темы, а потом ещё раз — внутри @media (prefers-color-scheme: dark). Это удваивает CSS, в котором потом ещё и легко запутаться. А вот функция light-dark() убирает дублирование: вы задаёте оба значения прямо в одном объявлении, а браузер сам выбирает нужное.

Функция light-dark() принимает два значения: первое используется в светлой теме, второе — в тёмной. Чтобы она заработала, нужно объявить на корне color-scheme: light dark — это говорит браузеру, что страница поддерживает обе схемы.

:root {
  color-scheme: light dark;
}

body {
  background: light-dark(#ffffff, #1a1a1a);
  color: light-dark(#1a1a1a, #f0f0f0);
}

.card {
  background: light-dark(#f5f5f5, #2a2a2a);
  border: 1px solid light-dark(#e0e0e0, #404040);
}

Системная тема — не единственный вариант. Если на конкретном элементе задать color-scheme: dark, то все вложенные light-dark() начнут отдавать тёмные значения, независимо от настроек ОС. Это позволяет сделать переключатель темы: меняете color-scheme на корне через JS — и весь интерфейс перестраивается.

Функция особенно хороша для дизайн-систем и компонентных библиотек, где каждый цвет описан один раз. Вместо двух наборов токенов вы держите один с парами значений. Сопровождать такой код проще: добавляя новый цвет, вы сразу думаете об обеих темах.

Функция light-dark() поддерживается в Chrome 123+, Firefox 120+ и Safari 17.5+. На середину 2026 года это покрывает подавляющее большинство пользователей. Для старых браузеров стоит оставить запасной цвет в обычном объявлении перед строкой с light-dark() — браузер просто проигнорирует непонятную функцию.

CSS
  • 25 июня 2026

Stream API. Читаем ответ сервера по мере получения

Обычный fetch работает так: браузер ждёт, пока сервер отправит весь ответ, и только потом отдаёт данные вашему коду. Для небольших JSON-ов это нормально. Но если ответ большой, или сервер генерирует его постепенно (как это делают языковые модели при стриминге), ждать полного ответа — плохая идея. Streams API позволяет читать ответ прямо по мере поступления.

В ReadableStream каждый ответ fetch имеет свойство body — это ReadableStream. Из него можно читать данные кусками (chunks) по мере их поступления:

const response = await fetch('/api/stream');
const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  console.log(decoder.decode(value));
}

Метод reader.read() возвращает промис с объектом { done, value }. value — это Uint8Array (сырые байты), поэтому нужен TextDecoder для перевода в строку. Когда данные кончаются, done становится true.

Читать дальше
JS
  • 24 июня 2026

Итоги 3-го чемпионата по вёрстке

Чемпионат по вёрстке помогает:

  1. Профессиональным разработчикам подтверждать свой уровень и навыки, оставлять цифровой след.
  2. Клиентам выбирать лучшие студии и компании для разработки своих проектов.
  3. Компаниям находить специалистов по реальному результату, а не по резюме.

Ключевые особенности соревнования:

  • сложные и объёмные макеты от профессиональных дизайн-студий;
  • двухнедельный формат, ориентированный на качество, а не скорость;
  • строгая многоуровневая оценка;
  • жюри из опытных разработчиков из бигтеха и компаний заказной разработки.

Третий чемпионат по вёрстке завершился 29 апреля. Ниже — его итоги и разбор уровня работ участников по трекам: для компаний и профессиональных разработчиков, а также для джунов. Участие приняли более 150 человек.

Читать дальше
Айти
  • 11 июня 2026

Как сделать блок с частыми вопросами на HTML и CSS без JS

Тег <details> уже давно позволяет делать раскрывающиеся блоки без единой строки JavaScript. Но у него была одна проблема: несколько таких блоков работали независимо — открытие одного никак не влияло на другие. Аккордеон, в котором открыт только один раздел, приходилось делать через JS. В 2024 году это изменилось: у <details> появился атрибут name.

Если дать нескольким элементам <details> одинаковый атрибут name, браузер объединит их в группу. Когда открывается один элемент — остальные из группы автоматически закрываются. Это поведение точно как у радиокнопок с одинаковым name.

<details name="faq">
  <summary>Вопрос первый</summary>
  <p>Ответ на первый вопрос.</p>
</details>

<details name="faq">
  <summary>Вопрос второй</summary>
  <p>Ответ на второй вопрос.</p>
</details>

<details name="faq">
  <summary>Вопрос третий</summary>
  <p>Ответ на третий вопрос.</p>
</details>

Это и есть эксклюзивный аккордеон. Ноль JavaScript, ноль дополнительных библиотек.

Читать дальше
Как сверстать
  • 7 июня 2026

Как работать с JSON в терминале через jq

Когда вы запрашиваете данные через curl или читаете конфигурационный файл, JSON в терминале выглядит примерно так: одна длинная строка без переносов и отступов, которую невозможно читать. А если ответ весит несколько килобайт с вложенными объектами — найти нужное поле глазами нереально.

jq — инструмент командной строки для работы с JSON: форматирует, фильтрует, извлекает нужные поля и преобразует данные. Работает как конвейер: передаёте JSON на вход, получаете нужный кусок на выходе.

Читать дальше
JS
  • 6 июня 2026

Цвета в oklch(): современный цветовой формат

HEX-коды вроде #3b82f6 — привычный способ задавать цвета в CSS. Но у них есть большая проблема: они не интуитивны для человека. Как сделать цвет светлее на 10%? Добавить прозрачность? Подобрать гармоничный акцентный оттенок? С HEX и даже с HSL это превращается в угадайку. oklch() решает эту задачу.

Читать дальше
CSS
  • 4 июня 2026

Нативный CSS nesting: вложенность без препроцессора

Разработчики давно полюбили Sass и Less за вложенные правила. Вместо того чтобы писать длинные селекторы много раз, можно было аккуратно вложить дочерние стили внутрь родительских. В 2024 году это умение получил сам CSS — никаких препроцессоров больше не нужно.

Читать дальше
CSS
  • 2 июня 2026

Запуск инструментов без установки с помощью npx

Когда вы хотите попробовать какой-нибудь CLI-инструмент, обычный путь такой: установить глобально через npm install -g, попользоваться, а потом забыть удалить. Со временем в системе накапливаются десятки глобально установленных пакетов разных версий, которые начинают конфликтовать друг с другом.

npx решает эту проблему: он запускает пакет напрямую из реестра npm, не устанавливая его глобально. Запустили — и пакет не остался в системе.

Читать дальше
Софт
  • 1 июня 2026

structuredClone() — правильное копирование объектов в JavaScript

Копирование объектов в JavaScript — одна из тех тем, которые поначалу кажутся простыми, а потом преподносят неожиданные сюрпризы.

Присвоить объект через = — не копирование. Это просто ещё одна ссылка на тот же объект. Измените копию — изменится оригинал:

const original = { name: 'Иван', scores: [10, 20, 30] };
const copy = original;

copy.name = 'Пётр';
console.log(original.name); // 'Пётр' — изменился оригинал!

Для поверхностного копирования используют Object.assign() или spread-оператор {...obj}. Но они копируют только первый уровень. Вложенные объекты и массивы по-прежнему остаются общими.

В 2022 году JavaScript получил structuredClone() — стандартный способ сделать полную глубокую копию.

Читать дальше
JS
  • 18 мая 2026

Умный перенос текста в CSS с text-wrap: balance и pretty

Перенос слов в заголовках и текстовых блоках — деталь, на которую пользователи не обращают внимания, когда она хороша, и сразу замечают, когда что-то не так. Одиноко висящее слово в последней строке заголовка, или строки разной длины там, где хотелось симметрии — такое встречается часто. CSS text-wrap предлагает два умных режима для решения этой проблемы.

Читать дальше
Как сверстать
  • 17 мая 2026

http-server — быстрый локальный сервер для статики

Открыть HTML-файл двойным кликом — плохая идея. Браузер откроет его по протоколу file://, и сразу начнутся проблемы: не загружаются шрифты, блокируются запросы к API из-за CORS, не работают относительные пути к модулям. Чтобы страница вела себя как в интернете, ей нужен настоящий HTTP-сервер.

http-server — минималистичный статический сервер, который запускается одной командой и не требует настройки.

Читать дальше
Софт
  • 15 мая 2026

Вам срочно нужно освоить Prettier, и вот почему

В команде из нескольких человек, где пока не устаканились стандарты написания кода, этот самый код быстро превращается непонятно во что: один ставит одинарные кавычки, другой — двойные, третий делает отступы табами, четвёртый — пробелами. На ревью половина комментариев относятся не к логике, а к стилю, и это большая трата времени и для команды, и для компании.

Prettier решает проблему радикально: он берёт ваш код и переформатирует его по единым правилам. После этого весь код в проекте выглядит одинаково, вне зависимости от того, кто его написал.

Читать дальше
Софт
  • 13 мая 2026

git bisect, или как быстро найти сломавший всё коммит

Бывает такая ситуация: функциональность работала неделю назад, а сейчас — нет. За это время в репозитории накопилось сорок коммитов от разных людей. Просматривать каждый по очереди — долго и мучительно.

git bisect решает эту задачу умно: он делает бинарный поиск по истории коммитов. Вы говорите «вот этот коммит рабочий, а вот этот — нет», а Git сам переключает репозиторий на середину диапазона и спрашивает: «Здесь работает?» После нескольких ответов плохой коммит найден.

Работает бинарный поиск: сорок коммитов — шесть вопросов, восемьсот коммитов — десять вопросов.

Читать дальше
Git
  • 13 мая 2026

Почему ESLint — это хорошо

Опечатка в имени переменной, использование == вместо ===, вызов функции до её объявления — всё это браузер обнаружит только в момент выполнения кода. В лучшем случае вы увидите ошибку сразу, в худшем — она всплывёт у пользователя в продакшене.

ESLint проверяет код до запуска. Он читает файл, анализирует структуру и сообщает о проблемах прямо в редакторе или в терминале. Это называется статическим анализом, или линтингом.

Читать дальше
JS
  • 12 мая 2026

Как CSS subgrid спасает карточки на сайтах

Grid Layout решил много задач с раскладкой, но одна проблема долго оставалась без решения. Представьте три карточки в сетке. У каждой — заголовок, описание и кнопка. Высота заголовков разная: в одной карточке текст длиннее, в другой короче. В итоге кнопки стоят на разной высоте, и сетка выглядит неаккуратно.

Раньше это решали через JavaScript: вычисляли высоту заголовков и выставляли min-height. Или просто мирились с несовершенством.

Subgrid позволяет дочернему элементу участвовать в сетке родителя. Карточка занимает несколько строк родительской сетки — и все её внутренние блоки выравниваются по общим линиям.

Читать дальше
CSS
  • 2 мая 2026

Контейнерные запросы в CSS на одном простом примере

Долгое время адаптивная вёрстка строилась на медиавыражениях: браузер смотрит на ширину окна и применяет нужные стили. Это работало, но создавало одну постоянную проблему.

Представьте карточку товара. На широком экране она выглядит горизонтально: слева фото, справа текст. На узком — вертикально: фото сверху, текст снизу. Казалось бы, медиавыражение справится. Но что если эту же карточку нужно показать в узкой боковой колонке на широком экране? Медиавыражение видит только ширину окна — она большая, а значит, карточка будет горизонтальной, хотя места у неё нет.

Container queries решают именно эту задачу: элемент адаптируется под размер своего контейнера, а не под размер окна.

Читать дальше
CSS
  • 1 мая 2026

Наводим порядок в каскаде с использованием CSS @layer

Если вы когда-нибудь подключали стороннюю библиотеку стилей и потом пытались её переопределить — вы знаете эту боль. Пишете правило, оно не работает. Добавляете класс поконкретнее — всё равно не работает. В итоге пишете !important и расстраиваетесь, потому что теперь нужно всё время учитывать это в дальнейшей работе.

Это называют войной специфичности. Возникает она потому, что CSS решает конфликты через длину и конкретность селекторов, а не через то, кто написал правило позже и кто важнее по смыслу.

В 2022 году в браузерах появился @layer — способ самим расставить приоритеты между группами стилей.

Читать дальше
CSS
  • 30 апреля 2026