Новинки CSS и веб-интерфейса: обзор I/O 2024

Веб-платформа полна инноваций, и CSS и функции веб-интерфейса находятся в авангарде этой захватывающей эволюции. Мы живём в золотую эру веб-интерфейса: новые функции CSS появляются в браузерах с невиданной ранее скоростью, открывая целый мир возможностей для создания красивого и увлекательного веб-интерфейса. В этой публикации блога мы подробно рассмотрим текущее состояние CSS и рассмотрим некоторые из самых революционных новых функций, которые меняют подход к разработке веб-приложений. Представленные на конференции Google I/O 2024, они меняют представление о том, как мы разрабатываем веб-приложения.

Новые интерактивные впечатления

Веб-опыт — это, по сути, взаимодействие между вами и вашими пользователями, поэтому так важно инвестировать в качественное взаимодействие с ними. Мы работаем над рядом действительно важных улучшений, которые открывают беспрецедентные возможности навигации по веб-страницам и между ними.

Анимации с прокруткой

Browser Support

  • Хром: 115.
  • Край: 115.
  • Firefox: за флагом.
  • Сафари: 26.

Source

Как следует из названия, API анимации на основе прокрутки позволяет создавать динамическую анимацию на основе прокрутки, не полагаясь на наблюдателей прокрутки или другие сложные скрипты.

Создание анимации с помощью прокрутки

Подобно тому, как на платформе работают анимации, основанные на времени , теперь вы можете использовать ход прокрутки скроллера для запуска, остановки и обратного воспроизведения анимации. Таким образом, при прокрутке вперёд вы будете видеть ход анимации, а при прокрутке назад — наоборот. Это позволяет создавать частичные или полностраничные визуальные эффекты с элементами, анимирующимися в области просмотра и внутри неё (также известно как scrollytelling) , для создания динамичного визуального эффекта.

Анимацию с помощью прокрутки можно использовать для выделения важного контента, направления пользователей по истории или просто для добавления динамики на ваши веб-страницы.

Визуальная анимация с прокруткой

Живая демонстрация

@keyframes appear {
  from {
    opacity: 0;
    scale: 0.8;
  }
  to {
    opacity: 1;
    scale: 1;
  }
}

img {
  animation: appear linear;
  animation-timeline: view();
  animation-range: entry 25% cover 50%;
}

Приведённый выше код определяет простую анимацию, которая отображается в области просмотра, изменяя прозрачность и масштаб изображения. Анимация управляется положением прокрутки. Чтобы создать этот эффект, сначала настройте CSS-анимацию, а затем задайте свойство animation-timeline . В этом случае функция view() со значениями по умолчанию отслеживает изображение относительно области прокрутки (которая в данном случае также является областью просмотра).

Важно учитывать поддержку браузера и пользовательские настройки, особенно в плане доступности. Поэтому используйте правило @supports , чтобы проверить, поддерживает ли браузер анимацию, управляемую прокруткой, и заключите анимацию, управляемую прокруткой, в запрос пользовательских настроек, например @media (prefers-reduced-motion: no-preference) чтобы учитывать предпочтения пользователя в отношении движения. Выполнив эти проверки, вы можете быть уверены, что ваши стили будут работать, и анимация не вызовет проблем у пользователя.

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* Apply scroll-driven animations here */
  }
}

Анимация с прокруткой может подразумевать полноценный прокручиваемый контент, но она также может подразумевать более тонкие анимации, такие как сворачивание заголовка и отображение тени при прокрутке веб-приложения.

Визуальная анимация с прокруткой

Живая демонстрация

@keyframes shrink-name {
  from {
    font-size: 2em;
  }
  to {
    font-size: 1.5em;
  }
}

@keyframes add-shadow {
  from {
    box-shadow: none;
  }
  to {
    box-shadow: 0 4px 2px -2px gray;
  }
}

header {
  animation: add-shadow linear both;
}

h2 {
  animation: shrink-name linear both;
}

header, h2 {
  animation-timeline: scroll();
  animation-range: 0 150px;
}

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

Преимущества производительности анимации с помощью прокрутки

Этот встроенный API снижает нагрузку на код, который вам пришлось бы поддерживать, будь то написанный вами собственный скрипт или добавление дополнительной сторонней зависимости. Он также устраняет необходимость в поставке различных наблюдателей прокрутки, что обеспечивает существенный выигрыш в производительности. Это связано с тем, что анимация, управляемая прокруткой, работает вне основного потока при анимации свойств, которые можно анимировать в компоновщике, таких как преобразования и прозрачность, независимо от того, используете ли вы новый API напрямую в CSS или с помощью хуков JavaScript.

Недавно Tokopedia использовала анимацию, управляемую прокруткой , чтобы панель навигации по товарам появлялась при прокрутке. Использование этого API дало ряд серьёзных преимуществ как для управления кодом, так и для производительности.

Анимация, управляемая прокруткой, управляет панелью навигации по продуктам на Tokopedia по мере прокрутки страницы вниз.

«Нам удалось сократить количество строк кода на 80% по сравнению с использованием традиционных событий прокрутки JS, и мы заметили, что средняя загрузка процессора при прокрутке снизилась с 50% до 2%. — Энди Вихалим, старший инженер-программист Tokopedia»

Будущее эффектов прокрутки

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

В будущем в браузерах появится ещё больше функций прокрутки. В следующем демо показано сочетание этих будущих функций. Для установки начальной даты и времени в элементах выбора используется CSS scroll-start-target , а для обновления даты в заголовке — событие JavaScript scrollsnapchange , что упрощает синхронизацию данных с событием привязки.

Посмотрите живую демонстрацию на Codepen

Вы также можете использовать это для обновления средства выбора в режиме реального времени с помощью события JavaScript scrollsnapchanging .

Эти конкретные функции в настоящее время доступны только в Canary за флагом, однако они открывают возможности, которые ранее было невозможно или было очень сложно реализовать на платформе, и подчеркивают будущие возможности взаимодействия на основе прокрутки.

Чтобы узнать больше о начале работы с анимацией, управляемой прокруткой, наша команда только что запустила новую серию видеороликов, доступную на канале Chrome for Developers на YouTube . Здесь вы узнаете об основах анимации, управляемой прокруткой, от Брамуса Ван Дамма, включая принципы работы этой функции, терминологию, различные способы создания эффектов и способы их комбинирования для создания насыщенного контента. Это отличная серия видеороликов, которую стоит посмотреть.

Просмотр переходов

Мы только что рассмотрели новую мощную функцию анимации на веб-страницах, но есть также и мощная новая функция под названием «переходы между представлениями», которая позволяет создавать анимацию между представлениями страниц и создавать плавный пользовательский интерфейс. Переходы между представлениями выводят веб на новый уровень гибкости, позволяя создавать плавные переходы между различными представлениями на одной странице или даже между разными страницами.

Browser Support

  • Хром: 111.
  • Край: 111.
  • Firefox: 144.
  • Сафари: 18.

Source

Airbnb — одна из компаний, которая уже экспериментирует с интеграцией переходов между видами в свой пользовательский интерфейс для плавной и бесперебойной навигации. Это включает в себя боковую панель редактора объявлений, редактирование фотографий и добавление удобств — всё это в рамках гибкого пользовательского интерфейса.

Переход между представлениями одного и того же документа, как на Airbnb .
Портфолио Максвелла Барвиана , демонстрирующее переходы между видами.

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

Способ быстрой реализации переходов представлений в одностраничном приложении так же прост, как обернуть взаимодействие с помощью document.startViewTransition и убедиться, что каждый элемент, который переходит, имеет view-transition-name , встроенный или динамический с помощью JavaScript при создании узлов DOM.

Демонстрационный визуальный пример

Живая демонстрация

document.querySelectorAll('.delete-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    document.startViewTransition(() => {
      btn.closest('.card').remove();
    });
  })
});
/* Styles for the transition animation */
::view-transition-old(.card):only-child {
  animation: fade-out ease-out 0.5s;
}

Просмотреть переходные классы

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

Browser Support

  • Хром: 125.
  • Край: 125.
  • Firefox: 144.
  • Сафари: 18.2.

Source

Посмотреть типы переходов

Ещё одним важным улучшением для переходов между представлениями стала поддержка типов переходов между представлениями . Типы переходов между представлениями полезны, когда требуется другой визуальный переход между представлениями при анимации переходов между представлениями страниц.

Browser Support

  • Хром: 125.
  • Край: 125.
  • Firefox: 144.
  • Сафари: 18.

Source

Например, вам может понадобиться, чтобы анимация главной страницы переходила к странице блога иначе, чем анимация страницы блога обратно к главной. Или вам может понадобиться, чтобы страницы сменялись по-разному, как в этом примере, слева направо и наоборот. Раньше это было неудобно делать. Можно было добавить классы в DOM для применения стилей, а затем удалить их. Типы переходов (view-transition-types) позволяют браузеру очищать старые переходы, не требуя от вас делать это вручную перед запуском новых, выполняя эту работу за вас.

Запись демонстрации пагинации . Типы определяют, какую анимацию использовать. Стили разделены в таблице стилей благодаря активным типам переходов.

Вы можете настроить типы в функции document.startViewTransition , которая теперь принимает объект. update — это функция обратного вызова, которая обновляет DOM, а types — это массив с типами.

document.startViewTransition({
  update: myUpdate,
  types: ['slide', 'forwards']
})

Переходы между многостраничными представлениями

Мощь интернета заключается в его обширности. Многие приложения представляют собой не просто одностраничный проект, а целую мозаику из нескольких страниц. Именно поэтому мы так рады сообщить о добавлении поддержки переходов между представлениями документов для многостраничных приложений в Chromium 126.

Browser Support

  • Хром: 126.
  • Край: 126.
  • Firefox: не поддерживается.
  • Сафари: 18.2.

Source

Этот новый набор функций для работы с разными документами включает веб-опыты, которые находятся в одном и том же источнике, например, переход с web.dev на web.dev/blog, но сюда не входит навигация между источниками, например, переход с web.dev на blog.web.dev или на другой домен, например, google.com.

Одно из ключевых отличий переходов между представлениями в пределах одного документа заключается в том, что вам не нужно заключать переход в document.startViewTransition() . Вместо этого включите обе страницы, участвующие в переходе, используя CSS-правило @view-transition .

@view-transition {
  navigation: auto;
}

Для более индивидуального эффекта можно подключить JavaScript, используя новые прослушиватели событий pageswap или pagereveal , которые предоставляют доступ к объекту перехода представления.

С помощью pageswap вы можете внести некоторые изменения в последнюю минуту на исходной странице прямо перед тем, как будут сделаны старые снимки, а с помощью pagereveal настроить новую страницу до того, как она начнет отображаться после инициализации.

window.addEventListener('pageswap', async (e) => {
    // ...
});

window.addEventListener('pagereveal', async (e) => {
    // ...
});
Демонстрация переходов между представлениями в многостраничном приложении. См. ссылку на демо .

В будущем мы планируем расширить возможности переходов между представлениями, включая:

  • Переходы с заданной областью действия : позволяют ограничить переход поддеревом DOM, позволяя остальной части страницы оставаться интерактивной и поддерживая несколько переходов представлений, выполняемых одновременно.
  • Переходы между представлениями с помощью жестов : используйте жесты перетаскивания или смахивания для запуска перехода между представлениями документов для более естественного взаимодействия в Интернете.
  • Соответствие навигации в CSS : настройте переход между представлениями между документами непосредственно в CSS в качестве альтернативы использованию событий pageswap и pagereveal в JavaScript. Чтобы узнать больше о переходах представлений для многостраничных приложений, в том числе о том, как наиболее эффективно настроить их с помощью предварительной визуализации, ознакомьтесь со следующим докладом Брамуса Ван Дамма:

Компоненты пользовательского интерфейса на базе движка: упрощение сложных взаимодействий

Разработка сложных веб-приложений — непростая задача, но CSS и HTML постоянно совершенствуются, делая этот процесс гораздо более управляемым. Новые функции и улучшения упрощают создание компонентов пользовательского интерфейса, позволяя вам сосредоточиться на создании качественного пользовательского опыта. Это достигается благодаря совместным усилиям нескольких ключевых органов по стандартизации и групп сообщества, включая рабочую группу CSS, группу сообщества Open UI и WHATWG (рабочую группу по технологиям веб-гипертекстовых приложений).

Одна из самых серьёзных проблем разработчиков — это, казалось бы, простой запрос: возможность стилизации выпадающих меню (элемента select). Хотя на первый взгляд всё кажется простым, это сложная проблема, затрагивающая множество компонентов платформы: от макета и рендеринга до прокрутки и взаимодействия, стилей пользовательского агента и свойств CSS, и даже изменений в самом HTML.

Выберите из списка параметров, содержащих внутри себя кнопку-триггер, стрелку-индикатор и выбранную опцию.
Разбивая части выбранного

Раскрывающийся список состоит из множества частей и включает в себя множество состояний, которые необходимо учитывать, например:

  • Привязки клавиш (для входа/выхода из взаимодействия)
  • Щелкните, чтобы закрыть
  • Активное управление всплывающими окнами (закрытие других всплывающих окон при открытии одного из них)
  • Управление фокусом вкладок
  • Визуализация значения выбранного варианта
  • Стиль взаимодействия со стрелками
  • Управление состоянием (открытие/закрытие)

Сейчас сложно управлять всем этим самостоятельно, но и платформа не упрощает эту задачу. Чтобы исправить это, мы разобрали эти элементы и предлагаем несколько простых функций, которые позволят не только стилизовать выпадающие списки, но и многое другое.

API Popover

Сначала мы добавили глобальный атрибут popover , который, я рад сообщить, несколько недель назад достиг статуса Baseline New Available.

Browser Support

  • Хром: 114.
  • Край: 114.
  • Firefox: 125.
  • Сафари: 17.

Source

Элементы всплывающего окна скрыты с помощью display: none до тех пор, пока не будут открыты с помощью вызывающего элемента, например кнопки, или с помощью JavaScript. Чтобы создать простой всплывающий элемент, установите атрибут popover для элемента и свяжите его идентификатор с кнопкой с помощью popovertarget . Теперь кнопка является вызывающим элементом.

Демонстрационный визуальный пример

Живая демонстрация

<button popovertarget="my-popover">Open Popover</button>

<div id="my-popover" popover>
  <p>I am a popover with more information.</p>
</div>

Благодаря включенному атрибуту popover браузер обрабатывает множество ключевых действий без дополнительных скриптов, в том числе:

  • Продвижение на верхний слой. : Отдельный слой над остальной частью страницы, поэтому вам не придется экспериментировать с z-index .
  • Функция скрытия подсветки. : Щелчок за пределами области всплывающего окна закроет всплывающее окно и вернет фокус.
  • Управление фокусом вкладок по умолчанию. : При открытии вспомогательного окна следующая вкладка останавливается внутри вспомогательного окна.
  • Встроенные привязки клавиатуры. : Нажатие клавиши esc или двойное нажатие закроет всплывающее окно и вернет фокус.
  • Привязки компонентов по умолчанию. Браузер семантически связывает всплывающее окно с его триггером.
Домашний экран GitHub
Меню на домашней странице GitHub .

Возможно, вы уже пользуетесь этим API всплывающих окон, даже не подозревая об этом. GitHub реализовал всплывающее окно в меню «Новости» на своей главной странице и в обзоре пул-реквестов. Они постепенно улучшили эту функцию, используя полифил поповера , созданный Oddbird при значительной поддержке Кейта Циркеля из GitHub, для поддержки старых браузеров.

«Нам удалось сделать устаревшими буквально тысячи строк кода, перейдя на Popover. Popover помогает нам, избавляя от необходимости бороться с магическими числами Z-индекса... Наличие правильного дерева доступности, установленного с помощью декларативного поведения кнопок и встроенных функций фокусировки, значительно упрощает для нашей системы проектирования правильную реализацию шаблонов». — Кит Циркель, инженер-программист, GitHub

Анимация эффектов входа и выхода

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

Возможность анимировать display и content-visibility на временной шкале ключевых кадров.

Свойство transition-behavior с ключевым словом allow-discrete позволяет разрешать переходы дискретных свойств, таких как display .

Browser Support

  • Хром: 117.
  • Край: 117.
  • Firefox: 129.
  • Сафари: 17.4.

Source

Правило @starting-style для анимации эффектов входа из display: none в верхний слой .

Browser Support

  • Хром: 117.
  • Край: 117.
  • Firefox: 129.
  • Сафари: 17.5.

Source

Свойство наложения для управления поведением верхнего слоя во время анимации.

Browser Support

  • Хром: 117.
  • Край: 117.
  • Firefox: не поддерживается.
  • Safari: не поддерживается.

Source

Эти свойства применимы к любому элементу, который вы анимируете в верхнем слое, будь то всплывающее окно или диалоговое окно. В целом, для диалогового окна с фоном это выглядит так:

Демонстрационный визуальный пример

Живая демонстрация

dialog, ::backdrop{
  opacity: 0;
  transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}

[open], [open]::backdrop {
  opacity: 1;
}

@starting-style {
  [open], [open]::backdrop {
    opacity: 0;
  }
}

Сначала настройте @starting-style , чтобы браузер знал, какие стили следует использовать для анимации этого элемента в DOM. Это делается как для диалогового окна, так и для фона. Затем задайте стили открытого состояния для диалогового окна и фона. Для диалогового окна используется атрибут open , а для всплывающего окна — псевдоэлемент ::popover-open . Наконец, анимируйте opacity , display и overlay с помощью ключевого слова allow-discrete чтобы включить режим анимации, в котором дискретные свойства могут изменяться.

Позиционирование якоря

Всполовер был только началом истории. Очень интересным обновлением является поддержка позиционирования якорей , начиная с Chrome 125.

Browser Support

  • Хром: 125.
  • Край: 125.
  • Firefox: не поддерживается.
  • Сафари: 26.

Source

Используя позиционирование с помощью якорей, всего несколькими строками кода браузер может реализовать логику привязки позиционируемого элемента к одному или нескольким якорным элементам. В следующем примере простая подсказка привязана к каждой кнопке, расположенной внизу по центру.

Демонстрационный визуальный пример

Живая демонстрация

Настройте позиционирование якоря в CSS, используя свойство anchor-name элемента привязки (в данном случае кнопки) и свойство position-anchor позиционируемого элемента (в данном случае подсказки). Затем примените абсолютное или фиксированное позиционирование относительно якоря с помощью функции anchor() . Следующий код позиционирует верхнюю часть подсказки относительно нижней части кнопки.

.anchor {
  anchor-name: --my-anchor;
}

.positioned {
  position: absolute;
  position-anchor: --my-anchor;
}

В качестве альтернативы можно использовать имя якоря непосредственно в функции якоря, пропустив свойство position-anchor . Это может быть полезно при привязке к нескольким элементам.

.anchor {
  anchor-name: --my-anchor;
}

.positioned {
  position: absolute;
  top: anchor(--my-anchor bottom);
}

Наконец, используйте новое ключевое слово anchor-center для свойств justify и align чтобы центрировать позиционируемый элемент относительно его якоря.

.anchor {
  anchor-name: --my-anchor;
}

.positioned {
  position: absolute;
  top: anchor(--my-anchor bottom);
  justify-self: anchor-center;
}

Хотя позиционирование якоря с помощью поповера очень удобно, наличие поповера определённо не является обязательным условием для использования позиционирования якоря. Позиционирование якоря можно использовать с любыми двумя (или более) элементами для создания визуальной связи. Более того, в следующем демо, вдохновлённом статьёй Романа Комарова , показано, как подчёркивание закрепляется за элементами списка при наведении на них курсора или нажатии клавиши Tab.

Демонстрационный визуальный пример

Живая демонстрация

В этом примере функция якоря используется для настройки положения якоря с использованием физических свойств left , right и bottom . При наведении курсора на одну из ссылок целевой якорь изменяется, и браузер сдвигает его, применяя позиционирование, одновременно анимируя цвет для создания интересного эффекта.

ul::before {
  content: "";
  position: absolute;
  left:   anchor(var(--target) left);
  right:  anchor(var(--target) right);
  bottom: anchor(var(--target) bottom);
  ...
}

li:nth-child(1) { --anchor: --item-1 }
ul:has(:nth-child(1) a:is(:hover, :focus-visible)) {
  --target: --item-1;
  --color: red;
}

позиционирование inset-area

Помимо абсолютного позиционирования по направлению по умолчанию, которое вы, вероятно, использовали ранее, добавлен новый механизм макета, который стал частью API позиционирования якорей, называемый областью вставки (inset area). Область вставки упрощает размещение позиционируемых элементов относительно соответствующих якорей и работает на сетке из 9 ячеек с элементом вставки в центре. Например, inset-area: top помещает позиционируемый элемент вверху, а inset-area: bottom — внизу.

Упрощенная версия первой демонстрации якоря выглядит так с inset-area :

.anchor {
  anchor-name: --my-anchor;
}

.positioned {
  position: absolute;
  position-anchor: --my-anchor;
  inset-area: bottom;
}

Вы можете комбинировать эти позиционные значения с ключевыми словами span, чтобы начать с центрального положения и затем либо растянуться влево, либо вправо, либо растянуться полностью, чтобы охватить все доступные столбцы или строки. Вы также можете использовать логические свойства. Чтобы упростить визуализацию и освоение этого механизма макета, ознакомьтесь с этим инструментом в Chrome 125+:

Поскольку эти элементы закреплены, позиционируемый элемент динамически перемещается по странице вместе с перемещением своего якоря. Таким образом, в данном случае мы имеем карточные элементы, стилизованные под контейнерные запросы, размер которых изменяется в зависимости от их собственного размера (чего нельзя было сделать с помощью медиазапросов), а закрепленное меню будет смещаться вместе с новым макетом по мере изменения пользовательского интерфейса карточки.

Демонстрационный визуальный пример

Живая демонстрация

Динамические позиции якоря с position-try-options

Меню и навигацию по подменю гораздо проще создавать, комбинируя позиционирование с помощью всплывающих окон и якорей. Когда вы достигаете края области просмотра с помощью якорного элемента, вы можете позволить браузеру изменить его положение. Это можно сделать несколькими способами. Первый — создать собственные правила позиционирования. В этом случае подменю изначально располагается справа от кнопки «Витрина». Но вы можете создать блок @position-try на случай, если справа от меню недостаточно места, задав ему идентификатор --bottom . Затем вы подключаете этот блок @position-try к якорю с помощью position-try-options .

Теперь браузер будет переключаться между этими состояниями, сначала пытаясь занять правильное положение, а затем перемещаясь вниз. И это можно сделать с помощью красивого перехода.

Демонстрационный визуальный пример

Живая демонстрация

#submenu {
  position-anchor: --submenu;
  top: anchor(top);
  left: anchor(right);
  margin-left: var(--padding);

  position-try-options: --bottom;

  transition: top 0.25s, left 0.25s;
  width: max-content;
}

@position-try --bottom {
  top: anchor(left);
  left: anchor(bottom);
  margin-left: var(--padding);
}

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

position-try-options: flip-block, flip-inline;

Для простого перелистывания используйте эти ключевые слова Flip и полностью откажитесь от написания определения position-try . Таким образом, теперь вы можете создать полнофункциональный элемент с якорным позиционированием, реагирующий на местоположение, всего с помощью нескольких строк CSS.

Демонстрационный визуальный пример

Живая демонстрация

.tooltip {
  inset-area: top;
  position-try-options: flip-block;
}

Узнайте больше об использовании позиционирования якоря .

Будущее многослойного пользовательского интерфейса

Мы видим привязанный опыт повсюду, и набор функций, представленный в этой статье, — отличное начало для раскрытия творческих возможностей и лучшего контроля над элементами с якорным позиционированием и многоуровневыми интерфейсами. Но это только начало. Например, в настоящее время popover работает только с кнопками в качестве вызывающего элемента или с помощью JavaScript. Для чего-то вроде превью в стиле Википедии, шаблона, распространенного на всех веб-платформах, необходимо обеспечить возможность взаимодействия с ним, а также возможность вызова всплывающего окна по ссылке или при появлении интересующего пользователя без необходимости клика по ссылке, например, при наведении курсора или фокусе на вкладке.

В качестве следующего шага для API всплывающих окон мы работаем над interesttarget , чтобы удовлетворить эти потребности и упростить воссоздание подобных впечатлений с помощью встроенных механизмов доступности. Это сложная проблема доступности, требующая решения, с большим количеством открытых вопросов относительно идеального поведения, но решение и нормализация этой функциональности на уровне платформы должны улучшить эти впечатления для всех.

<a interesttarget="my-tooltip">Hover/Focus to show the tooltip</a>

<span popover=hint id="my-toolip">This is the tooltip</span>

Кроме того, есть еще один ориентированный на будущее общий invoketarget , доступный для тестирования в Canary благодаря работе двух сторонних разработчиков, Кейта Сиркеля и Люка Уорлоу. invoketarget поддерживает декларативный интерфейс разработчика, который popovertarget предоставляет в виде всплывающих окон, нормализованных для всех интерактивных элементов, включая <dialog> , <details> , <video> , <input type="file"> и другие.

<button invoketarget="my-dialog">
  Open Dialog
</button>

<dialog id="my-dialog">
  Hello world!
</dialog>

Мы знаем, что существуют сценарии использования, которые пока не охватываются этим API. Например, стилизация стрелки, соединяющей закреплённый элемент с его якорем, особенно при изменении положения закреплённого элемента, а также возможность элемента «скользить» и оставаться в области просмотра, а не привязываться к другой заданной позиции при достижении им ограничивающей рамки. Поэтому, хотя мы и рады появлению этого мощного API, мы также с нетерпением ждём возможности дальнейшего расширения его возможностей в будущем.

Стилизуемый выбор

Используя совместно popover и anchor , команда добилась прогресса в реализации настраиваемого выпадающего списка выбора. Хорошая новость в том, что прогресс был значительным. Плохая новость в том, что этот API пока находится в экспериментальном состоянии. Тем не менее, я рад поделиться несколькими демонстрациями в режиме реального времени и новостями о нашем прогрессе, а также надеюсь получить ваши отзывы. Во-первых, был достигнут прогресс в предоставлении пользователям нового, настраиваемого опыта выбора. Текущий, находящийся в разработке способ сделать это — использовать свойство внешнего вида в CSS, установив его в appearance: base-select . После установки внешнего вида вы подключитесь к новому, настраиваемому опыту выбора.

select {
  appearance: base-select;
}

Помимо appearance: base-select , добавлено несколько новых обновлений HTML. Среди них — возможность заключать параметры в datalist для настройки и добавлять в параметры произвольный неинтерактивный контент, например изображения. Вы также получите доступ к новому элементу <selectedoption> , который будет отображать содержимое параметров, которое вы затем сможете настроить по своему усмотрению. Этот элемент действительно удобен.

Демонстрационный визуальный пример

демонстрация флага

Живая демонстрация

<select>
  <button type=popover>
    <selectedoption></selectedoption>
  </button>
  <datalist>
    <option value="" hidden>
      <p>Select a country</p>
    </option>
    <option value="andorra">
      <img src="Flag_of_Andorra.svg" />
      <p>Andorra</p>
    </option>
    <option value="bolivia">
      <img src="Flag_of_Bolivia.svg" />
      <p>Bolivia</p>
    </option>
...
  </datalist>
</select>

Следующий код демонстрирует настройку <selectedoption> в пользовательском интерфейсе Gmail, где визуальный значок отображает выбранный тип ответа для экономии места. Вы можете использовать базовые стили отображения внутри selectedoption чтобы отличать стили отображения варианта от стиля предварительного просмотра. В этом случае текст, отображаемый в варианте, может быть визуально скрыт в selectedoption .

Демонстрационный визуальный пример

демо-версия Gmail

Живая демонстрация

selectedoption .text {
  display: none;
}

Одно из главных преимуществ повторного использования элемента <select> для этого API — обратная совместимость. В этом варианте выбора страны вы увидите настраиваемый пользовательский интерфейс с изображениями флагов в параметрах, что упрощает анализ контента. Поскольку неподдерживаемые браузеры будут игнорировать непонятные им строки, такие как пользовательская кнопка, список данных, выбранный параметр и изображения в параметрах, резервный вариант будет аналогичен текущему интерфейсу выбора по умолчанию.

Неподдерживаемый браузер получает текущий избранный опыт.
Поддерживаемый браузерный вариант слева и неподдерживаемый браузерный вариант справа.

Благодаря настраиваемым параметрам выбора возможности безграничны. Мне особенно нравится этот селектор стран в стиле Airbnb, потому что он продуман и адаптирован для адаптивного дизайна. Вы сможете сделать это и многое другое с помощью готовящегося к выходу стилизованного селектора, что делает его столь необходимым дополнением к веб-платформе.

Демонстрационный визуальный пример

Живая демонстрация

Эксклюзивный аккордеон

Решение проблемы выбора стиля (и всех сопутствующих элементов) — не единственный компонент пользовательского интерфейса, над которым работала команда Chrome. Первым дополнительным обновлением компонента стала возможность создавать эксклюзивные аккордеоны, в которых одновременно может быть открыт только один элемент аккордеона.

Browser Support

  • Хром: 120.
  • Край: 120.
  • Firefox: 130.
  • Сафари: 17.2.

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

Эксклюзивная демо-версия аккордеона
<details name="learn-css" open>
  <summary>Welcome to Learn CSS!</summary>
</details>

<details name="learn-css">
  <summary>Box Model</summary>
  <p>...</p>
</details>

<details name="learn-css">
  <summary>Selectors</summary>
  <p>...</p>
</details>

:user-valid и :user-invalid

Ещё одним улучшением компонентов пользовательского интерфейса стали псевдоклассы :user-valid и :user-invalid . Псевдоклассы :user-valid и :user-invalid которые в последнее время поддерживаются во всех браузерах, ведут себя аналогично псевдоклассам :valid и :invalid , но сопоставляются с элементом управления формы только после того, как пользователь существенно взаимодействовал с полем ввода. Это означает, что для определения того, взаимодействовал ли пользователь со значением формы или оно стало «грязным», требуется значительно меньше кода, что может быть очень полезно для обеспечения обратной связи с пользователем и сокращает объём скриптов, необходимых для этого ранее.

Browser Support

  • Хром: 119.
  • Край: 119.
  • Firefox: 88.
  • Сафари: 16.5.

Source

Демонстрационный скринкаст

Живая демонстрация

input:user-valid,
select:user-valid,
textarea:user-valid {
    --state-color: green;
    --bg: linear-gradient(...);
}

input:user-invalid,
select:user-invalid,
textarea:user-invalid {
    --state-color: red;
    --bg: linear-gradient(...);
}

Узнайте больше об использовании псевдоэлементов проверки формы user-* .

field-sizing: content

Ещё одно удобное обновление компонента, появившееся недавно, — это field-sizing: content , которое можно применять к элементам управления форм, таким как поля ввода и текстовые области. Это позволяет увеличивать (или уменьшать) размер поля ввода в зависимости от его содержимого. field-sizing: content может быть особенно полезен для текстовых областей, поскольку вам больше не придётся ограничиваться фиксированными размерами, из-за которых вам может потребоваться прокручивать страницу, чтобы увидеть, что вы написали в предыдущих частях запроса в слишком маленьком поле ввода.

Browser Support

  • Хром: 123.
  • Край: 123.
  • Firefox: не поддерживается.
  • Предварительный просмотр технологии Safari: поддерживается.

Source

Демонстрационный скринкаст

Живая демонстрация

textarea, select, input {
  field-sizing: content;
}

Узнайте больше о размерах полей .

<hr> в <select>

Возможность включения элемента <hr> (горизонтальной линии) в элементах select — ещё одна небольшая, но полезная функция компонента. Хотя семантическая польза от неё невелика, она помогает аккуратно разделить контент в списке select, особенно тот, который не обязательно группировать с помощью optgroup, например, значение-заполнитель.

Выбрать снимок экрана

снимок экрана hr в избранном со светлой и темной темой в Chrome

Выбрать живую демонстрацию

<select name="majors" id="major-select">
  <option value="">Select a major</option>
  <hr>
  <optgroup label="School of Fine Arts">
    <option value="arthist">
Art History
  </option>
  <option value="finearts">
    Fine Arts
  </option>
...
</select>

Узнайте больше об использовании hr в select

Улучшение качества жизни

Мы постоянно совершенствуем интерфейс, и это касается не только взаимодействия и компонентов. За последний год появилось множество других обновлений, повышающих качество жизни.

Вложенность с просмотром вперед

В прошлом году встроенная вложенность CSS появилась во всех браузерах, и с тех пор она улучшилась, добавив поддержку предпросмотра, что означает, что использование символа & перед именами элементов больше не является обязательным. Благодаря этому вложенность стала гораздо более эргономичной и похожей на то, к чему я привык раньше.

Browser Support

  • Хром: 120.
  • Край: 120.
  • Firefox: 117.
  • Сафари: 17.2.

Source

Одна из моих любимых особенностей вложенности CSS — это возможность визуально блокировать компоненты, а внутри этих компонентов включать состояния и модификаторы, такие как запросы контейнеров и медиазапросы. Раньше я обычно группировал все эти запросы внизу файла для большей специфичности. Теперь вы можете писать их в понятном виде, рядом с остальным кодом.

.card {
  /* card base styles */

  h2 {
    /* child element style */
  }

  &.highlight {
    /* modifier style */
  }

  &:hover, &:focus {
    /* state styles */
  }

  @container (width >= 300px) {
    /* container query styles */
  }
}

Выравнивание содержимого для блочной разметки

Ещё одно действительно приятное изменение — возможность использовать механизмы центрирования, такие как align-content в блочной разметке. Это означает, что теперь можно выполнять такие действия, как вертикальное центрирование внутри div-элемента, без необходимости применять Flex или Grid-разметку и без побочных эффектов, таких как предотвращение схлопывания полей, которые могут быть нежелательны при использовании этих алгоритмов разметки.

Browser Support

  • Хром: 123.
  • Край: 123.
  • Firefox: 125.
  • Сафари: 17.4.

Скриншот

Живая демонстрация

div {
  align-content: center;
}

Обтекание текстом: баланс и красота

Говоря о макете, макет текста получил значительное улучшение с добавлением text-wrap: balance и pretty . text-wrap: balance используется для более однородного блока текста, в то время как text-wrap: pretty фокусируется на уменьшении количества одиночных символов в последней строке текста.

Демонстрационный скринкаст

Живая демонстрация

В следующем демо вы можете сравнить, перетаскивая ползунок, эффекты balance и pretty для заголовка и абзаца. Попробуйте перевести демо на другой язык!
h1 {
  text-wrap: balance;
}

Узнайте больше о text-wrap: balance .

Международные обновления типографики

Обновления типографской разметки для функций текста CJK получили много приятных обновлений за последний год, например, функцию word-break: auto-phrase , которая переносит строку по естественной границе фразы.

Browser Support

  • Хром: 119.
  • Край: 119.
  • Firefox: не поддерживается.
  • Safari: не поддерживается.

word-break: auto-phrase переносит строку по естественной границе фразы.
Сравнение word-break: normal и word-break: auto-phrase

И text-spacing-trim , который применяет кернинг между знаками препинания для улучшения читаемости китайской, японской и корейской типографики и получения более визуально приятных результатов.

Browser Support

  • Хром: 123.
  • Край: 123.
  • Firefox: не поддерживается.
  • Safari: не поддерживается.

Source

Правая половина точки CJK удаляется с помощью text-spacing-trim.
Если знаки препинания стоят подряд, правая половина точки CJK должна быть удалена.

Относительный синтаксис цвета

В мире цветовых тем мы увидели большое обновление относительного синтаксиса цветов.

В этом примере цвета используют тему на основе Oklch. По мере изменения значения оттенка в зависимости от ползунка изменяется вся тема. Этого можно добиться с помощью относительного цветового синтаксиса. Фон использует основной цвет на основе оттенка и корректирует каналы яркости, насыщенности и оттенка для изменения его значения. --i — это индекс уровня в списке для градации значений, показывающий, как можно комбинировать пошаговое управление с пользовательскими свойствами и относительным цветовым синтаксисом для создания тем.

Демонстрационный скринкаст

Живая демонстрация

В следующем демо вы можете сравнить, перетаскивая ползунок, эффекты balance и pretty для заголовка и абзаца. Попробуйте перевести демо на другой язык!
:root {
  --hue: 230;
  --primary: oklch(70% .2 var(--hue));
}

li {
  --_bg: oklch(from var(--primary)
    calc(l - (var(--i) * .05))
    calc(c - (var(--i) * .01))
    calc(h - (var(--i) + 5)));
}

функция light-dark()

Благодаря функции light-dark() темизация стала гораздо более динамичной и упрощенной.

Browser Support

  • Хром: 123.
  • Край: 123.
  • Firefox: 120.
  • Safari: 17.5.

Source

The light-dark() function is an ergonomic improvement that simplifies color theming options so that you can write theme styles in a more concise way, as demonstrated so nicely in this visual diagram by Adam Argyle. Before, you would need two different blocks of code, (your default theme and a user preference query), to set up theme options. Now, you can write these style options for both light and dark themes in the same line of CSS using the light-dark() function.

Visualization of light-dark() . See demo for more.
html {
  color-scheme: light dark;
}

button {
    background-color: light-dark(lightblue, darkblue);
}

If the user selected a light theme, the button will have a light blue background. If the user selected a dark theme, the button will have a dark blue background.

:has() selector

And I would be remiss to talk about modern UI without mentioning one of the most impactful interop highlights from the past year, which has to be the :has() selector, landing across browsers in December of last year. This API is a game-changer for writing logical styles.

Browser Support

  • Chrome: 105.
  • Край: 105.
  • Firefox: 121.
  • Сафари: 15.4.

Source

The :has() selector enables you to check if a child element has specific children, or if those children are in a specific state, and essentially can function as a parent selector as well.

Demo of has() being used to style comparison blocks on Tokopedia .

:has() has already shown to be particularly useful for many companies , including PolicyBazaar, who use :has() to style blocks based on their interior content, such as in the compare section, where the style adjusts if there is a plan to compare in the block, or if its empty.

“With the :has() selector, we were able to eliminate JavaScript based validation of the user's selection and replace it with a CSS solution which is working seamlessly for us with the same experience as before.–Aman Soni, Tech Lead, PolicyBazaar”

Контейнерные запросы

Another key addition to the web that is now newly available and growing in usage is container queries, which enable the ability to query an element parent's intrinsic size to apply styles: a much more fine-toothed comb than media queries, which only query the viewport size.

Browser Support

  • Chrome: 105.
  • Край: 105.
  • Firefox: 110.
  • Safari: 16.

Source

Angular recently launched a beautiful new documentation site on angular.dev using container queries to style the header blocks based on their available space on the page. So even if the layout changes, and goes from a multicolumn sidebar layout to a single-column layout, the header blocks can self-adjust.

Angular.dev site showcasing container queries in the header cards.

Without container queries, doing something like this was quite hard to achieve, and damaging for performance, requiring resize observers and element observers. Now, it's trivial to style an element based on its parent size.

Demo Screencast

Живая демонстрация

Recreating the Angular header card container query.

@property

And finally very soon, we are excited to see @property land in Baseline. This is a key feature for providing semantic meaning to CSS custom properties (also known as CSS variables), and enables a slew of new interaction features. @property also enables contextual meaning, typechecking, defaults, and fallback values in CSS. Opening the doors for even more robust features like range style queries. This is a feature that was never possible before, and now provides so much depth to the language of CSS.

Browser Support

  • Chrome: 85.
  • Edge: 85.
  • Firefox: 128.
  • Safari: 16.4.

Source

Demo Screencast

Живая демонстрация

@property --card-bg {
  syntax: "<color>";
  inherits: false;
  initial-value: #c0bae8;
}

Заключение

With all of these new powerful UI capabilities landing across browsers, the possibilities are endless. Novel interactive experiences with scroll-driven animations and view transitions make the web more fluid and interactive in ways we've never seen before. And next level UI components make it easier than ever to build robust, beautifully customized components without ripping out the entire native experience. And finally, quality of life improvements in architecture, layout, typography, and responsive design not only solve the little big things, but also give developers the tools they need to build complex interfaces that work on a variety of devices, form factors, and user needs.

These new features you should be able to remove third-party scripting for performance-heavy features like scrollytelling and tethering elements to each other with anchor positioning, build fluid page transitions, finally style dropdowns, and improve the overall structure of your code natively.

It's never been a better time to be a web developer. There hasn't been so much energy and excitement since the announcement of CSS3. Features we've needed but have only dreamed of actually landing in the past, are finally becoming a reality and a part of the platform. And it's because of your voice that we're able to prioritize and finally bring these capabilities to life. We're working on making it easier to do the hard, tedious stuff natively so you can spend more time building the things that matter–like the core features and design details that set your brand apart.

To learn more about these new features as they land, follow along at developer.chrome.com and web.dev, where our team shares the latest news in web technologies. Try out scroll driven animations, view transitions, anchor positioning, or even the stylable select, and let us know what you think. We're here to listen and we're here to help.