/usr/foxpeople/koko/site-root/2023/011.html - Netscape Navigator 4.76

/usr/foxpeople/koko/site-root/2023/011.html

Back Forward Reload Home Shop

Blog > Post

border-image-slice without border-image-slice

14 Feb 2023


A few months ago, I did a massive rewrite to my site. This involved re-doing the layout and removing the use of most CSS3 features, sticking to the bare minimum properties whenever and wherever possible. Some time later, I began to brainstorm ideas for a potential redesign, which eventually culminated in the idea of adapting my desktop setup to HTML/CSS. However, there was one problem: how would I go about making the "content" window scalable?

Enter: border-image-slice. It performs some nine-slice scaling to a source graphic, which can then be applied to a bordered element. This is perfect for conveying something like a window graphic! Unfortunately, taking a peek at MDN's browser compatibility table revealed that the property wouldn't work in any browser older than ~2012. Since I wanted to avoid yet another massive compatibility rewrite in the future, I had to figure out an alternative. So, here's what I came up with, as a step-by-step guide.


First, let's begin with a container div, which will hold our sliced/scaled graphic and content:

<div class="container">
</div>

Good job! I knew you could do it.

Now, we need to think about things a bit here. When it comes to nine-slice scaling, you've essentially got a 3x3 grid of images, and by extension, a 3x3 grid of "cells"; or, in our case, divs. So let's break it up by rows:

<div class="container">
	<div class="top">
	</div>
	<div class="center">
	</div>
	<div class="bottom">
	</div>
</div>

You can probably see where I'm going with this. Let's get those columns in there:

<div class="container">
	<div class="top">
		<div class="topleft"></div>
		<div class="topright"></div>
	</div>
	<div class="center">
		<div class="centerleft"></div>
		<div class="content">
			slice and dice<br>dice and slice
		</div>
		<div class="centerright"></div>
	</div>
	<div class="bottom">
		<div class="bottomleft"></div>
		<div class="bottomright"></div>
	</div>
</div>

The content div will— and you'll never believe this— be where our content appears. Note that I've foregone adding topcenter and bottomcenter divs (for their respective cells of the 3x3 grid); this is for reasons that'll become apparent later, once the styles are added.

If the structure of these divs seems confusing, try to picture it like this:

three layers. the bottom is a large square; the middle consists of 3 rows, totalling up to the size of that square; the top layer has smaller squares within those 3 rows.

...at least it'll be laid out like this after applying the styles. But before we can start adding them, we'll need an example image to play around with. I propose this one:

a test image, with 9 distinct sections in a 3x3 grid.

Since we're aiming to be compatible with old browsers, the use of background-position- and thus, spritesheets- might not be the best choice. Instead, let's break it up into individual images (it'll make things easier, anyway).

The styles do the bulk of the work. Let's start with the container; here we pretty much just give it some arbitrary width and height. We also add overflow: hidden to stop things from breaking when there's more content inside the center, or if the container is resized too small (spoiler alert...! fearful koko)

.container {
	position: relative;
	height: 150px;
	width: 200px;
	overflow: hidden;
}

Now let's go row-by-row, starting with the top.

.top {
	background-image: url("tc.png");
	height: 32px;
}
.topleft {
	background-image: url("tl.png");
	width: 32px;
	height: 32px;
}
.topright {
	background-image: url("tr.png");
	position: absolute;
	top: 0;
	right: 0;
	width: 32px;
	height: 32px;
}

The reason for the lack of topcenter and bottomcenter divs should now be apparent here: instead of adding an extra div, the top div will take care of our 'tc' graphic. The height property should match the height of the top-row graphics, too. For the top left, we specify the div's width and height to prevent it from shrinking to a size of 0x0. The top right div differs a bit, in that it needs some help sticking to the right side. We'll use position: absolute along with a top and right of 0 to do that.

You should see something like this by now:

slice and dice
dice and slice

Looks promising! Let's keep going, continuing on with the center row.

.center {
	position: absolute;
	top: 32px;
	bottom: 32px;
	width: 100%;
}
.centerleft {
	background-image: url("cl.png");
	position: absolute;
	top: 0;
	left: 0;
	width: 32px;
	height: 100%;
}
.centerright {
	background-image: url("cr.png");
	position: absolute;
	top: 0;
	right: 0;
	width: 32px;
	height: 100%;
}
.content {
	background-image: url("c.png");
	position: absolute;
	top: 0;
	bottom: 0;
	left: 32px;
	right: 32px;
	color: white;
}

This is where things start to get a bit messy.

This time, the row div— center— needs to be positioned using absolute. If we think about it, this is in relation to container, so we'll need 32px from the top and bottom (the height of the respective row graphics). The width also needs to be 100% of the container.

Much like like topright, the centerleft/right divs need some help sticking as well. Slap position: absolute onto them, fix them to the top of center with top: 0, then to their respective sides with left: 0 and right: 0. The widths from the graphics need to be specified as well, so say it width me: 32px. Then, add height: 100% to give them the same height as center.

The content div is a similar story, only this time we're pinning it to the top of center, offset from the left by the width of the centerleft graphic. Then we expand it to the bottom of center as well as to its very right, minus the width of the centerright graphic. The color property is just there to make our text a bit more legible.

So, how does it look now?

slice and dice
dice and slice

Closer! Just the bottom row, and we're done.

.bottom {
	background-image: url("/blogImg/011/bc.png");
	position: absolute;
	bottom: 0;
	width: 100%;
	height: 32px;
}
.bottomleft {
	background-image: url("/blogImg/011/bl.png");
	position: absolute;
	bottom: 0;
	left: 0;
	width: 32px;
	height: 32px;
}
.bottomright {
	background-image: url("/blogImg/011/br.png");
	position: absolute;
	bottom: 0;
	right: 0;
	width: 32px;
	height: 32px;
}

This should be easier for you to parse by now. The bottom div should stick to the bottom, have a height of 32px, and take up the full width of the container. Much like top, it should also handle our bottomcenter graphic. bottomleft/right need to stick to their respective corners, and once again position: absolute along with bottom: 0 and left/right: 0 will get us there. For the size of both, you know the drill.

With all that said and done, you should hopefully end up with something like this:

slice and dice
dice and slice

And there it is: something that vaguely looks like it was done with border-image-slice, using basic CSS! Let's see if we can add more content to the center.

slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice

Hm. I definitely added more than 4 lines there. No worries; adding overflow: auto to content's style will fix that.

slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice

Cool! And if you want to scale the center graphics instead of tiling them, you can add background-size: 100% 100% to the top, bottom, centerleft/right, and content divs. There's a bit of a caveat to this; because we skipped adding topcenter and bottomcenter divs for simplicity, the top and bottom sections will scale across the whole container, instead of between the left and right divs. Here's what that looks like, regardless:

slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
bro i am so tired of slicing and dicing. i need a nap

You could probably fix that with what you've learned here, though winking koko

As a cool added bonus, you can add resize: both to container's style to allow it to be resized from the bottom right corner. It's what I did to allow the content window to scale.

slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
slice and dice
dice and slice
ok that's enough. no longer in my slicing arc. not feeling very dicecore either

Despite its complexity, this technique does have a tiny advantage over border-image-slice, in that the widths of each graphic can be independent. Take the window graphics used for my site as an example:

Notice how the graphics used in the left and right columns have differing widths; this normally isn't possible with typical nine-slice scaling methods! Putting it all together, we get:

smug kokosmug kokosmug koko

Now the magic behind my site is ruined... fearful koko


And there you have it: border-image-slice without border-image-slice. If you enjoyed this article or found it useful, I don't take any donations but you can observe my fursona. please

Now go make something cool (and compatible with ancient browsers).


Share: 

(Not seeing your preferred service here? Contact me.)

cdrom
floppy
floppy
 
/
systemtour
 
dumpster