82

I have this HTML:

<div id="graphic">lorem ipsum</div>

with this CSS:

#graphic { background-image: url(image.jpg); width: 200px; height: 100px;}

The background image I'm applying is 200x100 px, but I only want to display a cropped portion of the background image of 200x50 px.

background-clip does not appear to be the right CSS property for this. What can I use instead?

background-position should not be used, because I'm using the above CSS in a sprite context where the image part I want to show is smaller than the element on which the CSS is defined.

TRiG
  • 10,148
  • 7
  • 57
  • 107
Dahie
  • 1,115
  • 1
  • 8
  • 9

3 Answers3

110

You can put the graphic in a pseudo-element with its own dimensional context:

#graphic {
  position: relative;
  width: 200px;
  height: 100px;
}
#graphic::before {
  position: absolute;
  content: '';
  z-index: -1;
  width: 200px;
  height: 50px;
  background-image: url(image.jpg);
}

#graphic {
    width: 200px;
    height: 100px;
    position: relative;
}
#graphic::before {
    content: '';
    
    position: absolute;
    width: 200px;
    height: 50px;
    z-index: -1;
    
    background-image: url(http://placehold.it/500x500/); /* Image is 500px by 500px, but only 200px by 50px is showing. */
}
<div id="graphic">lorem ipsum</div>

Browser support is good, but if you need to support IE8, use a single colon :before. IE has no support for either syntax in versions prior to that.

Agamemnus
  • 1,395
  • 4
  • 17
  • 41
Brent
  • 2,961
  • 1
  • 17
  • 18
  • I'm not seeing the background at all on your jsfiddle – Jeremy Moritz Aug 25 '14 at 22:16
  • @JeremyMoritz Looks like placekitten service is broken/down at the moment. Changed to use placehold.it. – Brent Aug 28 '14 at 14:42
  • This answer guided me towards using before and after instead of multiple backgrounds when you just need 2, and you can use sprites as well! – Tebo Feb 07 '15 at 20:37
  • what if I want to clib from inside not from left top? – JaskeyLam Oct 22 '15 at 09:31
  • 1
    @Jaskey : Just move the background with ```background-position``` inside pseudo-element. – Gelmir May 13 '16 at 09:17
  • 2
    For anyone unfamiliar with how pseudo elements render, the browser places them inside the html of the element you're targeting. I'm saying this so you don't have to learn the long way about discovering how it doesn't work with elements such as input fields which don't have internal html. – amonett Oct 12 '16 at 00:58
13

may be you can write like this:

#graphic { 
 background-image: url(image.jpg); 
 background-position: 0 -50px; 
 width: 200px; 
 height: 100px;
}
sandeep
  • 91,313
  • 23
  • 137
  • 155
  • actually that should work that is if you don't want to scale the background as well. if you want to scale the background as well, then you will have to use the tag – Shamsudeen Zziwa Oct 15 '11 at 10:36
  • @ShamsudeenZziwa; he didn't want to scale the image. He just want to show an image with 200x50px dimension. – sandeep Oct 15 '11 at 10:57
  • 1
    `background-position` should not be used, because I'm using the above css in a sprite-context and I therefore try to avoid this and see if I have other options. I will add this info also to the initial post. – Dahie Oct 15 '11 at 11:05
  • then a fiddle example is better to understand your problem – sandeep Oct 15 '11 at 11:14
3

Another option is to use linear-gradient() to cover up the edges of your image. Note that this is a stupid solution, so I'm not going to put much effort into explaining it...

.flair {
  min-width: 50px; /* width larger than sprite */
  text-indent: 60px;
  height: 25px;
  display: inline-block;
  background:
    linear-gradient(#F00, #F00) 50px 0/999px 1px repeat-y,
    url('https://championmains.github.io/dynamicflairs/riven/spritesheet.png') #F00;
}

.flair-classic {
  background-position: 50px 0, 0 -25px;
}

.flair-r2 {
  background-position: 50px 0, -50px -175px;
}

.flair-smite {
  text-indent: 35px;
  background-position: 25px 0, -50px -25px;
}
<img src="https://championmains.github.io/dynamicflairs/riven/spritesheet.png" alt="spritesheet" /><br />
<br />
<span class="flair flair-classic">classic sprite</span><br /><br />
<span class="flair flair-r2">r2 sprite</span><br /><br />
<span class="flair flair-smite">smite sprite</span><br /><br />

I'm using this method on this page: https://championmains.github.io/dynamicflairs/riven/ and can't use ::before or ::after elements because I'm already using them for another hack.

Mingwei Samuel
  • 2,917
  • 1
  • 30
  • 40