This media is not supported in your browser
VIEW IN TELEGRAM
#фишка дня
У скроллящегося сайдбара можно сделать fade по краям так, чтобы пункты меню как будто уходили под градиент сверху и снизу. И сделать это красиво.
Сразу пример со всем кодом и описанием: https://codepen.io/editor/alinaki/pen/019d954a-79e7-7e49-8653-181b0b67ad61
Для этого используется mask-image, а управляет всем scroll timeline: скролл контейнера становится прогрессом CSS-анимации. Дальше анимация меняет стопы градиента в маске, поэтому в начале верхний fade выключен, после начала прокрутки появляется, а в конце исчезает нижний.
Важный момент в том, что здесь не двигается сам градиент и не меняется opacity списка. Меняются именно стопы градиента, и из-за этого fade ведёт себя как часть скролла, а не как отдельный декоративный слой.
Если хочется понять глубже, смотреть стоит в сторону animation-timeline, scroll-timeline и обзора scroll-driven animations.
Upd. добавил светлую тему, чтобы разница была виднее.
#css #scroll
У скроллящегося сайдбара можно сделать fade по краям так, чтобы пункты меню как будто уходили под градиент сверху и снизу. И сделать это красиво.
Сразу пример со всем кодом и описанием: https://codepen.io/editor/alinaki/pen/019d954a-79e7-7e49-8653-181b0b67ad61
Для этого используется mask-image, а управляет всем scroll timeline: скролл контейнера становится прогрессом CSS-анимации. Дальше анимация меняет стопы градиента в маске, поэтому в начале верхний fade выключен, после начала прокрутки появляется, а в конце исчезает нижний.
@keyframes sidebar-fade-mask {
0% { --fade-top-end: 0%; --fade-bottom-start: 94%; --fade-bottom-end: 99%; }
8%, 92% { --fade-top-end: 6%; --fade-bottom-start: 94%; --fade-bottom-end: 99%; }
100% { --fade-top-end: 6%; --fade-bottom-start: 100%; --fade-bottom-end: 100%; }
}
.menu-scroll {
animation: sidebar-fade-mask auto linear both;
animation-timeline: scroll(self block);
mask-image: linear-gradient(
to bottom,
transparent 0%,
#000 var(--fade-top-end),
#000 var(--fade-bottom-start),
transparent var(--fade-bottom-end)
);
}
Важный момент в том, что здесь не двигается сам градиент и не меняется opacity списка. Меняются именно стопы градиента, и из-за этого fade ведёт себя как часть скролла, а не как отдельный декоративный слой.
Если хочется понять глубже, смотреть стоит в сторону animation-timeline, scroll-timeline и обзора scroll-driven animations.
Upd. добавил светлую тему, чтобы разница была виднее.
#css #scroll
👍20❤3🤩2
#фишка дня
Надоело угадывать высоту строки, чтобы текст стал высотой ровно в прописную букву? Say no more!
И вы великолепны.
P. S. ещё более вы великолепны, если Safari версии больше 17.2 включительно.
#css #бородач
Надоело угадывать высоту строки, чтобы текст стал высотой ровно в прописную букву? Say no more!
line-height: 1cap;
И вы великолепны.
P. S. ещё более вы великолепны, если Safari версии больше 17.2 включительно.
#css #бородач
❤16
This media is not supported in your browser
VIEW IN TELEGRAM
#codepen дня
Ну что, кажется, настало то время, когда для стилизации радиокнопок и чекбоксов не нужно больше изгаляться с
Итак, смотрим на пример от Джона Кантнера: https://codepen.io/alinaki/pen/ExMXbqz
1. Для начала, обнуляем все браузерные стили и предположения браузера об внешнем виде радиокнопок вообще через
2. Я вам этого не говорил, но, технически, уже давно можно на поля ввода накладывать псевдоэлементы. Но не на select. Я всё хочу написать большой пост про реализацию select, пока вот так.
Благодаря этой возможности, собственно, можно стилизовать чекбокс как душе угодно:
3. Освободившиеся ресурсы мозга и тот факт, что теперь все элементы красиво вложены в label (как минимум, не нужны for и id), можно отправить на реализацию разных эффектов.
Например, проверить, есть ли лейбл с выделенным чекбоксом и подвинуть к нему рамку:
Обратите внимание, рамка — отдельный элемент, к ней обращаемся через селектор низлежащих соседей ~.
Не знаю, что меня больше впечатляет. Псевдоэлементы на полях ввода или :has.
И да, поддерживается везде.
#css #has #appearance #бородач
Ну что, кажется, настало то время, когда для стилизации радиокнопок и чекбоксов не нужно больше изгаляться с
input:checked+i. Это освобождает мозг и руки для более приятных вещей.Итак, смотрим на пример от Джона Кантнера: https://codepen.io/alinaki/pen/ExMXbqz
1. Для начала, обнуляем все браузерные стили и предположения браузера об внешнем виде радиокнопок вообще через
appearance: none.2. Я вам этого не говорил, но, технически, уже давно можно на поля ввода накладывать псевдоэлементы. Но не на select. Я всё хочу написать большой пост про реализацию select, пока вот так.
Благодаря этой возможности, собственно, можно стилизовать чекбокс как душе угодно:
::before, ::after, :checked::before, :checked::after... В целом, лично я бы обошёлся радиальным градиентом и одним псевдоэлементом.3. Освободившиеся ресурсы мозга и тот факт, что теперь все элементы красиво вложены в label (как минимум, не нужны for и id), можно отправить на реализацию разных эффектов.
Например, проверить, есть ли лейбл с выделенным чекбоксом и подвинуть к нему рамку:
label:nth-of-type(2):has(input[type="radio"]:checked) ~ .selection {
transform: translateY(100%);
}
Обратите внимание, рамка — отдельный элемент, к ней обращаемся через селектор низлежащих соседей ~.
Не знаю, что меня больше впечатляет. Псевдоэлементы на полях ввода или :has.
И да, поддерживается везде.
#css #has #appearance #бородач
👍16
This media is not supported in your browser
VIEW IN TELEGRAM
#статья дня
Scroll-driven animations уже давно есть в Chrome, и за последний год вокруг них накопилось много примеров — у того же Bramus Van Damme были подробные демки с
Как всегда, это интерактивная документация по
Посмею себе напомнить ключевую идею процесса: прогресс анимации берётся не из времени (`animation-duration`), а из положения элемента относительно viewport или scroll-контейнера. В статье это сразу показывается на примере с progress bar, где значение анимации напрямую связано со скроллом страницы.
Дальше он последовательно вводит
Отдельно разбирается
Есть демонстрации с несколькими timeline’ами и синхронизацией анимаций, где один scroll-прогресс управляет сразу несколькими свойствами.
Практически в каждом блоке есть интерактив: можно скроллить вложенные контейнеры и сразу видеть, как меняется поведение.
Документация: https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timeline
Примеры от Google: https://developer.chrome.com/docs/css-ui/scroll-driven-animations/
Из нюансов — Safari всё ещё отстаёт: часть API отсутствует или работает неполно, так что без фоллбеков пока не обойтись.
#css #scroll
Scroll-driven animations уже давно есть в Chrome, и за последний год вокруг них накопилось много примеров — у того же Bramus Van Damme были подробные демки с
view-timeline и разными вариантами ranges. Теперь появился ещё один большой разбор от самого Джоша Комо: https://www.joshwcomeau.com/animation/scroll-driven-animations/Как всегда, это интерактивная документация по
animation-timeline.Посмею себе напомнить ключевую идею процесса: прогресс анимации берётся не из времени (`animation-duration`), а из положения элемента относительно viewport или scroll-контейнера. В статье это сразу показывается на примере с progress bar, где значение анимации напрямую связано со скроллом страницы.
Дальше он последовательно вводит
scroll-timeline и view-timeline. Первый вариант привязывается к прокрутке контейнера, второй — к тому, как конкретный элемент входит и выходит из viewport. Есть наглядные демо, где один и тот же @keyframes ведёт себя по-разному в зависимости от выбранного таймлайна.Отдельно разбирается
animation-range. На интерактивных примерах видно, как entry, exit, cover, contain влияют на диапазон, в котором проигрывается анимация.Есть демонстрации с несколькими timeline’ами и синхронизацией анимаций, где один scroll-прогресс управляет сразу несколькими свойствами.
Практически в каждом блоке есть интерактив: можно скроллить вложенные контейнеры и сразу видеть, как меняется поведение.
Документация: https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timeline
Примеры от Google: https://developer.chrome.com/docs/css-ui/scroll-driven-animations/
Из нюансов — Safari всё ещё отстаёт: часть API отсутствует или работает неполно, так что без фоллбеков пока не обойтись.
#css #scroll
👍6
#фишка дня
Итак, все мы знаем, что при добавлении скроллбара (если этот скроллбар, конечно, виден) у нас происходит сдвигпо фазе полей справа.
Ну или слева, если вы араб.
Но это же можно исправить! Используя правило
Демо от Ахмада Шадида в его Defensive CSS: https://defensivecss.dev/tip/scrollbar-gutter/
Can I Use: https://caniuse.com/?search=scrollbar-gutter
Поддержка в Chrome и Firefox. В Safari пока только в TP, но на Apple-устройствах скроллбары, как правило, скрыты и отображаются поверх контента, не занимая места.
Выглядит это, правда, как дополнительный паддинг, но!
Есть интересное но в виде
Раньше за похожее решение отвечало правило
Лучше всего это работает, впрочем, для попапов. Мало кого волнует скроллбар на тексте, а вот прыгающий
#css #scrollbar #gutter #бородач
Итак, все мы знаем, что при добавлении скроллбара (если этот скроллбар, конечно, виден) у нас происходит сдвиг
Ну или слева, если вы араб.
Но это же можно исправить! Используя правило
scrollbar-gutter: stable можно зарезервировать место под скроллбар, не прибегая к иным методам вроде overflow: scroll (который буквально этот самый скроллбар заранее покажет, даже если он не нужен).Демо от Ахмада Шадида в его Defensive CSS: https://defensivecss.dev/tip/scrollbar-gutter/
Can I Use: https://caniuse.com/?search=scrollbar-gutter
Поддержка в Chrome и Firefox. В Safari пока только в TP, но на Apple-устройствах скроллбары, как правило, скрыты и отображаются поверх контента, не занимая места.
Выглядит это, правда, как дополнительный паддинг, но!
Есть интересное но в виде
scrollbar-gutter: stable both-edges, которое зарезервирует место под скроллбар, и такое же — на другой стороне. Что, в целом, избавит нас от разных паддингов.Раньше за похожее решение отвечало правило
overflow: overlay, но его отменили в пользу gutter. Лучше всего это работает, впрочем, для попапов. Мало кого волнует скроллбар на тексте, а вот прыгающий
body при появлении модалки — это уже перебор.#css #scrollbar #gutter #бородач
❤6👍2
This media is not supported in your browser
VIEW IN TELEGRAM
#заметка дня
А помните (конечно же помните!) как мы с вами обсуждали CSS Custom Highlight API для реализации подсветки кода?
Ну вот же, положила: https://xn--r1a.website/htmlshit/2715
Так вот, а почему бы не объединить подсветку CSS с поиском по тексту? Ну в самом деле, интересно же, как это реализовано, например, в текстовых редакторах или браузерах при поиске по странице. Хотя бы на минимальном уровне.
А реализовано это через, простите, обход дерева!
Алгориииииитмы
Ладно, нам не придётся самим писать обходчик, он уже имеется! Вот: https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalker
Главное — это понять, какой параметр фильтрации узлов передать. Ведь объектная модель документа она не только из тегов состоит, там как минимум параллельно идут атрибуты, текст, комментарии... Нам незачем искать вообще по всему.
Ну в нашем случае всё просто: NodeFilter.SHOW_TEXT — ищем по текстовым нодам, словам.
Ну а дальше всё просто: проверяем регуляркой на совпадения и запускаем подсветку. Уж это за нас теперь может и браузер делать: https://codepen.io/alinaki/pen/zxvPbRJ
Да, теперь можно и ваших камтомных селектах красиво подсветить результат фильтрации.
Пользуемся, котаны.
#css #highlight #бородач
А помните (конечно же помните!) как мы с вами обсуждали CSS Custom Highlight API для реализации подсветки кода?
Ну вот же, положила: https://xn--r1a.website/htmlshit/2715
Так вот, а почему бы не объединить подсветку CSS с поиском по тексту? Ну в самом деле, интересно же, как это реализовано, например, в текстовых редакторах или браузерах при поиске по странице. Хотя бы на минимальном уровне.
А реализовано это через, простите, обход дерева!
Алгориииииитмы
Ладно, нам не придётся самим писать обходчик, он уже имеется! Вот: https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalker
Главное — это понять, какой параметр фильтрации узлов передать. Ведь объектная модель документа она не только из тегов состоит, там как минимум параллельно идут атрибуты, текст, комментарии... Нам незачем искать вообще по всему.
Ну в нашем случае всё просто: NodeFilter.SHOW_TEXT — ищем по текстовым нодам, словам.
Ну а дальше всё просто: проверяем регуляркой на совпадения и запускаем подсветку. Уж это за нас теперь может и браузер делать: https://codepen.io/alinaki/pen/zxvPbRJ
Да, теперь можно и ваших камтомных селектах красиво подсветить результат фильтрации.
Пользуемся, котаны.
#css #highlight #бородач
1👍8❤2
This media is not supported in your browser
VIEW IN TELEGRAM
#фишка дня
Я не думал, что доживу, но, похоже, скоро можно будет вписывать текст в контейнер без хаков с vw/vh и даже без скриптов.
Сразу пример (нужны флаги! ниже): https://codepen.io/cssgrid/pen/emBZzPL
Фича называется text-fit. Это часть экспериментального CSS (обсуждается в рамках CSS Text / Sizing), и идея тут очевидна: вписать текст в контейнер.
Вот спека в процессе: https://drafts.csswg.org/css-text-4/#text-fit-property
Пока это всё работает только за флагом
Но уже хорошо же!
#css #text #fit
Я не думал, что доживу, но, похоже, скоро можно будет вписывать текст в контейнер без хаков с vw/vh и даже без скриптов.
Сразу пример (нужны флаги! ниже): https://codepen.io/cssgrid/pen/emBZzPL
Фича называется text-fit. Это часть экспериментального CSS (обсуждается в рамках CSS Text / Sizing), и идея тут очевидна: вписать текст в контейнер.
Вот спека в процессе: https://drafts.csswg.org/css-text-4/#text-fit-property
Пока это всё работает только за флагом
chrome://flags → Experimental Web Platform features.Но уже хорошо же!
#css #text #fit
❤14🤩4
#статья дня
Кармен Ансио написал отличный материал про CSS-функцию
Причина понятна: обычно
Ансио показывает гораздо более интересный сценарий. Если заранее рассчитать движение какой-нибудь физической системы — например, пружины — то результат можно представить как последовательность значений и скормить её
Автор начинает с модели затухающей пружины, показывает уравнение, объясняет параметры системы и сопровождает всё это интерактивными примерами. Можно менять коэффициенты и сразу видеть, как меняется движение.
В общем, если у вас есть модель движения и набор точек, CSS уже умеет её воспроизводить.
Короче,
Ссылка ещё раз: https://www.carmenansio.com/articles/spring-physics-css
#css #easing #spring #linear
Кармен Ансио написал отличный материал про CSS-функцию
linear(). Она появилась уже довольно давно, но в реальных проектах встречается редко — большинство по привычке ограничивается ease, ease-in-out и разными вариантами cubic-bezier().Причина понятна: обычно
linear() воспринимают как способ вручную задать несколько точек на кривой анимации. Не самый удобный инструмент и не очень понятно, зачем он вообще нужен.Ансио показывает гораздо более интересный сценарий. Если заранее рассчитать движение какой-нибудь физической системы — например, пружины — то результат можно представить как последовательность значений и скормить её
linear(). Браузер потом просто воспроизведёт эту траекторию.
.card {
transition:
transform 647ms
linear(
0, 0.04, 0.15, 0.30,
0.46, 0.59, 0.69,
0.75, 0.79, 0.80
/* ... */
);
}
Автор начинает с модели затухающей пружины, показывает уравнение, объясняет параметры системы и сопровождает всё это интерактивными примерами. Можно менять коэффициенты и сразу видеть, как меняется движение.
В общем, если у вас есть модель движения и набор точек, CSS уже умеет её воспроизводить.
Короче,
linear() — это вам не это.Ссылка ещё раз: https://www.carmenansio.com/articles/spring-physics-css
#css #easing #spring #linear
👍9🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
#фишка дня
Аккордионы и прочие схлопывающиеся сценарии. Скажи, как ты их анимируешь, и я скажу, кто ты.
Если ты их до сих пор анимируешь через
Ну буквально, только что сессию демонстрационную проводил.
Согласен,
Да-да, давненько я не напоминал, что гриды прекрасно анимируются и что уже давно не нужны извращения. Но сегодня я пришёл с маленьким дополнением.
Все же в курсе, что классика — одна строка грида и 0fr ↔ 1fr?
Внутренний блок клипится — высота анимируется без
А вот дополнение: в
Демонстрация: https://codepen.io/alinaki/pen/QwGryqN
Первый аргумент в minmax — минимум, не максимум:
И да: padding на clip-слой не вешайте — только внутрь контента, иначе и под
#css #grid #accordion
Аккордионы и прочие схлопывающиеся сценарии. Скажи, как ты их анимируешь, и я скажу, кто ты.
Если ты их до сих пор анимируешь через
max-height, скорее всего, ты — LLM-ка, которая застряла где-то там.Ну буквально, только что сессию демонстрационную проводил.
Согласен,
height ещё плохо анимируется в auto, хоть и появился interpolate-size. Но ведь гриды никто у нас не отбирал!Да-да, давненько я не напоминал, что гриды прекрасно анимируются и что уже давно не нужны извращения. Но сегодня я пришёл с маленьким дополнением.
Все же в курсе, что классика — одна строка грида и 0fr ↔ 1fr?
.accordion-panel {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 0.28s ease;
}
.accordion-panel[data-open="true"] {
grid-template-rows: 1fr;
}
.panel-inner {
overflow: hidden;
min-height: 0;
}
Внутренний блок клипится — высота анимируется без
max-height: 9999px.А вот дополнение: в
grid-template-rows можно и пиксели, и minmax(). Например, свёрнуто, но кусочек текста виден:
grid-template-rows: minmax(48px, 0fr); /* закрыто */
grid-template-rows: minmax(48px, 1fr); /* открыто */
Демонстрация: https://codepen.io/alinaki/pen/QwGryqN
Первый аргумент в minmax — минимум, не максимум:
48px снизу, а не «не больше 48». Полное скрытие — по-прежнему 0fr.И да: padding на clip-слой не вешайте — только внутрь контента, иначе и под
0fr торчит, и при открытии прыгает.#css #grid #accordion
❤22👍6🔥5
This media is not supported in your browser
VIEW IN TELEGRAM
#статья дня
Вы когда-нибудь пытались анимировать смену цвета и сталкивались с тем, что в какой-то момент всё превращается в уныло-серое? Джош Комо как раз разбирает эту проблему.
Дело в том, что даже если мы задаём разные цвета через разные цветовые модели, браузер всё равно интерполирует их в RGB-пространстве. А оно ограниченное, и на кривой перехода иногда выпадает серый — как с градиентами (https://xn--r1a.website/htmlshit/806), только теперь в анимации.
Казалось бы, решение простое: крутим hue в HSL, и серого не будет. Но на практике CSS-анимации всё равно сводятся к RGB, и мы снова получаем неожиданный результат. И более того, анимация от 0 до 360 (полный оборот) вообще не будет анимирована. Оптимизация!
Есть два способа это обойти:
1. Использовать
2. Хранить угол оттенка в CSS-переменной и анимировать именно её, а не цвет в целом.
В итоге получается ровная и предсказуемая смена цвета без серых провалов.
Статья: https://www.joshwcomeau.com/animation/color-shifting/
#css #color #animation #бородач
Вы когда-нибудь пытались анимировать смену цвета и сталкивались с тем, что в какой-то момент всё превращается в уныло-серое? Джош Комо как раз разбирает эту проблему.
Дело в том, что даже если мы задаём разные цвета через разные цветовые модели, браузер всё равно интерполирует их в RGB-пространстве. А оно ограниченное, и на кривой перехода иногда выпадает серый — как с градиентами (https://xn--r1a.website/htmlshit/806), только теперь в анимации.
Казалось бы, решение простое: крутим hue в HSL, и серого не будет. Но на практике CSS-анимации всё равно сводятся к RGB, и мы снова получаем неожиданный результат. И более того, анимация от 0 до 360 (полный оборот) вообще не будет анимирована. Оптимизация!
Есть два способа это обойти:
1. Использовать
filter: hue-rotate(), чтобы прокручивать оттенки напрямую.2. Хранить угол оттенка в CSS-переменной и анимировать именно её, а не цвет в целом.
В итоге получается ровная и предсказуемая смена цвета без серых провалов.
Статья: https://www.joshwcomeau.com/animation/color-shifting/
#css #color #animation #бородач
❤7👍2