Is it possible to have a border that is thinner than 1px and works in IE6+ and is not an image and renders properly visually?
Thank you.
Edit: I have overseen then IE6 restriction, but I leave the answer here for others ...
Its possible with transform:scale(0.5)
and put a border element with border:1px;
inside. So you get a half pixel border, that (although tricked and browser dependend) is displayed on screen. But I use that trick for printing.
sure, you have to adapt the content of the element, or play with position
.outer {
border:1px solid green;
}
.halfpix {
-ms-transform-origin: 0 0;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-ms-transform:scale(0.5);
-webkit-transform:scale(0.5);
transform:scale(0.5);
width:200px;
height:100px;
border:1px solid black;
}
<div class="outer">
<div class="halfpix">
</div>
zoom browser window if your browser does not display
</div>
Although this isn't (currently) possible in any version of IE or Edge, on the latest versions of Firefox and Chrome you can now use border width values less than 1px.
.borderTest {
box-sizing: border-box;
display: block;
margin: 0.5em;
padding: 0.5em;
width: calc( 100% - 1em );
}
.borderTest:nth-child(1){
border: 1px solid #000
}
.borderTest:nth-child(2){
border: 0.75px solid #000
}
.borderTest:nth-child(3){
border: 0.5px solid #000
}
.borderTest:nth-child(4){
border: 0.25px solid #000
}
<div class="borderTest">1px</div>
<div class="borderTest">0.75px</div>
<div class="borderTest">0.5px</div>
<div class="borderTest">0.25px</div>
This outputs the following on a UHD screen:
As of mid 2020, current versions of Safari and Firefox both support border-width: .5px
.
On the other hand, Chrome will treat it as 1px
.
You can detect whether the browser supports it with something like:
var el = document.createElement('div');
el.style.position = 'fixed';
el.style.borderTop = '.5px solid';
document.body.appendChild(el);
var hasSubpixelBorder = el.getBoundingRect().height < 1;
document.body.removeChild(el);
Make sure this is called after document.body
is created if you are doing it at startup.
If this is not supported (e.g. Chrome) you can add a class to document.body
or some parent element to cause descendants to take on a different border style:
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
.noSubpixelBorder .border-top {
border-top-width: 0;
background-image: linear-gradient(180deg, var(--mycolor) 0, var(--mycolor) .5px, transparent 0);
}
}
@media (-webkit-min-device-pixel-ratio: 3) and (-webkit-max-device-pixel-ratio: 3.5), (min-resolution: 3dppx) and (max-resolution: 3.5dppx) {
.noSubpixelBorder .border-top {
background-image: linear-gradient(180deg, var(--mycolor) 0, var(--mycolor) .333333px, transparent 0);
}
}
You can use multiple linear gradients to achieve borders on multiple sides. This takes over background-image
so if you are using it for something else you will need to find another way (there are a couple others).
This is not particularly clean, but it seems to consistently work.
If you wanted to be super crafty, you could support oddball pixel ratios by computing the stylesheet on the fly.
Try adding a box-shadow
box-shadow: 0px 0px 1px 0px black;
I think you could define the width of a border using units like em
which would come out to less than 1px, and it would be valid. However, like Will Martin said, for display purposes it would just round it up or down to a whole pixel.
No. You can't show a size smaller than one pixel because pixels are the basic unit of the monitor. And anyway, no browser I know of allows you to specify sub-pixel widths. They just get rounded up to 1px or down to 0px.