Here is an isolated example of a button I've created in CSS. It features a 1px border with a gradient, and a background gradient. The background gradient is implemented as a pseudo-element to allow its opacity to be faded on hover.
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;
}
The button doesn't render identically between monitors of differing DPI. Screenshots of the button rendered in Chrome on Windows with varying DPI scales:
100% DPI-scaled monitor, rendering correctly with no gap.
150% DPI-scaled monitor, showing a gap between the background and border.
175% DPI-scaled monitor, showing a gap between the background and border.
200% DPI-scaled monitor, rendering correctly with no gap.
I've tried several strategies to render the button, but they all result in the gap:
linear-gradient
on both the border-image
and background-image
.I would take an (uneducated) guess that this is caused by sub-pixels when scaling. It can't be a fraction of a pixel, so it chooses a whole pixel value; the parent's calculated value is 1px bigger than the value given to the children at some scales.
Take the border off the button div itself, and put it on an ::after
pseudo-element so the border and background are both children. The border now appears to scale consistently with the background gradient.
Example
.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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With