Displaying Image Sprite in Pseudo-Element ::after

Hi everyone,

Back again with another riddle to solve for my Shipping Guide page. :wave:

I designed this page divider graphic:
pagedividers

I would like the top 2 designs in that graphic file to be displayed directly after the Table of Contents (one for full size width and one for narrows). The other two bar designs that I’m fond of will be used later in the document as sprites. My first assumption to target the styles to use the .introwrap ol::after as a pseudo-element, but I am firstly unclear if an ordered list element is suitable for the ::after target. :thinking:

The following code for simply displaying the entire graphic isn’t even working:

.introwrap ol::after { /* first page divider graphic */
	background:url("../images/pagedividers.png") no-repeat;
}

line 101, shippingguide.css

Then, once the image is properly targeted and displaying (either using the ordered list or a div or other suitable element), it’s time to determine the property to make the image a sprite. background-position or the clip property are my two guesses.

Thanks for any suggestions in advance.

-ty :smashy:

Hi etidd.
Anytime you use a pseudo ::before or ::after element it must be accompanied by the content property, even if it is empty.

Then for hooking a background image to it you would give it a block display and a height that matches your image height.

.introwrap ol::after { /* first page divider graphic */
  content:"";
  display:block;
  height:160px; /*adjust as needed*/
  background:url("../images/pagedividers.png") no-repeat;
}

That should get the image to display, then you can set your background positions for the sprite.

1 Like

Hey, what’s up, Ray? :wave:

By “hooking”, I’m assuming you mean only displaying a certain slice of the image.

Your code works brilliantly, and I really just leveled up on a bit of knowledge.
I had to adjust the HTML to give the <ol> an ID because the styles were applied duplicate times:

<ol id="divider">

I just changed the height to 171px, and it looks great! :clapper:
However, I will now need to center this pseudo-element. It’s off to the left. Is it time for margin:0 auto; ?

Then, all I need is a media query with the background-position and height set to the next “hook”. :fishing_pole_and_fish:
I can do that!

Is it possible to make the images stretch using this method (make the wide graphic version stretch to 120% at wide widths)?

Well, margin:0 auto, vertical-align:center, text-align:center, zeroing margins and padding does not move the pseudo-element into the center of the page. It’s aligned to the left.

…and this is me when I can’t center elements after about 5 years of learning to code CSS:
:banghead: :smashy: :ghost:

IMHO, in this case you could be better off using the “introwrap” rather than the list to hold the pseudo element.

Browsers are configured to try fix typos and common code errors but even then might be confused by a non item element as an item sibling, in the html it would be considered an error.

The auto margins needs a width to center a block, as default the block width is auto i.e filling available space. :slight_smile:

2 Likes

I should have already known this.

I should have known this, too.

All fixed. :clipboard:

.introwrap::after { /* first page divider graphic */
	content:"";
	background:url("../images/pagedividers.png") no-repeat;
	display:block;
	height:171px;
	width:680px;
	margin:0 auto;
}

With this structure and use of the ::after target, is it possible to make the dividers stretch and expand just a bit? My guess is no because there is already a definitive width and height using pixels.

Depending of what you want there are different options to try. :slight_smile:

Some info about background properties at Mozilla Dev:

Yes that’s what I meant. That’s how sprites work, showing a slice of the image in the fixed height container using background position.
Looks like you got that figured out now.

You could have also centered the background image within the full width block. That way you would not have to change widths on a media query. I guess that’s what I was trying to convey in my first post.

.introwrap::after {
    content: "";
    background: url("../images/pagedividers.png") no-repeat center 0px;
    display: block;
    height: 171px;

Then on mobile devices you can scale the image down with background-size in your media query.

Then replace the 0px shown above to show another slice of the image, and possibly change the height as well.

2 Likes

Okay. So, I’ve been playing around for a bit and have revised my goals. :goal_net:
background-size does make the image behave in the way I am envisioning (although it needs adjustments to the height as you mentioned).

The wide version of the graphic looks fine without any expanding. I have a very wide monitor, and the blank space on the left and right is acceptable to me. There isn’t any real advantage gained by making the large sprite shrink and expand. :expressionless:

However, the slim version does need to expand. So far, my code reads as follows in the media queries:

@media screen and (max-width:915px) {
	.introwrap::after {
		background-position:center -171px;
		height:101px;
	}
}

It does transition at the right time, but it’s not long before that graphic overflows the container:
overflow
So, for the second hook, the image definitely needs to fluidly shrink and expand.

…and when I add the background-size to the mix, the display issues become complex as the graphic shifts vertically. It’s hard to explain, but you can see the behavior on the page.
cag

background-size:cover;

I’m not sure what to do to keep the second hook in focus, but this is where a container may be helpful (as a guess). Changing the height in the media queries might be an option, but I am continuing to explore the possible remedies for what I’m trying to achieve.

-ty :smashy:

You could make the vertical position adapt to the height if you relate the height of its container to the background image’s cover size. I.e. adapt the container height to the width of the container.

So if you set the height with a viewport width value, the image could be vertically centered by a calculated* adjustment.

When you use percentage to position the background, that value will be used both for the image and where that point in the image appears in the container.

To make the background stick when the width changes, try these pair of values for the four sprites in order:

height: 16vw; 
background-position: center calc(26% + 4vw);

height: 10vw; 
background-position: center calc(63% - 1.2vw);

height: 4vw; 
background-position: center calc(84% - 1vw);

height: 4vw; 
background-position: center calc(96% - .6vw);

*) Nah, scrap the algorithm, just trial and error the value pairs if you change the sprite. :stuck_out_tongue:

2 Likes

Erik,

This seems to be reasonably close to what the goal is. You are very wise. :merman:

Maybe through the bits of chatter, I should have reiterated that the first 2 flower designs are designed for this, and the 2 bar designs are dividers for images in other content that’s to follow in the coming sections. If I want to add any more dividers (which I don’t think I need any more), then they will be added to the pagedividers.png file.

I have never worked with the calc() function or the vw units, so I will continue to study, but even after a bit of reading, this bit still confuses me as to why there is addition /subtraction at play and what this presents instead of just supplying a unit value.

So, just for good measure, I added some transparent space in between each hook in the graphic file (it’s now 500 px in height):
pagedividers

Here’s the present code in the media queries:

@media screen and (max-width:915px) {
	.introwrap::after {
		background-position:center -210px;
		background-size:cover;
		height:101px;
	}
}
@media screen and (max-width:850px) {
	h1 {font-size:2.5em;}
	.outer {border-width:85px;}
	body {font-size:1.35em;}
	.introwrap p:last-of-type {font-size:1.65em;}
	h2 {font-size:1.675em;}
	.introwrap::after {
		height:16vw; 
		background-position:center calc(26% + 4vw);
	}
}
@media screen and (max-width:750px) {
	h1 {font-size:2.0em;}
	.outer {border-width:75px;}
	body {font-size:1.2em;}
	.introwrap p:last-of-type {font-size:1.4em;}
	h2 {font-size:1.5em;}
	.introwrap::after {
		height:10vw; 
		background-position:center calc(63% - 1.2vw);
	}
}

This is very close and only displays the top 2 hooks that have the flower in the center (not the bar designs).
It would seem that all I need to do is adjust the height, correct?

Although, it does seem as if the design is too small / shrunken down at narrow widths.

Thanks for sharing your wisdom. Here’s an e-taco. :taco:

It looks like I may even need to add in a 3rd hook to get around the use of background-size:cover as it really makes things shrink too small at the most narrow points.

I commented out that block in order to test things:

@media screen and (max-width:915px) {
	/*.introwrap::after {
		background-position:center -210px;
		background-size:cover;
		height:101px;
	}*/
}

I don’t see it as too small even down to 320px device width. But compared to the toplogo image I would agree.

But instead of a 3rd hook I think you could enlarge the second sprite image up to the same width as the two bars below.

Just my two cents. :slight_smile:

Well, that’s 2 cents that go a long way. :1st_place_medal:

So, I wrote a bunch of new code and updated the graphics, and I did a great job! :clap: It’s almost ready.

Here’s the current CSS, lines 123 to the end:

/* media queries */
@media screen and (max-width:1000px) {
	.introwrap ol ol {padding-left:28%;}
}
@media screen and (max-width:915px) {
	.introwrap::after {background-size:cover;}
}
@media screen and (max-width:850px) {
	h1 {font-size:2.5em;}
	.outer {border-width:85px;}
	body {font-size:1.35em;}
	.introwrap p:last-of-type {font-size:1.65em;}
	h2 {font-size:1.8em;}
}
@media screen and (max-width:800px) {
	.introwrap::after {
		height:98px; 
		background-position:center -200px;
		background-size:initial;
	}
}
@media screen and (max-width:750px) {
	h1 {font-size:2.0em;}
	.outer {border-width:75px;}
	body {font-size:1.2em;}
	.introwrap p:last-of-type {font-size:1.4em;}
}
@media screen and (max-width:700px) {
	.introwrap ol {text-align:left;}
	.introwrap ol ol {padding-left:15%;}
}
@media screen and (max-width:610px) {
	.introwrap::after {background-position:center -323px;}
}
@media screen and (max-width:600px) {
	.introwrap ol ol {padding-left:10%;}
}
@media screen and (max-width:500px) {
	h2 {font-size:1.5em;}
	.introwrap ol ol {padding-left:5%;}
}

Do you see how the first hook shifts so nicely to background-size:cover and scales down before changing to the next hook? I really want to do that for the second hook as I feel it transitions just a tad bit soon. When I applied background-size:cover to the second hook, it causes the graphic to disappear (or something similar to this that I tried).

Is there some technicality that makes it impossible to preserve the background-position (the hook) while using background-size:cover? :mag_right:

I want the 2nd hook to get crunched in horizontally beginning at roughly 640 px wide, but maybe I should just add in a 4th hook. …but since I will be applying the bar designs later in the article, I need to know how to make them adjust horizontally only.

Well, I have 4 hooks now, and I think it’s done.
I exported the image file to jpeg to cut the file size down to 183KB for this particular image. Since this will be a long-form article (27 pages in text version), at what point does page file size become an issue? I ran a page tester, and it’s grading my page as an F with regards to image compression.

Current code:

/* media queries */
@media screen and (max-width:1000px) {
	.introwrap ol ol {padding-left:28%;}
}
@media screen and (max-width:915px) {
	.introwrap::after {background-size:cover;}
}
@media screen and (max-width:850px) {
	h1 {font-size:2.5em;}
	.outer {border-width:85px;}
	body {font-size:1.35em;}
	.introwrap p:last-of-type {font-size:1.65em;}
	h2 {font-size:1.8em;}
}
@media screen and (max-width:800px) {
	.introwrap::after {
		height:98px; 
		background-position:center -200px;
		background-size:initial;
	}
}
@media screen and (max-width:750px) {
	h1 {font-size:2.0em;}
	.outer {border-width:75px;}
	body {font-size:1.2em;}
	.introwrap p:last-of-type {font-size:1.4em;}
}
@media screen and (max-width:700px) {
	.introwrap ol {text-align:left; list-style-position:outside;}
	.introwrap ol ol {padding-left:15%;}
}
@media screen and (max-width:630px) {
	.introwrap::after {background-position:center -304px;}
}
@media screen and (max-width:600px) {
	.introwrap ol ol {padding-left:10%;}
}
@media screen and (max-width:530px) {
	.introwrap::after {background-position:center -404px;}
}
@media screen and (max-width:500px) {
	h2 {font-size:1.5em;}
	.introwrap ol ol {padding-left:5%;}
}

I’m not really sure if anyone cares to write back anymore, but if this can be improved, please do share.

No! :grin:

I’ll try to explain what was in play here and how to control it. :thinking:

You wanted a dynamic size of the background while keeping the aspect ratio of the image. So you used background-size: cover;

When the container width changes, the “cover” will also change the hieght of the image, so a pixel height position is never at the same point. A percentage height position always follows the current height, but the specs also tells you that when you use percentage to position the background, it will be used both for the image and where that point in the image appears in the container.

(Also noted in the specs; when the image and its container matches in size the percentage value will not affect the background’s position as it always points to the same pixel for both.)

The percentage position is explained at dev sites like Mozilla Dev, CSS-Tricks, and even Slashdot. They give some useful methods to calculate where the image will be positioned when the image and its container have different sizes. With the math you could find the percentage value that results in the position you want.

Unfortunately none I’ve seen has explained what happens if the background’s container is fluid or if the image’s size changes by some parameter.

I’ll try to sort out the parameters in your case. The version I answered to used “cover” to adjust the background size to fit its fluid container and I suggested the “vw” value to also adjust the container’s height to fit the sprite parts. Now, with more space around the sprite parts, a pixel height could also work.

The addition/subtraction was needed to adjust the position according to the background and container heights to preserve the relative position in all cases.

The algorithm I tossed up could be described by the terms:

P - Percentage point in the image that is to be moved. (E.g: the middle point of the sprite image part)

H - the container Height in current unit.

C - the percentage number for the point in the Container where the image point is to move. (Like .50 or 50/100 for the 50% center.)

I - the percentage number for the point in the Image that is to be moved in position. (e.g: .25 for 25%)

D - (C/100 - I/100) The +/- Difference factor of C and I.

A - (Hvw * D) The +/- length in current unit to Adjust the image position in the container.

calc(P% +/- Avw) - The resulting calc to get the image in the (pixel) position you want.

Now, with more space between the sprites, the container’s pixel height is simpler to work with.

Well done! :slightly_smiling_face:

There are different ways to achieve that.

But you could also use “cover” and the “calc()” above to fit the bar in a suitable height, vw or px as current unit. :slightly_smiling_face:

5 Likes

Thanks for the in-depth response. It’s certainly my first go-around with the calc() function, but if I’m lucky enough, I’ll get to correspond with you when I reach the 2nd section when the bar designs will be displayed. My inclination was to use the border-image property and display it using the round or stretch values, though now I know that calc() can be applied universally. I also discovered that while cover is a value that maintains the aspect ratio of the image, a percentage value achieves the same elasticity.

Although you may not have mentioned file size in your post because it may not be as important as I’m making it out to be, but this is going to be the longest page I’ve ever made, and I don’t know how cautious to be in regards to page file size. I think you may have been hesitant at the idea of using 3rd and 4th hooks because now the file size for this one image is 183kb, but maybe I should tuck that issue on the back burner until this page grows to be a little more mature. I’m going to do some reading and some searching here on the forums to see if I can find out more about the page file size issue.