Привет, Хабр.


В начале января 2025 года мне захотелось посмотреть, какие новые фишки CSS стали поддерживаться современными браузерами за прошлый год. Провести некий срез, что уже можно использовать. И тут меня посетила мысль: «А почему бы не поделиться новинками на Хабре?». Вот я и пришёл.


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


Для составления списка я использовал сайт «Can I Use». Брал те новшества, которые стали «зелёными» в 2024 году. Смотрел последние версии браузеров Chrome, FireFox, Opera, Edge, Safari, iOS Safari, Samsung Internet и Android Browser.


Не буду больше тянуть. Давайте посмотрим, что я вам подготовил.


▍ Значение balance для свойства text-wrap


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


Возьмём заголовки. Как сделать так, чтобы текст в них равномерно распределялся? Для пояснения задачи я создал пример.


<body>
  <main class="content">
    <h1>«Больше никогда не будет такого игрока». Овечкин поразил Америку 874-м голом и рекордом</h1>
    <p>Когда казалось, что Александр Овечкин, забив всего один гол в пяти матчах — да и тот в пустые ворота, вновь попал в кризис, капитан «Вашингтона» вернулся — и как! Грандиозно! Ови забил в овертайме в сухом матче, принеся победу «столичным».</p>
  </main>
</body>

.content {
  box-sizing: border-box;
  max-width: 80rem;
  padding-inline: 1rem;
  margin-inline: auto;
  text-align: center;
}



Получилось так, что последнее слово осталось одиноким в своей строке. Я забыл, как в типографике называется такая ошибка. Вроде «висячие слова». Но я не уверен.


В общем это поведение супер критическое. Меня не раз просили его исправить. В те времена для решения проблемы я прибегал к помощи магии. Теперь есть значение balance для свойства text-wrap.


Не будем долго тянуть и добавим его для заголовка.


h1 {
  text-wrap: balance
}



При значении balance браузеры равномерно распределяют символы между строками. В итоге мы снижаем вероятность появления «висячего слова». А значит наши дизайнеры будут довольны.


▍ CSS-вложенность


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


.awesome-block {
  border: 2px solid lightblue;
  padding: 1rem;
   
  h3 {
    font-size: 3rem;
  }
}

Только у меня для вас сюрприз. Этот код будет работать в браузере. В CSS теперь тоже есть вложенность. Даже символ амперсанда сохранился.


.awesome-block {
  border: 2px solid lightblue;
  padding: 1rem;
   
  &:hover {
    background-color: tomato;
  }
}

Я зашёл с плюсов, чтобы вы подумали: «Вау, как круто!». Конечно, есть и свои минусы. Нельзя использовать амперсанд в названии класса. Несколько видов синтаксиса. Подводные камни в алгоритме работы. Всё это есть.


Но всё же сама фишка зайдёт многим. Появится CSS с «нативной» вложенность, поэтому нам нужно уже начинать изучать её.


▍ Псевдо-классы :user-valid и :user-invalid


При разработке формы есть обязательные поля. Они могут быть заполнены корректно или нет. В CSS для этого есть псевдо-классы :valid и :invalid.


Если честно говорить, то они работают странно. Рассмотрим пример.


<body>
  <form class="form">
    <div class="form__group">
      <label for="name">Введите логин</label>
      <input id="name" type="text" value="melnik909" required>
    </div>	
    <div class="form__group">
      <label for="password">Введите пароль</label>
      <input id="password" type="password" required>
    </div>		
    <button>Войти</button>
  </form>
</body>

input:invalid {
  box-shadow: 0 0 10px red;
}

input:valid {
  box-shadow: 0 0 10px green;
}



Открыв страницу, мы увидим, что браузеры уже добавили зелёную и красную тень к полям. Хотя мы ещё даже не взаимодействовали с ними. Это как раз упущение авторов стандартов. По этой причине псевдо-классы :valid и :invalid были нелюбимы разработчиками.


Хорошо, что это упущение уже исправлено. Появились псевдо-классы :user-valid и :user-invalid. Они не сработают, пока пользователь не начнёт взаимодействовать с полем.


Исправим предыдущий пример, добавив их вместо предыдущих псевдо-классов.


input:user-invalid {
  box-shadow: 0 0 10px red;
}

input:user-valid {
  box-shadow: 0 0 10px green;
}



Уже другое дело! Стили не применились после загрузки страницы. И так будет, пока я не буду взаимодействовать с полем.


▍ Свойство scrollbar-gutter


У меня есть грешок. Меня раздражают «прыжки» контента при открытии и закрытии модальных окон. В рамках этой статьи я не могу показать их. По этой причине я нашёл подходящий пример на сайте Дока.


Почему происходит такое поведение? Обратите внимание на полосу прокрутки браузера. Если модальное окно закрыто — она есть, когда оно открыто — полоса убирается. Такое поведение достигается с помощью значение hidden для свойства overflow, добавленного к элементу <body>. Убирая и добавляя полосу прокрутки, браузеры смещают контент на её ширину. Следовательно, он «прыгает».


Решить эту проблему теперь просто. Появилось свойство scrollbar-gutter, которое управляет пространством, выделяемым под полосу прокрутки. Например, значение stable заранее зарезервирует место под полосу прокрутки.


html,
body {
  scrollbar-gutter: stable;
}

Только посмотрите, как изменилось поведение модального окна. Больше никаких «прыжков».


▍ Математическая функция round()


При вёрстке интерфейсов иногда получаются значения с десятичной частью. Для примера посмотрите на значение у свойства margin в инструментах разработчика.


.box {
  width: 2rem;
  height: 2rem;
  background-color: lightblue;
  box-sizing: border-box;
  margin: 1.25rem;
}



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


В CSS никогда не было возможности округлить значение, а теперь есть специальная функция round(). А самое главное — это значение to-zero. Оно любимо мной, потому что отбрасывает дробную часть.


.box {
  width: 2rem;
  height: 2rem;
  background-color: lightblue;
  box-sizing: border-box;
  margin: round(to-zero, 1.25rem, 1px);
}



Если подойти более серьёзно к вопросу, то функция round() супер полезна. Лично мой любимый способ сочетать её с функцией calc().


▍ Ключевые слова safe и unsafe


Вы же знаете свойства align-items и justify-content? Я уверен, что да. Но, к сожалению, я сомневаюсь в том, что вы слышали об их главной особенности. При позиционировании элементов с помощью этих свойств может обрезаться часть элементов.


Как сказано в стандарте, это происходит, когда дочерние элементы больше по размерам, чем родительский контейнер. Случается переполнение и обрезка элементов, как в моём примере.


.parent {
  width: 20rem;
  height: 5rem;
  background-color: lightblue;
  
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.child {
  width: 150%;
  background-color: tomato;
}



По этой причине авторы стандартов придумали ключевые слова safe и unsafe.


Ключевое слово safe сообщает браузерам, что они должны применить значение start. Это поможет избежать ситуации, когда элемент может быть обрезан в начале.


.parent {
  width: 20rem;
  height: 5rem;
  background-color: lightblue;
  
  display: flex;
  flex-direction: column;
  align-items: safe center;
  justify-content: center;
  overflow: hidden;
}



Ключевое слово unsafe вы наврятли будете задавать. Браузеры сами поймут, что его надо использовать, если вы просто указываете значение для свойств align-items и justify-content.


▍ Свойство align-content


Я хорошо помню времена, когда появились флексбоксы. Поэтому долгое время я считал, что при использовании свойства align-content надо использовать «флексы». Ладно, или «гриды». Так тоже потом стало можно.


А теперь давайте покажу вам магию. Посмотрите в инструменты разработчика на этом скриншоте.




Да! Теперь свойство align-content работает само по себе. Нам не нужно добавлять flex, inline-flex, grid и inline-grid значения для свойства display у родительского элемента. Вот код из моего примера в качестве доказательства.


.container {
  height: 10rem;
  background-color: lightblue;
  align-content: center;
}

.awesome-block {
  background-color: tomato;
}

У нас наконец-то появился способ отцентрировать элемент по вертикали с помощью одного свойства! Теперь все программисты, хейтившие CSS, получили ответ. Я уже думаю выпить за это. Всё-таки десять лет ждал.


▍ Вместо заключения


В рамках этой статьи я рассказал только про те CSS-фишки, пользу которых мог показать в рамках статьи. Но есть ещё те, которые не смог добавить. А они также очень полезны. Поэтому я их перечислю без объяснения.


Обратите, пожалуйста, внимание:

  • на единицу измерения cap, которая рассчитывается относительно высоты заглавных букв;
  • свойство content-visibility, оптимизирующее скорость отображения страницы;
  • свойство transition-behavior, позволяющее анимировать элемент, даже если для него переключается значение для свойства display;
  • математические функции rem() и mod().

Вот теперь обзор закончен. Я вам рассказал всё, что нашёл. Но как я оставлю вас без своей рекомендации? Я так не могу!


Я считаю самыми полезными следующие:

  • значение balance для свойства text-wrap;
  • псевдо-классы :user-valid и :user-invalid;
  • функциюround();
  • свойство scrollbar-gutter;
  • свойство transition-behavior.

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


На этом всё. Спасибо за чтение!


P.S. Помогаю больше узнать про CSS в своём ТГ-канале CSS isn't magic. Присоединяйтесь. Ссылка в профиле.


© 2025 ООО «МТ ФИНАНС»

Telegram-канал со скидками, розыгрышами призов и новостями IT ?

Комментарии (20)


  1. wadowad
    11.02.2025 14:41

    По поводу первого примера: союз "и" практически никогда не должен "отлепляться" от последующего слова (за очень редким исключением). Предлоги так точно нужно переносить вместе со словом, к которому они относятся. Мне кажется, проблему "висячих" союзов и предлогов проще решать неразрывными пробелами. Особенно с таким зоопарком устройств, когда заранее неизвестно какой ширины будет блок с контентом.

    Можно попытаться это дело автоматизировать по словарю предлогов и союзов или, например, договорится с редактором, что двойной пробел будет преобразовываться в неразрывный. Как вариант, банальный фильтр для Wordpress'а:

    function my_title_filter($title) {
    	//замена двойного пробела на неразрывный
    	$title = str_replace('  ', '&nbsp;', $title);
    
    	return $title;
    }
    
    add_filter('the_title', 'my_title_filter');


    1. artptr86
      11.02.2025 14:41

      Двойной пробел как неразрывный при наборе слов, которые должны быть «вместе» на строке, выглядит ещё хуже. Уж лучше тогда как в Латехе использовать тильду (~) в качестве символа неразрывного пробела. В наборе обычных текстов она практически не используется, при этом гораздо нагляднее, чем двойной пробел.


      1. wadowad
        11.02.2025 14:41

        Я руководствовался в первую очередь "обратной совместимостью". Если скрипт не отработает, то в html ничего критичного не произойдёт, т.к. двойной пробел будет считаться за один.

        Да, двойной пробел не очень нагляден, особенно если следующее слово в редакторе переносится на другую строку. Но ничего другого в голову тогда не пришло, а теперь как-то устаканилось.

        Знак тильды спорное решение, потому что нужно переключать раскладку, либо пользоваться комбинациями. По трудозатратам получается равносильно вводу неразрывного пробела Alt+255.


        1. artptr86
          11.02.2025 14:41

          А что означает "если скрипт не отработает"? Это же пхп, а не клиентский жс, если он не отработает, то пользователь вообще ничего не увидит. Кроме того, можно было бы организовать подстановку неразрывных пробелов по словарю и/или регуляркам.


          1. wadowad
            11.02.2025 14:41

            В приведённом выше примере с Wordpress подразумевается, что фильтр "зашит" в functions.php темы, а не оформлен отдельным плагином. При смене темы фильтр может потеряться.


            1. artptr86
              11.02.2025 14:41

              То есть вы поленились написать плагин, захардкодили фильтр в тему, а теперь этим оправдываетесь?

              Безотносительно, замена по словарю всё равно обратно совместима.


              1. wadowad
                11.02.2025 14:41

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

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


    1. Per_Ardua
      11.02.2025 14:41

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

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


      1. gun_dose
        11.02.2025 14:41

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


        1. Per_Ardua
          11.02.2025 14:41

          Тут да, вы правы, в этой задаче LLM будет лишней.

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


          1. gun_dose
            11.02.2025 14:41

            Вообще, для конкретно этой задачи нужен типограф. Это софт, который приводит тексты к определённым стандартам - кавычки-ёлочки, длинные тире (—), убрать двойные пробелы, вставить неразрывные пробелы. И готовых решений для этого просто тьма, начиная от библиотек под любой популярный язык программирования, заканчивая онлайн-сервисами, как у студии Артемия Лебедева.


      1. vanxant
        11.02.2025 14:41

        Нормальные типографы для русского языка, которые убирали висячие строки, заменяли кавычки на лапки и ёлки, дефисы на тире где надо и т.д., появились лет так 20 назад. Без всяких там LLM.


    1. GeorgeTudosi
      11.02.2025 14:41

      Для неразрывного пробела есть символ U+00A0, который прекрасно вводится с помощью типографской раскладки. Уже много лет пользуюсь, и не представляю себе, как без неё люди-то живут :). Кроме пробела, там ещё много полезных символов.

      Но дальше начинается интересное. Например, есть такой «конструктор сайтов» Тильда. Так вот, там программисты специально постарались, чтобы неразрывный пробел автомагически преобразовывался в обычный, а чтобы ввести именно неразрывный пробел, надо набрать #nbsp;. Что?!11 В каком бреду вообще можно было такое придумать?

      И Adobe тоже отличились, вот уж от кого не ожидал. Привычный ⌥+пробел не работает, надо ⌘+⌥+X. Зачем так извращаться? Ну ладно, свой шорткат — понимаю, не у всех раскладка есть. Но чужой-то зачем ломать?


    1. riky
      11.02.2025 14:41

      или договорится с редактором чтобы он сразу ставил неразрывный пробел alt + 0160.
      также можно ему перех сохранением подсказывать места где пропустил (по словарю)


  1. Luzinov
    11.02.2025 14:41

    Классно, но пока 90% пользователей не обновятся до новейших браузеров мы не сможем использовать это в проде.


    1. Azirel
      11.02.2025 14:41

      1. Luzinov
        11.02.2025 14:41

        https://caniuse.com/mdn-css_properties_scrollbar-gutter

        Декабрь 24 вас не смущает?


        1. amakhrov
          11.02.2025 14:41

          Конкретно это правило вполне можно использовать в проде - хуже-то не будет. Большинству браузеров будет лучше, а Сафари продолжит скакать как и раньше.


  1. Sergei_Erjemin
    11.02.2025 14:41

    Я забыл, как в типографике называется такая ошибка. Вроде «висячие слова». Но я не уверен.

    Это называется "вдовы". Одинокие слова на последней строчке параграфа. Это не только в заголовках некрасиво.

    А еще бывают "сироты" -- это одинокие строчки (и даже две или три) которые переползают на новую страницу или колонку (ну или остаются на предыдущей странице или колонке). За таким тоже надо следить.

    А еще бывают "колодцы". Это когда на нескольких строчках подряд пробелы между словами выстраиваются вертикально (это действительно выглядит как колодец). Как с этим бороться в веб-верстке пока не придумано (по крайне мере не придумано мной).


    1. melnik909 Автор
      11.02.2025 14:41

      О, спасибо! Буду знать теперь