Skip to main content

CSS3 Implementation of Half-Pixel Borders

Free2015-06-20#CSS#Solution#半像素边框#0.5px

Are there lines thinner than 1px? If CSS3 is supported, yes, and it's easy to implement.

1. Approach

A normal 1px black solid border:

border: 1px solid #000;

Of course, a half-pixel border isn't simply changing 1px to 0.5px (haven't tested, but it might be parsed as 1 or 0). The value of border-width can only be a natural number.

Similarly, outline, box-shadow, etc., cannot draw 0.5px fine lines either.

Conventional approaches won't work, but we can cleverly implement this using pseudo-elements + scaling. The specific steps are as follows:

  1. Set the target element as a positioning reference

     .thinner-border {
         position: relative; /* Anything other than the default static value works */
     }
    
  2. Add a before or after pseudo-element to the target element, and set absolute positioning

     .thinner-border:before {
         content: '';
         position: absolute;
     }
    
  3. Add a 1px border to the pseudo-element

     border: 1px solid red;
    
  4. Set the pseudo-element's width and height to 2 times the target element

     width: 200%;
     height: 200%;
    
  5. Scale down by 0.5 (back to the target element's size)

     transform-origin: 0 0;
     transform: scale(0.5, 0.5);
    
  6. Include the border

     box-sizing: border-box;
    

In short, enlarge first then scale back. border-box is key; otherwise, the border won't scale together.

2. Specific Implementation

The steps above are already clearly written out. Putting them together gives the complete implementation:

.thinner-border {
    position: relative;
}

.thinner-border:before {
    content: '';
    position: absolute;
    width: 200%;
    height: 200%;
    border: 1px solid #000;
    -webkit-transform-origin: 0 0;
    -moz-transform-origin: 0 0;
    -ms-transform-origin: 0 0;
    -o-transform-origin: 0 0;
    transform-origin: 0 0;
    -webkit-transform: scale(0.5, 0.5);
    -ms-transform: scale(0.5, 0.5);
    -o-transform: scale(0.5, 0.5);
    transform: scale(0.5, 0.5);
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

This functionality adds a half-pixel border to block and inline-block elements with a class value of thinner-border. Since inline elements have some restrictions on width and height, the 200% obtained by the pseudo-element will be smaller than the actual value, and the border's width and height will also be smaller than expected.

3. Demo

.ib { display: inline-block; } .bx { display: block; } .bd { border: 1px solid #000; } .thinner-border { position: relative; } .thinner-border:before { content: ''; position: absolute; width: 200%; height: 200%; border: 1px solid #000; -webkit-transform-origin: 0 0; -moz-transform-origin: 0 0; -ms-transform-origin: 0 0; -o-transform-origin: 0 0; transform-origin: 0 0; -webkit-transform: scale(0.5, 0.5); -ms-transform: scale(0.5, 0.5); -o-transform: scale(0.5, 0.5); transform: scale(0.5, 0.5); -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .one-fourth:before{ width: 400%; height: 400%; -webkit-transform: scale(0.25, 0.25); -ms-transform: scale(0.25, 0.25); -o-transform: scale(0.25, 0.25); transform: scale(0.25, 0.25); }
1px border, block

Half-pixel border, block

1px border, inline Half-pixel border, inline-block Half-pixel border, inline, border too narrow
1/4 pixel border

The border effect is more obvious when viewed on a mobile browser; what changes is the line width, not the color

Note: Although theoretically borders can be arbitrarily thin (1/n px), due to precision issues (precision affects border width and height), half-pixel borders are the most practically useful. Although there are still issues: if width and height are odd numbers, the border position will offset by 0.5px, which is acceptable in practical applications.

Comments

No comments yet. Be the first to share your thoughts.

Leave a comment