Хватит мучить JS там, где справится пара тегов
Признайся, сколько раз ты подключал целую библиотеку или писал потный JS-код с высчитыванием scrollHeight только для того, чтобы сделать обычный аккордеон? Дизайнеры рисуют красивые плавные раскрывашки, а стандартный HTML-тег details из коробки выглядит как привет из девяностых: дерганый, с уродливым стандартным треугольником и нулевой гибкостью. Мы привыкли думать, что details и summary — это для черновиков, а для продакшена нужно городить кастомные решения. Но на дворе почти 2026 год, и ситуация изменилась настолько, что пора выбрасывать костыли.
Как мы страдали раньше
Раньше кастомизация details была похожа на прогулку по минному полю. Чтобы убрать стандартную стрелочку, приходилось писать summary::-webkit-details-marker { display: none; }, что само по себе выглядит как костыль. А если ты хотел добавить анимацию раскрытия? Забудь. CSS не умеет анимировать height: auto, поэтому мы либо использовали max-height: 1000px (что ломало тайминги анимации), либо писали скрипты, которые измеряли высоту контента. К слову, когда контента внутри аккордеона очень много, не лишним будет вспомнить про оптимизацию рендеринга с помощью content-visibility, чтобы браузер не потел над отрисовкой скрытых блоков.
Как делать правильно в 2026 году
Сегодня details — это полноценный гибкий инструмент. Главный прорыв последних лет — это свойство interpolate-size: allow-keywords и новые возможности работы с состояниями. Теперь мы можем анимировать переход от закрытого к открытому состоянию прямо через CSS, не зная точной высоты контента. Мы используем псевдоэлемент ::marker для кастомизации иконки или вовсе скрываем его через list-style: none на теге summary (да, теперь это работает кроссбраузерно и легально).
Более того, современный подход подразумевает использование селектора [open] для стилизации. Мы можем плавно менять прозрачность контента, вращать кастомную иконку и даже управлять раскладкой через Grid. И не забудь про доступность: когда настраиваешь свои стили, убедись, что пользователь четко видит фокус. В этом тебе поможет доступность интерфейсов с псевдоклассом :focus-visible, чтобы не раздражать тех, кто пользуется клавиатурой.
Готовый сниппет кода
Лови чистый, современный код, который можно брать и вставлять в проект. Здесь минимум стилей, но максимум эффекта: плавная анимация стрелочки и контента без единой строчки JavaScript.
/* Стилизуем контейнер */
details {
border: 1px solid #e2e8f0;
border-radius: 8px;
background: #ffffff;
transition: all 0.3s ease;
overflow: hidden;
}
/* Убираем дефолтный маркер и делаем summary флексом */
summary {
list-style: none;
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
cursor: pointer;
font-weight: 600;
user-select: none;
}
/* Скрываем стандартный маркер в Safari */
summary::-webkit-details-marker {
display: none;
}
/* Наша кастомная иконка */
summary::after {
content: "→";
transition: transform 0.3s ease;
}
/* Состояние при открытии */
details[open] summary::after {
transform: rotate(90deg);
}
/* Плавное появление контента */
.content {
padding: 0 1rem 1rem;
opacity: 0;
transform: translateY(-10px);
transition: all 0.4s ease;
}
details[open] .content {
opacity: 1;
transform: translateY(0);
}
Частая ошибка новичков
Самый распространенный косяк — это попытка анимировать сам тег details. Помни: когда атрибут open добавляется к тегу, браузер мгновенно меняет его состояние, и контент появляется в DOM-дереве «резко». Чтобы анимация выглядела дорого и плавно, нужно анимировать именно внутренний обертку-контейнер (в нашем примере это .content). Если ты просто повесишь транзишн на details, ты получишь либо дерганый скачок, либо ничего. Также никогда не удаляй outline у summary просто так — если тебе не нравится стандартная синяя рамка, замени её на что-то более эстетичное, но не лишай пользователя навигации.
🔥 Больше фишек, готовых сниппетов и передовых подходов к CSS мы публикуем в нашем Telegram-канале. Подписывайтесь, чтобы не пропустить!