Background Images

Using backgrounds in CSS gives you the ability to control its position. It is done by controlling its position relativly to the 0,0 point which is the top left corner of the block. If you're rule has a background-position value of left top for example, flipping it to be right top wouldn't be a problem since right is a valid value.

So where's the problem? Let's say you're flipping an LTR design, you come across a rule where the background-position is set to 20px 15px. This means that the image will be moved 20px from the left and 15px from the top.Check the screenshot below.

Now you need to flip it to move 20px from the right instead of the left. Unfortunately when the page's direction is flipped to RTL the 0,0 point of the block will remain to be the top left corner.

There are many ways to solve this. We'll use a very common example where this issue can be faced, custom bullets of a list item <li>.

The HTML is a simple UL:

  • Link Item 1
  • Link Item 2
  • Link Item 3
  • Link Item 4
  • Link Item 5

 

And the CSS is also simple:

ul	{ list-style:none; border:1px solid #1b75bc; width:300px;
	  float:left; margin:0;padding:20px 0;}
	
ul li { background:transparent url('bullet.png') 10px 0 no-repeat;
		padding:0 30px; line-height:20px; border-bottom:1px solid #d8ecbd;
		margin:5px 0;}

The LTR list looks like this:

LTR Menu Screenshot

1. Calculate the actual distance from the left

Simply you'll subract the offset of the bullet (20px in our example) from the container's width (300px in our example). So 300-20=280px. The RTLed background position will be: 280px 15px.

Pros:

No need to manipulate the photo or add extra HTML or CSS

Cons:

You'll need to know the width of the container (which isn't possible in fluid layouts). And if you changed the width of the container, moved the list to another block or used it somewhere else, you'll have to recalculate the new offset or use different values to each one.

[UPDATE]: As pointed out by Daniel, percentages can be used instead of px values. This applies to both LTR and RTL layouts. So instead of 20px we use 0.0.6%(20/300). And in the RTL CSS, we'll replace it with a 99.94%(100-0.06). Of course we might need to re-caluclate the percentage if the block is moved to a relatively wider or narrower container. But in general, it'll get more accurate results than a fixed px value since you might not change the percentage value if the difference isn't that big.

2. Add the space to the image

Since the right is a valid value of the background-position rule, we can use it and add the whitespace to the image itself. We'll add extra 20px of white space to the right of our bullet picture and set its position to the right to have the effect that it's 20px away from the right edge. Check the screenshot below of the bullet used.

Bulluet with extra whitespace to the right

Pros:

No need to add extra HTML or CSS

Cons:

You'll need to modify the photo each time you update the offset. Or worse, you'll end up having many images with different widths according to each offset you use in your design.

3. Use margin and padding

This method will also use the "right" keyword that can be used in the background-position rule. But instead of assigning the background image to the list item <li> itself, we'll wrap the content with a <span> for example and assign the background image to this span. Then we add the offset value (our 20px) as a right-margin. Finally, we'll set the right-padding of the span to the difference between the of the padding of the <li> and the bg-image offset (to move the content away from the image) after resetting the padding of the <li> itself (since we used them on the span).

Pros

Can be modified easily and used anywhere.

Cons

You will have to wrap the content of the <li> with a child. It's not really a con compared to how effective this method is. And extra content won't affect the layout if not used (the LTR styles won't need to be changed with the extra markup).

 4. Avoid it :)

Okay this might be silly but if you can avoid setting an offset then why not? Do you have any other solutions or suggestions? Please share them in the comments

The Source code of this tutorial is available to download. You'll see the three solutions available as three CSS classes. You can test them by changing the class assigned to the <ul> in the <div id="rtl"> block.

Average: 3 (11 votes)

Comments

Good Info, thank you.

Couldn't you work out the x and y percentages of where they appear in the container..
So instead of
background:transparent url('bullet.png') 280px 0 no-repeat;

use something like:
background:transparent url('bullet.png') 90% 0 no-repeat;

That's a very nice and effective way too, I use it sometimes(can't believe I missed to add it to the article). But it shares somehow the same cons as using a fixed x value, if you move the block to a different section or modified the width, you'll have to recalculate it(90% of 300px isn't the same as 90% of a 500px).
Thanks for the heads up. I'll update the post.

It's true that 90% of 300px isn't the same as 90% of a 500px, however using %'s would be better than using fixed px values because at least the general position within the container will be the same - which means that even if the container width changes - you still may not need to update the % of the horizontal value

I Agree!
Thanks again for the note. Post is updated.

In modern browsers you can now use the 4-value background position syntax which does exactly what you want, so:
background: transparent url('bullet.png') 10px 0 no-repeat;

becomes:
background: transparent url('bullet.png') right 10px top 0 no-repeat;

Unfortunately this doesn't work in IE8, so for automatic RTL conversion the only workaround I found is to measure containers and images after page load and set the new position with javascript ( https://github.com/yonatan/rtl-toolkit/blob/49ec076dcfe8bb1b3f49b012c1aa... ).

Add new comment

Twitter Updates

Recent comments

Who's online

There are currently 0 users online.