HTML: Sub-pixel border
Asked Answered
F

17

18

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.

Fibro answered 18/4, 2011 at 22:38 Comment(4)
Why do you ask? Is there an implementation you are looking at?Cassaundracassava
Sounds like a recipe for disaster. It's hard enough to whole pixels to line up consistently across browsers.Mirepoix
Dulicate of better question and answers, which are sadly marked as duplicate of this one: https://mcmap.net/q/149495/-css-border-less-than-1px-duplicateVish
@Vish no, this one was first. The one that you sent the link to was December 2012 whereas this one is April 2011. But thanks for noting that the other one is a dupe.Antenatal
K
11

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.

Kira answered 18/4, 2011 at 22:50 Comment(4)
True, you're right about em units evaluating to partial pixels in some cases. I had forgotten that.Capri
Would the em trick work to get thinner lines on high definition screens, which draw "1px" lines with multiple pixels?Cadenza
Very late, but yeah, it should!Kira
This will not produce different results from equivalent px units on any browser.Kangaroo
B
10

Edit: I have overseen the 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>
Bering answered 1/6, 2015 at 15:42 Comment(1)
You can use scaleX(0.5) or scaleY(0.5) as well to scale in only one dimension, great answer!Cleric
B
4

I don't know about IE8-10 (IE6-7 definitily no go) , but in Chrome and FF I get the thinnest border with box-shadow. Works best to get a 1px <hr> instead of the autorendered 2px, but can be used on a border as well.

The thin border on the HR is more prominent in FF than Chrome, but also Chrome renders 2px.

http://jsfiddle.net/GijsjanB/3G28N/

.thin {
    border: 1px solid white;
    box-shadow: 0 0 1px black;
}
Bravery answered 18/6, 2013 at 15:55 Comment(0)
C
2

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.

Capri answered 18/4, 2011 at 22:45 Comment(2)
With modern resolutions this is no longer true. Monitors can render sub-pixel quality display items and many fonts actually require it in order to look decent on a retina style display.Gowrie
Also an issue for printing—Chrome 52 ignores the (probably unknowable for it) printer pixels and uses 1px = 1/72in as the thinnest possible line. Tried fractional pixels, inches, ems—none would create a line thinner than 1/72in. Even in a print media query. Tempted to see if using an image works, but I suspect I'll just make my peace with the chubby rulesVenenose
C
2

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:

enter image description here

Chibouk answered 27/11, 2016 at 20:21 Comment(2)
Thank you for pointing this out! FYI, if anyone has an issue with different border calculation in Chrome/FF and IE, please have this in mind.Emad
All appear the same on Chrome 62 macOS 10.13 (retina display @2x). Using the box-shadow trick works though.Penile
N
2

Try adding a box-shadow

box-shadow: 0px 0px 1px 0px black;
Neils answered 8/7, 2020 at 4:33 Comment(0)
S
1

you can transform the line like that:

.thin{ -ms-transform:scale(1, 0.5); -webkit-transform:scale(1, 0.5); transform:scale(1, 0.5);}

or, if the line is vertical

.thin{ -ms-transform:scale(0.5, 1); -webkit-transform:scale(0.5, 1); transform:scale(0.5, 1);}
Siemens answered 23/3, 2017 at 10:18 Comment(0)
P
1

To render native 1px borders on high DPI/@2x/retina displays, there are a couple of tricks.

On Firefox and Safari (macOS and iOS), use a 0.5px border:

/* Fallback: Most browsers now render 0.5px as 1px though */
.el {
  border: 1px solid red;
}
.retina .el {
  border: 0.5px solid red;
}

On Chrome, use a box-shadow with a 0.5px spread:

.retina-chrome .el {
  box-shadow: 0 0 0 0.5px red;
}

Use JS to add a class to the HTML element to only target @2x+ displays.

if (window.devicePixelRatio >= 2) {
  document.documentElement.classList.add(
    window.chrome ? 'retina-chrome' : 'retina'
  );
}

For @1x displays, use a slightly lighter color 1px border.

Penile answered 22/11, 2017 at 7:8 Comment(0)
K
1

Edit: Chrome 98 (February 1, 2022) added direct support for border-width values less than 1px.

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.

Kangaroo answered 4/6, 2020 at 20:37 Comment(0)
Y
0

0.1em displays border smaller then 1px try dotted border with 1px and compare it with 0.1em

Younker answered 27/7, 2012 at 10:3 Comment(1)
I see no difference in Chrome 20.Fibro
D
0

Maybe late post ,

<table>
  <tr>
    <td style="border:1px ridge">
    ....text....
    </td>
   </tr>
 <table>

using ridge(alternative) for thin border //IMO

Drawshave answered 20/3, 2017 at 6:45 Comment(1)
Wrong Answer. ridge: "Displays a border with a 3D effect, like if it is coming out of the page"-MDNAnastomosis
Z
0

For me this worked:

  • I needed a white border with less than 1px
  • So I added some opacity to the border color and it started to look thiner than 1px
  • like this:border-top: 1px solid #ffffff26;
Zumstein answered 27/5, 2018 at 19:44 Comment(0)
O
0

try

 border-top: 1px solid #c9d6df;

smaller than

 border: 1px solid #c9d6df;
Odor answered 24/3, 2021 at 9:4 Comment(0)
K
0

You could use CSS border-image to set an SVG or other image as the border, and then you could make the image line as narrow as you would like. It may still be rendered on screen as 1px, but if you then print or save the webpage out, the true size will be kept.

Kef answered 19/7, 2021 at 7:36 Comment(0)
A
0

With border you have a hard time to achieve thinner line!

If you want to have a horizontal line like me, you can do that with height instead of border:

Note: Maybe you need to zoom in to see the real difference between the two lines!

.normal {
  height: 1px;
  background-color: #8bacda;
}
.thinner {
  height: 0.01em;
  background-color: #8bacda;
}
<p>Normal Line</p>
<div class="normal"></div>
<p>Thinner Line</p>
<div class="thinner"></div>
Ancestry answered 21/11, 2021 at 17:24 Comment(0)
B
0

To easily get a border that looks smaller than a pixel, simply set the opacity of the border element to 0.1.

border{
  opacity: 0.1;
}
Bomarc answered 29/5, 2023 at 1:32 Comment(0)
T
0

It can be done with box-shadow used as a border:

box-shadow: 0px 0px 0.5px 1px rgba(0,0,0,1);
Tenure answered 9/11, 2023 at 6:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.