Welcome to WebmasterWorld Guest from 34.204.191.31

Forum Moderators: not2easy

Message Too Old, No Replies

Using background-size to shrink a sprite

     
2:16 am on Jul 1, 2018 (gmt 0)

Senior Member

WebmasterWorld Senior Member 5+ Year Member Top Contributors Of The Month

joined:Mar 15, 2013
posts: 1194
votes: 119


I have 2 sprites set up for emojis, where one is just a larger version of the original emojis so that the user can mouse over the small emoji and see it bigger.

It originally looked like this:

[data-emoji] {
background:url('//example.com/sprite_emoticon.png');
width: 19px;
height: 19px
}

[data-emoji_large] {
background:url('//example/sprite_emoticon_large.png');
width: 40px;
height: 40px;
display: none
}

[data-emoji='01'],
[data-emoji_large='01'] { background-position: 0 0 }

...

[data-emoji='56'] { background-position: 0 -836px }
[data-emoji_large='56'] { background-position: 0 -1804px }


But since each data-emoji is just a smaller version of the same data-emoji_large, I feel like I'm wasting bandwidth by loading 2 images and doubling down on the CSS... why not just load the larger version, then use background-size to make the smaller one?

Assuming you guys agree that this is a good idea in the first place...

How do I modify each of the [data-emoji='xx'] elements to be the smaller version of the original?

I've gotten this far:

[data-emoji], [data-emoji_large] {
background:url('//example.com/sprite_emoticon_large.png');
}

[data-emoji] {
width: 19px;
height: 19px;
background-size: contain
}

[data-emoji_large] {
width: 40px;
height: 40px;
display: none
}

// I thought this would be the next section
[data-emoji='56'],
[data-emoji_large='56'] { background-position: 0 -1804px }


but the problem is that [data-emoji='56'] takes the entire sprite_emoticon_large.png and shrinks it down to 19x19, instead of just the 40x40 section that was defined by [data-emoji_large]. Which makes sense, really, because at this point [data-emoji] doesn't "know" that the original is 40x40.

So what's the right way to do it?
2:26 am on July 1, 2018 (gmt 0)

Senior Member

WebmasterWorld Senior Member 5+ Year Member Top Contributors Of The Month

joined:Mar 15, 2013
posts: 1194
votes: 119


Oh, and before someone asks, "why not have them both in one sprite?"

My script shows the smaller emojis immediately, but only shows the larger ones when the user mouses over the smaller one. So my original logic was to load the smaller image (12kb) in line with the page, then I load the second one (40kb) last on the page since it wouldn't be needed quite so quickly.

Using the above CSS method takes away that ability to load them separately, anyway, but if I mash the images together then I go from a 40kb image to a 52kb one. So if there's a way that I can just use the one and save 12kb of download time, I'd rather use that :-)
3:14 am on July 1, 2018 (gmt 0)

Administrator from US 

WebmasterWorld Administrator not2easy is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Dec 27, 2006
posts:4525
votes: 350


It's kind of hard to tell what's going on because I haven't worked with CSS that uses [element] (within brackets). Is this the name of the class?
5:06 am on July 1, 2018 (gmt 0)

Administrator from US 

WebmasterWorld Administrator not2easy is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Dec 27, 2006
posts:4525
votes: 350


Looking into the syntax, I see that it is used for textarea with .svg image files or css sprites. It could be that the
[data-emoji='56']
needs its own css to prevent its defaulting to the css for "[data-emoji]" but as mentioned, I have not integrated emoji this way myself, so I'm not much help.
5:14 am on July 1, 2018 (gmt 0)

Senior Member

WebmasterWorld Senior Member 5+ Year Member Top Contributors Of The Month

joined:Mar 15, 2013
posts: 1194
votes: 119


No, it's the data-attribute... I think it's new to HTML5, and it's something I've started using recently because it's given me more flexibility with some things. I think of it as if classes could be arrays.

So where I was doing this before:

.sprite {
background:url('//example.com/sprite_emoticon_large.png');
width: 19px;
height: 19px
}

.image { background-position: 0 0 }

<div class="sprite image"></div>


I'm now doing:

[data-sprite] {
background:url('//example.com/sprite_emoticon_large.png');
width: 19px;
height: 19px
}

[data-sprite='1'] { background-position: 0 0 }

<div data-sprite="1"></div>


So you see, it gives me the option of setting multiple attributes to a single element (eg, <div data-sprite="1" data-foo="bar" data-csdude="cool"></div>), and I can assign styles or functions to [data-sprite] and [data-sprite="1"] separately.

And in jQuery, I can do something like this:

[data-sprite]
.on('click', function() {
console.log($(this).data('sprite'));
})


which would give me the value of data-sprite (in this case, "1").

It also doesn't have to have a value; so I could just say <div data-foo></div>, then in jQuery:

[data-foo]
.on('click', function() {
console.log("you clicked it!");
})


Check this out:

[sitepoint.com...]
7:05 am on July 25, 2018 (gmt 0)

Senior Member

WebmasterWorld Senior Member 5+ Year Member Top Contributors Of The Month

joined:Mar 15, 2013
posts: 1194
votes: 119


For posterity, I figured this one out! But I have no clue why it works.

[data-emoji],
[data-emoji_medium],
[data-emoji_large] {
background:url('//example.com/sprite_emoticon_large.png');
background-size: 100%
}

// changed from 19 to 20 for the sake of easy math
[data-emoji] {
width: 20px;
height: 20px
}

// added this one just as an example for you guys
[data-emoji_medium] {
width: 30px;
height: 30px
}

[data-emoji_large] {
width: 40px;
height: 40px
}

[data-emoji=56] { background-position: 0 -902px }
[data-emoji_medium=56] { background-position: 0 -1353px }
[data-emoji_large=56] { background-position: 0 -1804px }


The sprite_emoticon_large.png image is of the emojis at 40px width, so the other two scale it down. You'll see that the background position on the first one is half of the third one (because 20px is half of 40px), and the middle one is 75% of the third one (because 30px is 75% of 40px).

"background-size: 100%" was the magic trick. Without it, they don't scale.

It makes absolutely no sense to me as to why this worked, but it did. I'm guessing that the width in each one set the background size appropriately?
7:03 am on July 27, 2018 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member tangor is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Nov 29, 2005
posts:10471
votes: 1099


Appears to work the same way as the auto image width 100% works ... it fits the container. :)