Making custom themes work with RTL languages.

Started by Antechinus, June 16, 2011, 03:02:03 AM

Previous topic - Next topic

Antechinus

Having your custom theme fully compatible with RTL languages is not required for getting a theme approved by the Customise Team, but these days in 2.0 we have this magical thing called rtl.css. It makes sense to use it, and it's a lot easier than you mght think.

Why should you care? Well, if you're into making custom themes you presumably want to make cool stuff for other people. Some other people use RTL languages. Having a good rtl.css makes things easy for them and they'll think you're really clever. ;)

So, how do we do this? I've recently approved a couple of themes that were next in the queue, and I gave the authors complete rtl.css for their themes as an optional extra. Now I'm not going to get into writing complete custom rtl.css for everyone. I simply don't have the time. I'll just use one of those themes as an example for everyone since it illustrates all the basic points very well.

The first thing to understand is that rtl.css only relates to positioning. Colours aren't relevant so you don't have to worry about them. In 99% of cases images wont be relevant either. If you hit an odd case where an image does need to be changed it will be obvious, but in general you can ignore all code related to images and colours (the exception is usually things like positioning of logos).

The second thing to understand is that all positioning for default elements is already covered by the default rtl.css. You don't need to worry about default elements unless you have changed their positioning. Most themes use standard positioning for default elements and custom positioning for custom elements. With themes like this, you only have to worry about the custom classes and ID's, and you only have to worry about the code specifically tied to their positioning. This usually isn't much, and a reasonably proficient coder can do it all in ten minutes without trying too hard.

How do you know when you have it right? Easy. Use an RTL language to check it. I have Arabic and English installed on my test sites just for this purpose. I leave the languages section of admin open in one tab, so I can switch languages easily while testing in other tabs. I can't read Arabic, but that doesn't matter. I know where all the buttons are and I can see the url for any link in my status bar. Navigation is still easy, and this is fine for the amount of testing required.

On to examples. This first pile of code is the index.css custom classes from the theme I'll be using as a demonstration.

#header {
   position: relative;
   height: 147px;
   overflow: hidden;
   background: url(../images/theme/headerb.jpg) 0 0 repeat-x;
}
#head-r {
   height: 147px;
   background: url(../images/theme/headerr.jpg) 100% 0 no-repeat;
}
#head-l {
   background: url(../images/theme/headerl.jpg) 0 0 no-repeat;
}
#navbar {
   background: url(../images/theme/navbg.png) repeat-x;
   width: auto;
   height: 32px;
   margin: 0 0.7em;
   padding: 0;
   line-height: 32px;
   border-top: 1px solid #2b2b2b;
   border-bottom:  1px solid #2b2b2b;
   clear: both;
}
#navtop {
   position: relative;
   height: 32px;
   z-index: 1000;
   padding: 0;
   margin: 0;
}
#navtop ul {
   margin: 0;
   padding: 0;
}
#navtop li {
   float: left;
   margin: 0;
   padding: 0 0 0 2px;
   position: relative;
   list-style: none;
}
#navtop ul li {
   display: block;
   padding: 0px 2px 0px 0px;
   float: left;
   height: 32px;
   width: auto;
   margin: 0px;
   background: url(../images/theme/navsep.gif) no-repeat top right;
}
#navtop li a {
   display: block;
   line-height: 32px;
   padding: 0 11px;
   color: #FFF;
   font-size: 0.9em;
   text-transform: capitalize;
}
#navtop li a.active {
   color: #BBBBBB;
   text-decoration: none;
   background: url(../images/theme/navbg.gif) repeat-x;
   font-weight: bold;
}
#navtop li a:hover, #navtop li:hover a, #navtop li.sfhover a {
   color: #FFF;
   text-decoration: none;
   background: url(../images/theme/navbg.gif) repeat-x;
}
#navtop li:hover li a, #navtop li ul li a:hover {
   color: #FFF;
   background: url(../images/theme/navbg.gif) repeat-x;
}
#navtop li li {
   width: 200px;
   height: auto;
   padding: 0;
}
#navtop li li a, #navtop li li a:hover, #navtop li li a, #navtop a.active li a, #navtop li:hover li a, #navtop li.sfhover li a {
   background: none;
   height: 30px;
   line-height: 30px;
   margin: 0;
   font-weight: normal;
   text-transform: none;
   font-size: 0.9em;
   color: #777;
}
#navtop li ul {
   background: #2b2b2b;
   position: absolute;
   border-left: 0.19em solid #98251B;
   border-bottom: 0.21em solid #98251B;
   width: 200px;
   left: -999em;
   margin-left: -1px;
}
#navtop li ul ul {
   margin: -27px 0 0 195px;
}
#navtop ul li li:hover, #navtop ul li li.hover {
   position: static;
}
#navtop li:hover ul ul, #navtop li:hover ul ul ul, #navtop li.sfhover ul ul, #navtop li.sfhover ul ul ul {
   left: -999em;
}
#navtop li:hover ul, #navtop li.sfhover ul {
   left: 3px;
}
#navtop li li:hover ul, #navtop li li li:hover ul, #navtop li li.sfhover ul, #navtop li li li.sfhover ul {
   left: 0;
}
#logo a {
   position: absolute;
   top: 2em;
   left: 2em;
   display: block;
   width: 451px;
   height: 30px;
   cursor: pointer;
   background: url(../images/theme/logo.png) no-repeat;
}
#searcharea {
   clear: both;
   position: absolute;
   bottom: 20px;
   right: 2em;
   padding: 0;
   display:block;
   float:right;
   margin:0 22px 0 0;
   width:191px;
   height:30px;
   background:url(../images/theme/search_bg.png) no-repeat;
}
#searcharea .inputbox {
   font: 12px "Lucida Grande","Lucida Sans Unicode",Arial,sans-serif;
   width: 140px;
   height:13px;
   line-height:13px;
   margin:5px 0 0 19px;
   padding:3px 5px 4px 7px;
   float:left;
   background: none;
   border: none;
   color: #ccc;
}
#top-main {
   background: url(../images/theme/topb.png) 0 0 repeat-x;
}
#top-r {
   background: url(../images/theme/topr.png) 100% 0 no-repeat;
}
#top-l {
   background: url(../images/theme/topl.png) 0 0 no-repeat;
   padding: 15px 25px 20px 25px;
}
#bodyarea {
   padding: 10px;
   color: #333;
   background: #F5F5F5;
   color: #333;
   padding-left: 20px;
   padding-bottom: 25px;
   padding-right: 20px;
   margin: 0;
}
.clr {
   clear: both;
}
#bdy-l {
   background: url(../images/theme/bl.png) 0 50% repeat-y;
   padding-left: 11px;
}
#bdy-r {
   background: url(../images/theme/br.png) 100% 50% repeat-y;
   padding-right: 11px;
}
#my-avatar {
   float: right;
   padding-top: 2px;
   padding-left: 10px;
}
#userarea {
   float: right;
   margin: 0 1em;
   padding: 0.82em 1em 0 0;
   text-align: right;
   width: 38em;
   color: #f0f0f0;
   line-height: 125%;
}
#userarea ul li.greeting {
   font-size: 1.2em;
   font-weight: bold;
   line-height: 1.1em;
}
#userarea a:link, #userarea a:visited {
   color: #f0f0f0;
}
#userarea a:hover {
   color: #CC3333;
   text-decoration: underline;
}
#news {
   position: absolute;
   float: left;
   clear: both;
   top: 10.5em;
   left: 2em;
   text-align: left;
   font-size: 8pt;
   color: #B7B7B7;
   font-family: Helvetica, Arial, sans-serif;
   width: 50%;
}
#news a:link, #news a:visited {
   color: #B7B7B7;
}
#news a:hover {
   color:  #D73C26;
   text-decoration: none;
}
#footer {
   background: url(../images/theme/footb.png) 0 100% repeat-x;
}
#foot-r {
   height: 73px;
   background: url(../images/theme/footr.png) 100% 100% no-repeat;
}
#foot-l {
   background: url(../images/theme/footl.png)  0 100% no-repeat;
}
#footerarea {
   text-align: center;
   font-family: Verdana, Helvetica, Arial, sans-serif;
   color: #222;
   padding: 15px;
   line-height: 130%;
}
#footerarea a:link, #footerarea a:visited {
   color: #222;
}
#footerarea a:hover {
   color: #D73C26;
   text-decoration: underline;
}


The second pile of code is all the custom rtl.css that was needed to make the theme work in RTL languages. As you can see, there's not much needed.

#navtop li {
   float: right;
   margin: 0;
   padding: 0 2px 0 0;
}
#navtop ul li {
   padding: 0 0 0 2px;
   float: right;
   background: url(../images/theme/navsep.gif) no-repeat top left;
}
#navtop li ul {
   background: #2b2b2b;
   border-right: 0.19em solid #98251B;
   border-bottom: 0.21em solid #98251B;
   right: -999em;
   margin-right: -1px;
}
#navtop li ul ul {
   margin: -27px 195px 0 0;
}
#navtop li:hover ul ul, #navtop li:hover ul ul ul, #navtop li.sfhover ul ul, #navtop li.sfhover ul ul ul {
   right: -999em;
}
#navtop li:hover ul, #navtop li.sfhover ul {
   right: 0;
}
#navtop li li:hover ul, #navtop li li li:hover ul, #navtop li li.sfhover ul, #navtop li li li.sfhover ul {
   right: 0;
}
#logo a {
   right: 2em;
}
#searcharea {
   left: 2em;
   right: auto;
   float: left;
   margin:0 0 0 22px;
}
#searcharea .inputbox {
   margin: 5px 19px 0 0;
   padding: 3px 7px 4px 5px;
   float: right;
}
#my-avatar {
   float: left;
   padding-right: 10px;
}
#userarea {
   float: left;
   padding: 0.82em 0 0 1em;
   text-align: left;
}
#news {
   float: right;
   right: 2em;
   text-align: right;
}


Steps are:

1/ change any instances of float: left; to float: right;

2/ change any instances of float: right; to float: left;

3/ change any left margins into right margins (paddings are treated the same way).

4/ change any right margins into left margins (again, paddings are treated the same way).

5/ CSS borders can be treated the same way as margins and paddings.

6/ Sometimes you will need to move an image around. The following example is an image divider between menu tabs. Most of the code can be ignored. The only changes are to the left/right padding, the float, and the position of the divider image.

Index.css:

#navtop ul li {
   display: block;
   padding: 0px 2px 0px 0px;
   float: left;
   height: 32px;
   width: auto;
   margin: 0px;
   background: url(../images/theme/navsep.gif) no-repeat top right;
}


Rtl.css:

#navtop ul li {
   padding: 0 0 0 2px;
   float: right;
   background: url(../images/theme/navsep.gif) no-repeat top left;
}


Sometimes an alternative syntax is used for image positioning. The last lines could also be written like this, which means the same thing:

Index.css:

#navtop ul li {
   background: url(../images/theme/navsep.gif) no-repeat 100% 0;
}


Rtl.css:

#navtop ul li {
   background: url(../images/theme/navsep.gif) no-repeat 0 0;
}


7/ Relative and absolute positioning.
    This is slightly trickier. In the case of elements that use relative or absolute positioning, the positioning has to be changed from (example) left: -999em; to right: -999em; Obviously, if the positioning is set as (other example) right: -999em; in index.css it will be changed to left; -999em; in rtl.css. This will deal with most cases, but sometimes you will find that an element still appears to be "stuck" in the original position.

What is happening here is that it is still reading the original index.css and is getting confused between the two. In this case you override the index.css by using the auto value in rtl.css. So if positioning is set as (example) right: -999em; in index.css, you would use left; -999em; right: auto; in rtl.css. You can see an example of this in the code for #searcharea.

Index.css:

#searcharea {
   clear: both;
   position: absolute;
   bottom: 20px;
   right: 2em;
   padding: 0;
   display:block;
   float:right;
   margin:0 22px 0 0;
   width:191px;
   height:30px;
   background:url(../images/theme/search_bg.png) no-repeat;
}


Rtl.css:

#searcharea {
   left: 2em;
   right: auto;
   float: left;
   margin:0 0 0 22px;
}


Note that only the code that relates to left/right positioning is modifed. The rest is ignored.

In practice, doing this takes less time than reading about it once you have done it once or twice. It's really not that big a deal, and it will make your theme more accessible to a wider range of people. That's why we do it in the default theme. :)


Advertisement: