How to Use border-image CSS Property for Non-Symmetrical Images

Georgia Stavropoulou
d-e weblog
Published in
6 min readApr 19, 2019

Building a website as a non-developer is pretty hard. The latest bump on our road was the millimeter lines of our mockup for Rosalind’s site and how to code them.

1. The easy way

The easiest way we came up with was the background image. We simply exported the lines from the Inkscape file as a .png for the y-axis. And this is the snippet:


body{
background-image: url(‘images/leftborder.png’);
background-position: left top;
background-repeat: repeat-y;
}

It’s self-explanatory, but if you have any questions feel free to ask. We would repeat this process for the x-axis, but this didn’t seem right. Michael was at unease. We already had a big background image and we added lightheartedly two more. Moreover the two background-images approach had an unsolvable overlap. It felt like this would backfire any time soon. We dropped it.

2. The kludge

A few minutes in stack overflow and the hacky approach popped up. It included an extra <div> in the html document before any other element in the <body> with class=”mil”. The <div> needed extra styling to hold our lines. Here it is:


.mil{
width: 100%;
height: 200px;
margin-left: 260px;
background: blue;
background-image: url(‘images/topborder.png’);
background-repeat: repeat-x;
}

The color is blue, so we could see what we were doing. Y-axis was next. But now we had a bunch of new actual elements, the code was messy and everything in the website went 200px down and this had to be corrected, and, well, this was not the solution.

We took a break and revisited later with a fresh eye. And coffee.

Joe the CEO.

3. The optimal way

I. Image first

The millimeter image was initially an svg image created in Inkscape. We decided to make sure the vectors aligned exactly to pixels in order to avoid aliasing problems (for example equal-thickness lines not showing as having equal thickness on-screen. See the section Antialiasing and Raytracing of (this article for more info). We opened a new Inkscape file clicked on View > Page Grid, so that a pixel grid was visible. We also set pixel to be the general display unit of the Document and the custom size. The page has width 112px and height 126px. We made this match the final size in browser (virtual) pixels we wanted to show it so that we would spend less time in size calculations.

Inkscape settings.

With the Rectangle tool we drew millimeter lines with 2px width, both horizontally and vertically, as depicted below. We were very meticulous with the space left right after the last two lines, exactly 12px; the same space is left among all the other lines. We avoided the Bezier tool, because it snapped to the middle of the line of the grid and gave us half a pixel as a leftover. All these helped us to create an image, for which we knew and could calculate any required measurements in pixels.

The millimeter lines.

BUT when we exported the image, we went at the Export PNG Image tab and at the Page > Image size we doubled it (again in px), so width became 224px and height 252px actual image pixels.

We were set for perfection.

II. A pixel is not a pixel is not a pixel

Why we decided to export*2? Well because most modern browsers render everything double-sized up (or more). Naturally a designer opts in for maximum quality of their website in every device. And with this choice the millimeter image would keep its quality, in any scale up to 2:1.

If you would like to make sure you maintain absolute sharpness in 3:1 screens like those of QHD smartphones you can export in 288dpi in Inkscape (3x), or even more. Keep in mind however that size can quadruple each time you double sizes, depending on your graphic.

All the above allowed us to use the border-image CSS property for the body of the document. Here’s our snippet:


body{
border-image-source: url(‘images/borderimage.png’);
border-image-slice: 140 0 0 84;
border-image-width: 70px 0 0 42px;
border-image-repeat: round;
width: max-content;
margin: 0;
}
main{
margin-left: 60px;
}

Let’s elaborate a bit more on that.

  • border-image-source

That was an easy one. We simply put the url; in our case it was a short url, because the CSS document and the images subfolder are in the same folder named public_html. How tidy and mighty we are! :P

  • border-image-slice: 140 0 0 84;

These are the the numbers for top, right, left and bottom parts that we need to slice. Notice no px designation .We picked these numbers by breaking down this diagram here. This gray area that our slicing shades is going to be the pinpointed part of our image and the right and bottom leftovers are the repeating units that eventually will build the border. These numbers are in actual pixels (i.e. doubled in our case). The cool about that is you can triple, quadruple etc, depending on how technology advances!

This is the starting point that won’t move.
  • border-image-width: 70px 0 0 42px;

Note here that regardless the fact that we doubled up our pixels to export, CSS needs to be set in the original (virtual) pixels of our Inkscape lines, hence 70px and 42px are the correct values and not 140px and 84px. The needed width from top to bottom equals with 70px (that is our measuring unit regarding our original image, plus we need to have our border image appearing only on our left), 0 for right and bottom because we have no border image appearing there and 42px from left to right, since that’s the maximum width of our original vertical millimeter lines.

  • border-image-outset

We omitted this CSS property, because the initial value of 0 was working just fine for us.

  • border-image-repeat: round;

We tried all the other options but round tiled the lines nicely, without visible distortions of the image, errors, bugs or extra pixels. We also tried various versions in Inkscape with more lines drawn, but the latest version was the most optimal. As such less distortion appeared when the image repeated itself.

For this case study margin of the body had to be set in 0, so no gap was left between the browser window and the lines.

  • border-style: solid;

But the image was not displayed on Chrome. We did a bit online research which involved, guess what, stackoverflow and chrome platform status and we solved this by adding an extra line of code in the stylesheet. With a solid border-style our millimeter lines were working on Chrome just fine.

To quote the chrome platform status website,

Blink will begin to require a border style in order to paint border images. This has always been required by the spec, but has not been enforced. In order to not be affected by this change, add e.g. ‘border-style:solid’ where border-image is used.

  • width: max-content;

And last but not least, this was a real brain teaser, the width had to be equal to max-content. The width of our <body> element by default equals the width of the viewport. Our Rosalind image was larger, exceeding the viewport width by far. Naturally the border image ended where the viewport ended. Although brutalism guides our web design choices and we were tempted to leave it like this, in the end we had to go with width: max-content; to fill the gap between each border entirely.

Without width: max-content; the lines stop, even tough the image does not.
With width: max-content; the lines go on till the end of the scroll bars.

We’d love to have your comments! What do you think of the border-image property? Have you ever used it?

--

--