Галоўная / Артыкулы

Адаптаванне сучаснага CSS для безпечной роботы: анкіры, сеткавые ляйны, дапамога Scope і функцыя light-dark()

Дазвольце даклэ научыцца, як пазіцыянаванне анкараў, попап-вікна, муравлярная структура з сеткавымі лянамі, пераходы между відзорамі, функцыі light-dark() і @scope заменяюць бібліятэкі JavaScript, а таксама як выкарыстоўваць кожную з іх з альтернатывамі.

Выдавец: REACTAPP.TOP7 хв чытання1605 слоў

Крыніцы: CSS Can Already Do This. Developers Are Still Scared to Ship It.

Большынства пакетаў фронт-энда яшчэ маюць бібліятэкі, чыя ўзгаледна задача — вылучыць месца для падказак, такія як Floating UI або ўсё той жа Popper, а таксама іншыя бібліятэкі, якія аранжуюць карточкі у сетку у стыле Pinterest. Адныя браузеры тепер можаць выканаць абе ція заведамыя задачы самы, а таксама кальколькі іншых задач, якія раней выкарыстоўвалі JavaScript, пры тым малая колькасць команды ўсё ж зняла гэтыя залежнасці. У гэтым кансультатывным матэрыяле рассказваецца пра пяць функцыяй CSS, якія можуць заменіць распашчасты код бібліятэкаў, пояснюецца, як кожная з іх працуе, і паказваецца, як ўжываць іх без рызыка з-бягу падтрымкі ў разных браузерах.

Якія жаданыя, але водночас ухіляюцца

Рэзультаты апытакоў дэвелопераў добра падметляюць гэты напянот. У рэзультатах даследжэння «State of CSS» за 2026 год пазычаннікаванне анкараў было выбрана як найболей цікавая новая функцыя для дэвелопераў, заменіўшая :has(), якая зараз настолькі шырока вжываецца, што больш не здаецца новай. У тым жа апытакоўзе таксама спыталі, якія функцыі людзі намеравана адхоўляюць, таму што ўсё яшчэ не верыць у падтрымку з боку прыгледачаў, і пазычаннікаванне анкараў таксама стала лідерам у гэтым списку. Закрыць гэтую прыему значнаю часткай адбываецца за дапамогою функцый, якія працуюць за дапамогою фічар-запытак. Цифры апытакоў і статус падтрымкі быстра зменяюцца, таму трэба спрыймать іх як момантальныя даны і пераканацца ў актуальных данных прыдатнасі пры выкарыстоўванні будзь-якай функцыі.

Пазычаннікаванне анкараў заместо бібліятэкі падказак

Падчынныя методы JavaScript прыкладваюць елемент, який плавае, да свайго трыгеру, вымерваючы абодву вялічыны і пераскладваючы пазыцію з кожнай перезапісу сторанкі чыста ў вялічыну. Пазыціонаванне анкора пераносіць гэтыя взаўзаёмныя зв’язкі ў CSS.

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

.trigger {
  anchor-name: --menu-trigger;
}
.menu {
  position: fixed;
  position-anchor: --menu-trigger;
  top: anchor(bottom);
  left: anchor(center);
  position-try-fallbacks: flip-block, flip-inline;
}

Кожны элемент выпаловае адзін конкрэтны ролю:

  • anchor-name дае элементу ідэнтыфікатор у вигляде пунктыроў, за які іншы элементы можаць пазыціонавацца.
  • position-anchor паведамляе элементу, які знаходзіцца ў пазыцыі, які анкор з заданым іменем ён павінен следаваць.
  • anchor() чытае координаты, такія як нижняя грань анкора чыста ў горизонтальны цэнтр, безпасоверхнева з таго элемента.
  • position-try-fallbacks паказвае альтернатывы, якія выкарыстоўвае браузер, калі элемент можа перапыліць вікнапраэкт; flip-block і flip-inline перавертаюць яго верхняй або горизантальны спакой.
  • Супрацоўка з атрыбутам popover

    Атрыбут popover, які таксама ўключаны, але часта ігноруецца, керуе прыемамі выпадаючага меню: кнопка з popovertarget актывае элемент з адпаведным id, не трэба ніякога скрыпту:

    <button popovertarget="menu">Options</button>
    <div id="menu" popover anchor-name-target="--menu-trigger">...</div>
    

    Будзьце абярожны з гэтым фрагментам: anchor-name-target не ўзьлеглая атрыбут HTML, таму не копіюйце яго такім, які ён. З’яўляйце поп-ап, выкорыстоўваючы CSS і атрыбуты anchor-name та position-anchor, як паказана вышэй. Дзеякія браузеры таксама спрыймаюць кнопку, якая запускае поп-ап, як неявны анкер для поп-апа, адкрытага за дапамой popovertarget; пераканайцеся ў актуальной даследчыцы, прытаму як вы хочаце на гэта раслучыцца.

    Тое, што popover задае ў сваім стандарцы, — это адрасаванне на верхнім слое, таму меню апыяўляецца над усім, без супербора значэння z-index у всім прыкладзе, лёгкае закрыцце, калі корыстувач нажме за межамі або клавішу Escape, і правильна обработка фокуса пад час адкрыцья та закрыцья. Ён не захопляе фокус, як модальны dialog, таму для сапраўдная модальнаяе інфармацыі выкорыстоўвайце dialog у замену.

    Ёсць большая інфармацыя пра API прыгледачаў, якія робяць пакеты npm непатрэбнымі; адзін раз прыгляніце нашаму аптаварысу пра вялікія API прыгледачаў, якія заменяюць популярныя пакеты.

    Натыўнае мазання з сеткавымі лянкамі

    З таго часу, як CSS Grid з’явіўся ў прыгледачах у 2017 годзе, для стварэння мазаных лейаутаў яшчэ быў неабходны JavaScript, і самэ гэта стала прычыной таго, што бібліятэкі на кшталт Masonry і падобныя пакеты былі запусцаны мільйонамі разоў. Адныя гэта зменяецца. Наступная правіла ўтвараюць цэлы лейаут:

    .gallery {
      display: grid-lanes;
      gap: 10px;
      grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    }
    

    Кожная карточка размешчаецца ў тым столбце, які нараз чыяе большайшы прастор, таму элементы розташоўваюцца ўжоўку без неравнамерных празораў. Не існуе ResizeObserver, а таксама няма перакалібравання столбцоў у скрыптазе пасля завершэння загрузкі карточкі. Синтаксіс гэтага элемента стварыўся пасля гадоўых дыскусый між виробнікамі прыгледачаў, калі Apple і Google падтрымвалі розныя падходы, прычым display: grid-lanes стаў компромісам.

    За данымі пра падтрымку на момент напісання, Safari першы ўключыў гэты элемент, тады як Chrome і Firefox заставілі яго ў режыме пробнай роботы. Гэта поясняе, чаму так мало сайтов яго викорыстоўвае, і чаму зараз варта яго реалізаваць. Павінны быць размешчаны grid-lanes у блоке @supports (display: grid-lanes), а як альтэрнатыва — звычайная сетка.

    Пераходы між відобразамі, з высокай абераганосцю

    Хутчэй заўсёды трэба быць астатрактычным. Хоць існуе падтрымка API View Transition, яна ў розных браузерах разніцягаецца, таму гэта явышчаеся сярод найбольш ухілваных функцый, нароўна з пазыціонаваннем анкора, і такая астатракцыя ўсё ж разумна.

    Базавы механізм прост: апошню змяну DOM трэба абгортаваць у document.startViewTransition(), і тады браузер стварае ксэранкі старага і новага стану, пасля чога пераходзіць межы імі плавна, без неабяжнай бібліятэкі анімацый і без ручнага фіксавання стану да і пасля змян. Наступныя псэуда-элементы кантролююць гэты стандартны пераход, тут яго скорачваючы да 0,3 секунды:

    ::view-transition-old(root),
    ::view-transition-new(root) {
      animation-duration: 0.3s;
    }
    

    Сёньдзе можна на яго паложыцца як на метод прагрэсіўнага падвышэння якасці. Браузер, у которам няма данай API, проста пераходзіць у новы стан, таму нічога не ламаецца. Гэта робіць яго безпечным для некритычных момантав, такіх як змена стороніцы або пераранжаванне спісу. У скрыптах паказваецца, каб пераканацца, што document.startViewTransition існуе, прычым яго вызываюць, а ў разе проблем — застосаваць змены без яго.

    Одна палітра для светлага і темнага режыма за дапамою light-dark()

    Тыповы темны режым выкарыстоўвае два цэлых калеровыя системы: адну ў медыа-запите prefers-color-scheme: dark і другую паўтарна. Функцыя light-dark() злучае кожную пару ў адну декларацыю.

    У прыводзе нижэй спачатку задаецца документу оба режымы за дапамою color-scheme, які неабходны для работы light-dark(), а пасля кожнай власці прызначаюцься яе значэння для светлага і темнага режыма паўтарна:

    :root {
      color-scheme: light dark;
    }
    
    body {
      background: light-dark(#ffffff, #1a1a1a);
      color: light-dark(#111111, #eeeeee);
    }
    

    Калі color-scheme ўстановлена, кожны вызов light-dark() дае правильную значэння, якая адпавядае настройкам системы пользователя, і больш не трэба дублюваць запиты да медыя-запісоў у файле стайла. Па іншым способам рэалізаціі темавання можна паглядзець у нашай статыце пра методы рэалізаціі темнага режыму.

    Адгрупаванне стаяў за дапамогою @scope

    Однай з галоўных прычынах викорыстання CSS-у-JS чыстага падчынення BEM є прасачанне спецыфічнасці: правіла .card, прызначаныя для аднаго компонента, таксама стаяляюць некаляжны элемент .card, які знаходзіцца глыбэй у маркапе іншага компонента. @scope натычна обмежвае стаяў толькі ў паддрэве.

    У прыказе нижчэй стаяў параграфаў прыменяюцца ўнутрь .card, але не праходзяць далей да элемента .card-nested:

    @scope (.card) to (.card-nested) {
      p {
        color: var(--card-text);
      }
    }
    

    Першы выбірач задае коран тэриторіі. Клаза to задае нижнюю межу, залишаючы прастор, дзе вкладаны компонент можа кераваць своімі стылямі замест таго, каб спадзяцца ў стылі свайго родніка. Для всьога гэтаго не трэба крока будовы, стварання імен класоў чы JavaScript у час выконання. Гэта не заменіць усё, што робіць CSS-in-JS, напрыклад, стылі, вычысляваныя на адзе з параметраў компонента, але гэта усуне адну з галоўных прычынаў, чаму команды яго адбіраюць.

    Браузер — гэта экасістэма

    Усе пяць функцыяй вже ўсталяныя прынеймна ў аднам рэальным браузеры сёгодні, і ні адна з іх не залежыць ад React, плагіну для бандлера чы выдання фрэймворку. Разлік межы таго, што можа CSS, і таго, што команды выкорыстоўваюць, здарожае пераважна прыzwычкай: прыблізна дзесяць гадоў рашэнне проблемы інтэрфейсу значыла установку пакета.

    Выберыце адзін месца, дзе ваш проект выкарыстоўвае альтернатыўны спосаб на JavaScript для рашэння адной з гэтых проблем, заменіце яго пасля @supports і пагледзіце, што зламаецца. Зазвычай — менш, чым вы спакульвалі.

    Частае запытанні

    Чы ўсталяванне анкера готава да выкарыстання ў прымэтнае робота?

    Яна вже выдана і можа быць выкарыстоўваная сёння пасля пераконтролу @supports. Яе месца ў спісе самых абмежана выкарыстоўваемых функцый паказвае абераганне ў зв’язку з неоднаковым распространенням між прыгледчыкамі, а не брак функцый. Яе союз з альтернатыўным рашэнням, напрыклад простым статычным размешчэнням, ёсць належным рывенем аберагання.

    Чы вам яшчэ патрэбна бібліятэка для мазонкі?

    Для новага проекту, верагодна, няма, за ўмовы, што display: grid-lanes знаходзіцца ў блоке @supports з звычайной сеткой як альтернатывай. Для існуючага лейауту, які выкарыстоўваецца ў прымэтнае робота і мае строгую матрыцу падтрымкі прыгледчыкаў, краща заставіць бібліятэку ў вжыцці яшчо калькі часу.

    Калькі функцыяў калі лепш заўсёды спачатку?

    light-dark(). эта адмена ў аднай лініі для кожнага значэння калеру; на момент напісання яна мела найшырэйшую падтрымку з усіх пяці, а таксама дазволяе адмахнуцца вялікага блака дуплікатаваных CSS-кодав для темнага режыму без рызыку для макета.

    Галоўныя выводы

    • Спрыяйце поступовам удосконаленню кожной функцыяў: викорыстоўвайце натыўнае падзеянне там, дзе яно падтрымванае, а іншыя рашэнні — там, дзе яны вядомы.
    • Пазіцыонаванне анкера паўсюду разам з popover задовольняе большасць патрэб да інфармацыйных панелей та выпадаючых меню, але пры неабходнасці справжняго модальнага вікна наладзіце анкер у CSS і викорыстаўце dialog.
    • grid-lanes та пераходы між відобразамі ўсё яшчэ не ўсталіліся; адключайце іх за дапамогою @supports або пераканальнага чэку падчас выконання.
    • light-dark() та @scope негайна адмахваюцца коду і несу мінімальны рызык.