Стилизация::search-text и другие псевдоэлементы выделения | CSS-трюки

Стилизация::search-text и другие псевдоэлементы выделения | CSS-трюки


хром 144 недавно отправлен ::search-textТеперь это один из многих псевдоэлементов, связанных с подсветкой. При этом выбирается текст поиска на странице, то есть текст, который выделяется при этом. Ctrl/Разрешение + Ф-Введите поисковый запрос на странице, и совпадение будет найдено.

По умолчанию ::search-text Матчи отмечены желтым цветом, а текущая цель (::search-text:current) оранжевый, но ::search-text Позволяет нам изменить его.

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

Различные типы выделения псевдоэлементов

псевдоселектор Выбирает… примечания
::search-text Найдите совпадения на странице ::search-text:current Выбирает текущую цель
::target-text фрагменты текста Фрагменты текста позволяют программно выделять их с помощью параметров URL. Если поисковая система перенаправляет вас на сайт, она может использовать фрагменты текста, поэтому ::target-text легко запутывается ::search-text.
::selection Текст, выделенный с помощью указателя
::highlight() Пользовательские выделения, определенные с помощью API Custom Highlights API JavaScript.
::spelling-error слова с ошибками В основном это относится только к редактируемому контенту.
::grammar-error неправильная грамматика В основном это относится только к редактируемому контенту.

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

Как должно выглядеть выделение псевдоэлементов?

Вопрос в том, все ли они (кроме ::highlight()) имеют стиль по умолчанию, зачем нам выбирать их с помощью псевдоэлементов? Причиной этому является доступность (особенно цветовой контраст) и удобство использования (акцент). Например, если по умолчанию используется желтый фон ::search-text Текст недостаточно контрастирует с цветом или не выделяется на фоне контейнера, возможно, вы захотите его изменить.

Я уверен, что есть много способов решить эту проблему (хотелось бы услышать “Вызов принят” в комментариях), но лучшее решение, которое я придумал, — это использовать синтаксис относительного цвета. Я ошибся с ними обоими. background-clip: text И backdrop-filter: invert(1) Прежде чем мы поймем, почему многие свойства CSS выходят за рамки, когда дело доходит до выделения псевдоэлементов:

body {
  --background: #38003c;
  background: var(--background);

  mark,
  ::selection,
  ::target-text,
  ::search-text {
    /* Match color to background */
    color: var(--background);

    /* Convert to RGB then subtract channel value from channel maximum (255) */
    background: rgb(from var(--background) calc(255 - r) calc(255 - g) calc(255 - b));
  }
}

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

Здесь происходит следующее: я конвертирую цвет фона контейнера в формат RGB, а затем вычитаю значение каждого канала (r, gИ b) с максимальным значением канала 255Инвертирование каждого канала и общего цвета. Затем этот цвет устанавливается в качестве цвета фона выделения, гарантируя, что он будет выделяться в любой ситуации, а благодаря новому CodePen Slideverse вы можете поиграться с демо-версией, чтобы увидеть ее в действии. Вы также можете сделать это с другими цветовыми форматами, кроме RGB, но RGB является самым простым.

Итак, это касается удобства использования, но как насчет доступности?

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

Если вам не нравится случайность инвертирования цветов, это понятно. Вы можете вообще выбрать цвета и вместо этого вручную написать для них условный CSS, но найти доступные цвета на разных фонах вашего дизайна для разных типов псевдоэлементов подсветки, принимая во внимание альтернативные методы просмотра, такие как темный режим, — это головная боль. Кроме того, я думаю, что некоторые элементы пользовательского интерфейса (например, выделение, ошибки, индикаторы фокуса) Нужный Будь уродливым. Они Нужный Брутально выглядит и ощущается иначе, чем цветовая палитра дизайна. Они должны намеренно не вписываться и требовать максимум внимания.

Обратите внимание, что разные типы псевдоэлементов выделения также должны визуально различаться по очевидным причинам, но не в том случае, если два разных типа перекрывают друг друга (например, пользователь выбирает совпадающий в данный момент текст с помощью поиска на странице). Итак, в измененном фрагменте кода ниже: mark, ::selection, ::target-textИ ::search-text Происхождение у всех немного разное.

Я ушел mark без изменений, r ценность ::selection как это было g ценность ::target-text Как было, так и b ценность ::search-text Как бы то ни было, у последних трех перевернуты только два канала вместо всех трех. Теперь они различаются по цвету (но по-прежнему отображаются перевернутыми) и имеют значение альфа. 70% (100% Для ::search-text:current), они также сливаются друг с другом, поэтому мы можем видеть, где начинается и заканчивается каждый момент:

body {
  --background: #38003c;
  background: var(--background);

  mark,
  ::selection,
  ::target-text,
  ::search-text {
    color: var(--background);
  }

  mark {
    /* Invert all channels */
    background: rgb(from var(--background) calc(255 - r) calc(255 - g) calc(255 - b) / 70%);
  }

  ::selection {
    /* Invert all channels but R */
    background: rgb(from var(--background) r calc(255 - g) calc(255 - b) / 70%);
  }

  ::target-text {
    /* Invert all channels but G */
    background: rgb(from var(--background) calc(255 - r) g calc(255 - b) / 70%);
  }

  ::search-text {
    /* Invert all channels but B */
    background: rgb(from var(--background) calc(255 - r) calc(255 - g) b / 70%);
    
    &:current {
      /* Invert all channels but B, but without transparency */
      background: rgb(from var(--background) calc(255 - r) calc(255 - g) b / 100%);
    }
  }
}

::spelling-error И ::grammar-error Они исключены из всего этого, поскольку имеют свою собственную визуальную значимость (красное подчеркивание и зеленое подчеркивание соответственно, обычно в отличие от нейтрального фона редактируемого элемента, такого как