Различный зазор в 0–1 пиксель между фоном и границей div на дисплеях с высоким разрешением

Вот отдельный пример кнопки, которую я создал в CSS. Он имеет границу в 1 пиксель с градиентом и фоновый градиент. Градиент фона реализован в виде псевдоэлемента, позволяющего уменьшать его непрозрачность при наведении курсора.

https://codepen.io/anon/pen/wbYoeo?editors=1100

.Button
{
  width: 200px;
  height: 30px;
  cursor: pointer;
    padding: 0.8rem;
    border-style: solid;
    border-image: linear-gradient(
        to right,
        green 0%,
        blue 100%);
    border-image-slice: 1;
    border-width: 1px;
    position: relative;
  margin-top: 10px;
    transition: color 0.2s;
}

.Button::before
{
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    background-image: linear-gradient(
        to right,
        green 0%,
        blue 100%);
    opacity: 0.5;
    transition: opacity 0.2s;
}

Кнопка не отображается одинаково на мониторах с разным DPI. Скриншоты кнопки, отображаемой в Chrome в Windows с различными масштабами DPI:

Монитор со 100% масштабированием DPI, правильное отображение без зазоров.

Монитор с масштабированием 150% DPI, показывающий зазор между фоном и границей.

Монитор с масштабированием 175% DPI, показывающий зазор между фоном и границей.

Монитор с масштабированием 200% DPI, правильное отображение без зазоров.

Я пробовал несколько стратегий для рендеринга кнопки, но все они приводят к разрыву:

  • Пытался использовать изображение с градиентом вместо linear-gradient как для border-image, так и для background-image.
  • Пытался использовать явный div для фонового градиента вместо псевдоэлемента.
  • Попытался использовать явный div для фонового градиента вместо псевдоэлемента, а также использовал сплошную левую и правую границу и псевдоэлементы ::before и ::after с линейно-градиентным фоном для верхней и нижней границ.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
6
0
2 453
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Причина?

Я бы предположил (необразованно), что это вызвано субпикселями при масштабировании. Это не может быть доля пикселя, поэтому он выбирает целое значение пикселя; расчетное значение родителя на 1 пиксель больше, чем значение, данное дочерним элементам в некоторых масштабах.

Обходной путь

Снимите границу с самого элемента div кнопки и поместите ее на псевдоэлемент ::after, чтобы граница и фон были дочерними элементами. Теперь кажется, что граница масштабируется в соответствии с фоновым градиентом.

Пример

.Button {
  width: 200px;
  height: 30px;
  cursor: pointer;
  padding: 0.8rem;
  position: relative;
  margin-top: 10px;
  transition: color 0.2s;
}

.Button::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background-image: linear-gradient( to right, green 0%, blue 100%);
  opacity: 0.2;
  transition: opacity 0.2s;
}

.Button:hover::before {
  opacity: 0.5;
}

.Button:active::before {
  opacity: 1;
}

.Button::after {
  content: '';
  border-style: solid;
  border-image: linear-gradient( to right, green 0%, blue 100%);
  border-image-slice: 1;
  border-width: 1px;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  top: 0;
}

html {
  height: 100%;
  display: table;
  margin: auto;
}

body {
  background: black;
  display: table-cell;
  vertical-align: middle;
  color: white;
  font-family: sans-serif;
}
Click it:
<div class = "Button"></div>

Другие вопросы по теме