Потенциально в браузере появится :near() you | CSS-трюки

Потенциально в браузере появится :near() you | CSS-трюки


Незадолго до конца 2025 года я увидел это предложение. :near()Псевдокласс, который будет соответствовать при передаче указателя элементу. на сколько? Ну, это будет зависеть от стоимости <length> Аргумент предоставлен. Томас Валичивич, предложивший :near()Предполагается, что это работает следующим образом:

button:near(3rem) {
  /* Pointer is within 3rem of the button */
}

Для тех, кому интересно: да, мы можем использовать теорему Пифагора («Евклидово расстояние» — это математический термин) для измерения расстояния по прямой между двумя элементами с помощью JavaScript, поэтому я предполагаю, что именно это будет использоваться здесь за кулисами. У меня есть несколько вариантов использования, которыми я могу поделиться с вами, но демо будет представлять собой только симуляцию. :near() Поскольку он, по-видимому, не поддерживается ни одним веб-браузером. Должны ли мы копать?

визуальные эффекты

не задавая никаких вопросов, :near() Может использоваться для почти бесконечного (извините) количества визуальных эффектов:

div {
  /* Div is wow */

  &:near(3rem) {
    /* Div be wowzer */
  }

  &:near(1rem) {
    /* Div be woahhhh */
  }
}

пока элементы не потускнеют :near()

Чтобы уменьшить визуальный беспорядок, вы можете затемнить некоторые компоненты, пока пользователи не приблизятся к ним. :near() может быть более эффективным, чем :hover В этом сценарии это связано с тем, что у пользователей могут возникнуть проблемы со взаимодействием с компонентами, когда они имеют ограниченную видимость, поэтому возможность запускать их «раньше» может в некоторой степени компенсировать это. Однако нам необходимо обеспечить доступный цветовой контраст, поэтому я не уверен, насколько это полезно. :near() Может случиться в такой ситуации.

button:not(:near(3rem)) {
  opacity: 70%; /* Or...something */
}

скрывать до тех пор, пока элемент :near()

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

Итак, вы знаете, что происходит, когда вы наводите курсор на изображение и появляется кнопка «Поделиться»? Имеет смысл, не так ли? Поскольку мы не хотим, чтобы изображение было нечетким, оно изначально скрыто. Это не оптимально с точки зрения UX, но все же это шаблон, с которым люди знакомы, например, в Pinterest.

И вот как :near() Может увеличить. Люди знают или подозревают, что кнопка там есть, верно? Возможно, в правом нижнем углу? Они примерно знают, куда нажать, но не знают Абсолютно Где, потому что они не знают размера или смещения кнопки. Хорошо, когда я покажу тебе кнопку? :near() Это означает, что для появления кнопок не нужно так точно наводить на них курсор. Этот сценарий очень похож на приведенный выше, возможно, с другими причинами снижения видимости.

Однако нам нужно, чтобы эта кнопка была доступной (с возможностью наведения, фокусировки и поиска на странице). Чтобы это произошло, мы не можем использовать:

  • display: hidden (Не наводится, не фокусируется и не постранично)
  • visibility: hidden (Нет возможности наведения, фокусировки и даже возможности просмотра страниц на страницах)
  • opacity: 0 (Невозможно показать его после того, как он будет найден с помощью функции «Найти на странице»).

он покидает нас content-visibility: hiddenНо проблема со скрытием использования контента content-visibility: hidden (или с элементами display: none) в том, что они буквально исчезают, и невозможно приблизиться к тому, чего нет. Это означает, что нам нужно зарезервировать для него место, даже если мы не знаем Сколько космос.

Сейчас, :near() Не поддерживается ни в одном веб-браузере, поэтому в приведенной ниже демонстрации я поместил кнопку в контейнер. 3rem Из paddingИ пока этот контейнер происходит :hoverЭд, кнопка показана. Это увеличивает размер наводимой области вместо самой кнопки (которую я сделал красной, чтобы вы могли ее видеть). По сути, это имитирует button:near(3rem).

Резервный вариант встраивания кода

Но как можно что-то скрыть, зарезервировав место?

Прежде всего, мы заявляем contain-intrinsic-size: auto none По скрытым целям. Это гарантирует, что он сохранит определенную форму, даже если что-то изменится (в данном случае, даже если его содержимое скрыто). вы можете указать <length> для любого значения, но в этом случае auto Это означает, каким бы ни был представленный размер. noneкоторое является обязательным резервным значением, также может быть <length>Но нам это совершенно не нужно, так что»none

Проблема в том, что указанный размер был «пустым», потому что кнопка content-visibility: hiddenЗапоминание? Это означает, что нам нужно отрисовать ее всего на миллисекунду, и именно это и делает эта анимация:

<div id="image">
  <div id="simulate-near">
    <button hidden="until-found">Share</button>
  </div>
</div>
@keyframes show-content {
  from {
    content-visibility: visible;
  }
}

button {
  /* Hide it by default */
  &:not([hidden="until-found"]) {
    content-visibility: hidden;
  }

  /* But make it visible for 1ms */
  animation: 1ms show-content;

  /* Save the size while visible */
  contain-intrinsic-size: auto none;
}

Обратите внимание, что если кнопка имеет hidden=until-found значение атрибута, что делает его фокусируемым и доступным для просмотра страниц на страницах, content-visibility: hidden не было объявлено, поскольку hidden=until-found Он делает это автоматически. Во всяком случае, анимация заявляет content-visibility: visible Для 1ms Тогда как contain-intrinsic-size: auto none Сохраняет свою форму и надежно удерживает свое место, позволяя нам наводить на него курсор, даже когда он невидим.

Теперь, когда вы понимаете, как это работает, вот полный код (опять же смоделированный, потому что :near() Пока не поддерживается):

<div id="image">
  <div id="simulate-near">
    <button hidden="until-found">Share</button>
  </div>
</div>
@keyframes show-content {
  from {
    content-visibility: visible;
  }
}

#simulate-near {
  /* Instead of :near(3rem) */
  padding: 3rem;

  button {
    /* Unset any styles */
    border: unset;
    background: unset;

    /* But include size-related styles */
    padding: 1rem;

    /* Hide it by default */
    &:not([hidden="until-found"]) {
      content-visibility: hidden;
    }

    /* But make it visible for 1ms */
    animation: 1ms show-content;

    /* Save the size while visible */
    contain-intrinsic-size: auto none;
  }

  &:where(:hover, :has(:focus-visible)) button {
    color: white;
    background: black;
    content-visibility: visible;
  }
}

Если вам интересно, почему мы беспокоимся border И backgroundэто потому что content-visibility: hidden Скрывает только содержимое, а не элемент, но мы его включили padding Потому что это влияет на форму, которую мы пытаемся представить и запомнить. После этого мы также применяем эти стили content-visibility: visible Нажмите кнопку, когда появится обертка :hoverЭд или :has(:focus-visible).

И вот то же самое, но с неподдерживаемым :near(): :

<div id="image">
  <button hidden="until-found">Share</button>
</div>
@keyframes show-content {
  from {
    content-visibility: visible;
  }
}

button {
  /* Unset any styles */
  border: unset;
  background: unset;

  /* But include size-related styles */
  padding: 1rem;

  /* Hide it by default */
  &:not([hidden="until-found"]) {
    content-visibility: hidden;
  }

  /* But make it visible for 1ms */
  animation: 1ms show-content;

  /* Save the size while visible */
  contain-intrinsic-size: auto none;

  &:where(:near(3rem), :hover, :focus-visible) {
    color: white;
    background: black;
    content-visibility: visible;
  }
}

Суммируя, :near() Позволяет нам делать то, что делает смоделированная технология, но без дополнительной разметки и творческих селекторов, и если есть необходимость в доступе, он у нас есть. animation/contain-intrinsic-size двигаться.

предварительная выборка/пререндеринг, когда рядом

Я не предлагаю использовать предварительную выборку/предварительный рендеринг. :near() или даже функциональность :near() Его следует расширить, но также и для того, чтобы API правил спекуляций мог воспользоваться преимуществами встроенной функциональности. Уже использует API правил ставок mousedown, touchstartНаправление и скорость указателя, внешний вид окна просмотра и остановка прокрутки служат сигналами для начала предварительной загрузки/предварительного рендеринга связанного ресурса, так почему бы и нет, когда он находится рядом?

На самом деле, я думаю, что «рядом» можно использовать как понятие Очень больше, чем это :near()И Нужный Рассмотрите возможность использования этого пользовательского хит-теста pointermove Это связано с высокими затратами на производительность и сложностью реализации (как указывает Томас). Давайте посмотрим на другой пример.

Улучшите взаимодействие с заинтересованными абонентами

При взаимодействии с наложениями, активируемыми при наведении, существует риск случайного перемещения указателя от триггера или цели. Использует API Interest Invoker, который облегчает взаимодействие, инициируемое наведением курсора. interest-show-delay И interest-hide-delay Свойства CSS предотвращают случайную активацию и деактивацию соответственно, но с точки зрения пользовательского опыта все, что связано с задержкой и чувствительностью ко времени, неинтересно.

несколько примеров:

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

Таким образом, вместо (или в дополнение к) показа и сокрытия задержек API Interest Invoker может использовать концепцию «поблизости», чтобы гарантировать, что наложения не исчезнут из-за неправильного взаимодействия. Это можно настроить с помощью свойств CSS (например, near-radius: 3rem или автобус near: 3rem), что противоположно :near() вызовет функциональность (interest И loseinterest события JavaScript в данном случае).

Другой вариант использования, предложенный Томасом в его предложении: отображение подсказки «перетащите, чтобы изменить порядок» при наведении курсора на перетаскиваемый элемент. Это отличный вариант использования, поскольку показ всплывающих подсказок всего на несколько миллисекунд раньше сокращает время выполнения задачи.

К сожалению, у вас возникнут трудности с эмуляцией их с помощью валидного HTML (я так думаю?), главным образом потому, что <a>Песок <button>s может содержать только определенные элементы.

отрицательные стороны :near()

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

Другие потенциальные злоупотребления включают тепловые карты, снятие отпечатков пальцев и агрессивную рекламу. Его также можно использовать способами, которые негативно повлияют на производительность. Предложение Томаса прекрасно показывает эти злоупотребления и их методы. :near() Это можно реализовать, чтобы помешать им.

:near() проблемы доступности

:near() не должно означать :hover Или :focus/:focus-visible. Я думаю, что многое из этого очевидно, если серьезно задуматься, но я все равно вижу, как границы пересекаются. Хороший вопрос, который следует задать перед использованием :near() Является: «Мы предопределены или спекулятивны?» Превентивный подход может быть и хорош, но доказано предположением Это всегда будет плохо, потому что мы никогда не хотим, чтобы пользователи думали, что они перемещаются или фокусируются на интерактивном элементе, хотя на самом деле это не так (или еще нет). Это упоминается в различных частях Руководства по обеспечению доступности веб-контента, но особенно в Критериях успеха 2.4.7: Видимый фокус (Уровень AA).

Аналогичным образом, Критерий успеха 2.5.8: Целевой размер (уровень AA) гласит, что интерактивные элементы меньше, чем 24x24px Вокруг них должно быть дополнительное расстояние, которое рассчитывается как 24px - target width/24px - target heightно имеет ценность или нет :near() Немного неясно, какие это будут факторы.

в заключение

Здесь есть над чем подумать, но в конечном итоге мне бы хотелось, чтобы это было реализовано так, как предложил Томас. При этом руководство WCAG Конечно Принимайте конкретные меры перед началом любой реализации, особенно с учетом того, чего мы уже можем достичь. :near() Подойдет (хотя и с большей разметкой и, возможно, некоторыми хитростями CSS).

И опять же, я думаю, нам следует рассмотреть идею «рядом» как концепцию, в которой базовая функциональность может быть использована с помощью API спекулятивных правил и API Interest Invoker (последний со свойством CSS). near-radius).

Ваши мысли, пожалуйста!


Возможно, в браузере появится :near(). Первоначально вы опубликовали его на CSS-Tricks, входящем в семейство DigitalOcean. Вы должны получать информационный бюллетень.

Leave a Reply

Your email address will not be published. Required fields are marked *