14

I am creating a card game . I have a sprite image of cards . Say in the sprite , each of the cards is 50px wide and 80px high . enter image description here Now I have some divs where I want to place these cards . enter image description here

Say the Divs are 100px wide and 160px high .

I have using the first image as a Sprite for the Divs like in the below.

background: url(../images/poker_sprite.gif) no-repeat scroll 0 0 transparent ;

I vary the x and y positions so that different divs get diff cards .

What CSS property do I use to make the background image fit to the Div ? I am not allowed to change the size of the Sprites or the Div .

Now I am going to Drag these cards and place them into some slots as marked 1-13 below . enter image description here

So the card div will have variable width . The background image will need to resize to fit in the variable width div . How do I go about doing this ? Should I used multiple sprites of various sizes?

Thanks !

geeky_monster
  • 8,672
  • 18
  • 55
  • 86

7 Answers7

21

You can achieve this using the background-size property, although the results might not be too pretty, since it stretches the background image.

So, if you know that your sprite is 13x5 cards exactly in size, you can give the cards background-size: 1300% 500% and then size them any way you want, since the background itself will scale accordingly.

Example

JSFiddle: http://jsfiddle.net/uLnzc/.

HTML

<!-- Hearts --->
<div class="card card-hearts-2"></div>
<div class="card card-hearts-3 card-wide"></div>
<div class="card card-hearts-4 card-high"></div>

<!-- Clubs -->
<div class="card card-clubs-q"></div>
<div class="card card-clubs-k card-wide"></div>
<div class="card card-clubs-a card-high"></div>

CSS

.card {
    width: 81px;
    height: 117px;
    background: url('https://i.stack.imgur.com/WZ9Od.gif') no-repeat;
    background-size: 1300% 500%;
}
.card-wide {
    width: 100px;
}
.card-high {
    height: 130px;
}

/**
 * Backgrouns position of all the cards
 *
 * x offset in %: i * (100/x); i = 0, 1, ..., (x - 1); x = the number of cols in the sprite
 * y offset in %: j * (100/y); j = 0, 1, ..., (y - 1); y = the number of rows in the sprite
 */

.card-hearts-2 { background-position: 0 0; }
.card-hearts-3 { background-position: 8.33% 0; }
.card-hearts-4 { background-position: 16.667% 0; }
/* ... */

/* ... */
.card-clubs-q { background-position: 83.333% 50%; }
.card-clubs-k { background-position: 91.667% 50%; }
.card-clubs-a { background-position: 100% 50%; }

You can read about offsetting backgrounds in percentages at MDN.

JSFiddle: http://jsfiddle.net/uLnzc/.

Alexander Wallin
  • 1,394
  • 10
  • 22
  • Great !! I think this is what I wanted . I wasnt aware of that background size could be used this way . Let me try this out . – geeky_monster Aug 29 '13 at 01:44
  • Do it. You should note that ``background-size`` isn't supported in IE8 and below. – Alexander Wallin Aug 29 '13 at 01:55
  • Ok. No worries. This works . We are targeting WebKit browsers as of now . – geeky_monster Aug 29 '13 at 02:00
  • What do I do if am using Javascript later to change the height & width ? I find that the background image gets changed to another card . – geeky_monster Aug 29 '13 at 03:11
  • I've updated to answer to handle rendering of different cards. Altering width with JavaScript is no different from doing it using CSS. – Alexander Wallin Aug 30 '13 at 13:14
  • 1
    Wow. Totally worked. I had no idea that was possible. – Gabriel Yarra Apr 11 '14 at 06:15
  • Fantastic solution. In my case, I was originally trying to work with a sprite of different sized items, which made this way too complicated. Luckily my sprite was made up of groups of similar items, so all I needed to do was pull them out into sprites of similarly-sized elements and this method worked beautifully. – Mike Jan 20 '17 at 19:47
  • This might work for a deck of cards, but others should be warned that when they add additional icons or images to a sprite sheet and increase the height or width, it will throw off the math and you will need to fix every icon. For many applications, this is a huge chore and I've frequently seen it cause more trouble than it's worth. I've seen sites where it was so problematic that each time they need to add an icon they would just create a whole new sprite sheet rather than tamper with the previous fragile ones. – Andrew Craswell Aug 14 '17 at 18:40
1

Another solution is to create an SVG and assign class attributes to the different path groups (each representing/rendering a card). If all path groups have position: absolute and display: none, you could show only the path group matching the container card element and stretch it to full width and height with pure vector resizing.

This will generate huge amounts of markup, so the best thing here would probably be on SVG per card.

Chris Coyier has an excellent article about using SVGs.

Example

HTML+SVG

<div class="card card-hearts-ace">
    <svg id="cards-svg" ...>
        <g class="svg-card svg-card-hearts-ace">
            <path fill="#FF0000" d="..." />
            <path fill="#FF0000" d="..." />
        </g>
        <g class="svg-card svg-card-hearts-2">
            <path fill="#FF0000" d="..." />
            <path fill="#FF0000" d="..." />
        </g>
        ...
    </svg>
</div>

CSS

.card .svg-card {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
.card-hearts-ace .svg-card-hearts-ace {
    display: block;
}
.card-hearts-2 .svg-card-hearts-2 {
    display: block;
}
/* And so on... */
Alexander Wallin
  • 1,394
  • 10
  • 22
1

Hi this is the easiest way of doing what you are after!

CSS -

.smking,.king{
position: relative;
background-image: url(https://i.stack.imgur.com/WZ9Od.gif);
background-size: 1300% 500%;
}

.king{
width: 50px;
height: 80px;
background-position: 100px 0px;
}

.smking{
width: 30px;
height: 50px;
background-position:  60px 0px;
}

HTML -

<div class="king"></div>
<div class="smking"></div>

This will load your image once and set it up ready to be resized!

http://jsfiddle.net/j3xXe/10/

Regards

Alphanu

Alphanumu
  • 37
  • 2
  • The most important solution IMHO. The key point is the background-size scaling. It allows using relative units for setting the with/height of an element such like vw/vh. – srgg6701 Mar 24 '15 at 10:03
  • How did you arrive at the particular sizes / percentages? More explanation would improve the quality of this answer. – Professor Abronsius Sep 11 '22 at 08:54
0

For a regular image max-width: 100% and Max-height: 100% should force the image to resize to the div.

For a background-image background-size: 100% should work.

ZeroPhase
  • 649
  • 4
  • 21
0

I would suggest having 2 sprites, mainly because you have a smaller resolution in your example sprite then would look good in the example div.

innerurge1
  • 718
  • 3
  • 17
  • A complete pro way to handle this would be to create an SVG and assign ``class`` attributes to the different path groups (each representing a card). If all path groups have ``position: absolute`` and ``display: none``, you could show only the path group matching the container card element and stretch it to full width and height with pure vector resizing. – Alexander Wallin Aug 29 '13 at 01:40
0

This will do what I believe you are looking for and should be supported for all browsers.

Say you want a king in a specific slot what you would do is place these two classes in your css.

.king{
    width: 50px;
    height: 80px;
    position: relative;
    background-position: 50px 0px;
    background-image: url(https://i.stack.imgur.com/WZ9Od.gif);
}
.play-area{
    width: 50px;
    height: 80px;
    position: absolute;
}

Now for the html you just need

<div class="play-area">
    <div class="king"></div>
</div>

All you need to do is play around with the numbers so the borders of the cards displayed come out correct.

Here's the fiddle: http://jsfiddle.net/j3xXe/4/

ZeroPhase
  • 649
  • 4
  • 21
0

Alexander Wallin's answer is great! But I believe there is a small error in the formula for computing the percentage offset; where 100 is divided by x, it should be divided by (x-1):

/**
 * Background position of all the cards
 *
 * x offset in %: i * (100/(x-1); i = 0, 1, ..., (x - 1); x = the number of cols in the sprite
 * y offset in %: j * (100/(y-1); j = 0, 1, ..., (y - 1); y = the number of rows in the sprite
 */

PS: Sorry for making this comment as an answer. I do not have the necessary credits for making comments.

Leif John
  • 778
  • 6
  • 21