Вот отдельный пример кнопки, которую я создал в 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
.Я бы предположил (необразованно), что это вызвано субпикселями при масштабировании. Это не может быть доля пикселя, поэтому он выбирает целое значение пикселя; расчетное значение родителя на 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>