Vertically centring multi-line text with CSS

by James Diacono 18. November 2010 06:34

So you have a fixed height container, and you want your text to be vertically centred, whether it be one line or many lines of text.  In every browser.   This is possible, as I just learned from this article.

For all modern browsers, and IE8 and IE9, the method uses display:table-cell.  For IE6 and IE7, the method described in the above article is used, which takes advantage of a height bug.

You HTML looks like this:

<div id="container">
	<div id="wrapper">
		<div id="content">
			Stuff and things
		</div>
	</div>
</div>

Your CSS looks like this:

#container
{
	width:200px;
	height:50px;
	background-color:red;
	*position:relative;
}
#wrapper
{
	background-color:green;
	height:inherit;
	display:table-cell;
	vertical-align:middle;
	*height:auto;
	*position:absolute;
	*top:50%;
}
#content
{
	background-color:blue;
	*position:relative;
	*top:-50%;
	color:white;
}

The result looks like this:

IE6

ie6-multilineie6-singleline

IE7

ie7-multilineie7-singleline

IE8

ie8-multilineie8-singleline

IE9 Beta

ie9-multilineie9-singleline

Google Chrome

chrome-multilinechrome-singleline

And of course, this is not just constrained to text.  #content can be any variable-height block...

Categories: CSS

Mixing percentage and pixel dimensions in CSS

by James Diacono 9. November 2010 05:32

Okay, so there is no trick to actually compute these dimensions (except in IE).  However, there is a little known technique in CSS which is supported in all browsers and solves most of these problems.

Most usually, the desire to mix the two units comes about when one wants column A to fill the page except for column B, which has a fixed pixel width.  The problem becomes more formidable when doing the same thing with rows, the reason being that while a block element will naturally expand to fit its container’s width, there is no parallel behaviour for height.

The misconception: when positioning absolutely, two positions and two dimensions should be set.  I.E., top, left, width, height.

The truth: many combinations of position and dimension may be used.  Want to fill the page except for a 300px bar on the right?  Sure:

html, body {
    height: 100%;
}

#content {
    position:absolute;
    top:0;
    right:300px;
    bottom:0;
    left:0;
}

Turns out you don't even need to specify dimensions, they can be implied by positions. This is actually really old-school stuff which is supported by IE of old, back when it couldn't deal with flowing layouts very well. If you want to start combining percentages with pixels, just mess around with this technique and some containers.

Tags:
Categories: CSS

Styling XML with CSS

by James Diacono 23. April 2010 05:26

I’m sure you’ve heard of XSLT (DON'T GO AWAY I'M NOT SUPPORTING XSLT!). XSLT is used to transform XML into different XML – for example, rendering XML as HTML.  An example:

The XSLT method

<album>
	<title>Funkentelechy Vs. The Placebo Syndrome</title>
	<artist>Parliament</artist> 
	<year>1976</year> 
	<funkativity>10</funkativity> 
</album>

can be transformed (using XSLT) to this:

<div class="album">
	<h1>Funkentelechy Vs. The Placebo Syndrome</h1>
	<p class="artist">Parliament</p>
	<p class="year">1976</p>
	<p class="funkativity">This album has a funkativity rating of 10/10</p>
</div>

Now the question is, "is h1 a better tagname for the artist of the album than artist?". I'm pretty sure the answer is no. However, the HTML engine has no idea how to display an artist tag - it treats every unknown tag like a span tag.

The pure CSS method

So display information has to come from somewhere else. Some people may find the idea of markup depending entirely on CSS for display abhorrent. I do not. I maintain that reading the source of the album XML block makes just as much sense as reading the rendered HTML version. And screenreaders...if I was a screenreader I'd want concise and descriptive XML, rather than having to wade through a bunch of HTML crap. And let's be real: everyone's web client supports CSS.

Styling XML with CSS is actually very simple and very robust. The first thing to understand is that HTML is just a custom namespace of XML. The second thing to understand is you can have multiple namespaces present in any XML document. That means you can use both HTML and, say, a custom namespace...which you can define and set styling rules.

I won't blather much more. I'll just fill you in on how CSS targets namespaces.

The CSS @namespace declaration

In short, I can write up a stylesheet which targets a specific namespace and only a specific namespace. My XML file would look like this:

<?xml version="1.0" encoding="UTF-8" ?>
<albums xmlns="http://jdiacono.org/music">
	<album>
		<title>Funkentelechy Vs. The Placebo Syndrome</title>
		<artist>Parliament</artist> 
		<year>1976</year> 
		<funkativity>10</funkativity> 
	</album>
<albums>

Here I declare that the XML inside and including the albums block is of the namespace http://jdiacono.org/music. Don't be misled by the namespace looking like a URL...I haven't even registered jdiacono.org and this is still valid. This is because namespaces are actually just unique, case-sensitive strings, and URLs tend to be unique and full of information. Let it be known that this block is all there is. It is a completely self descriptive block of pure data, which references nothing external.

Now to style this...here is my CSS:

@namespace url("http://jdiacono.org/music");

albums {
	display:block;
	}
	
album {
	display:list-item;
	list-style-type:decimal;
	margin-bottom:0.5em;
	padding:0.5em;
	border:1px solid;
	}
	
album title {
	display:block;
	font-size:2em;
	font-weight:bold;
	border-bottom:1px dashed;
	}
	
album artist {
	display:block;
	font-size:0.9em;
	}
	
album year {
	display:block;
	font-weight:bold;
	letter-spacing:0.4em;
	color:Green;
	}
	
album funkativity {
	display:block;
	font-style:italic;
	}
	
album funkativity:before {
	content: "This album has a funkativity rating of ";
	}
	
album funkativity:after {
	content: "/10";
	}

Now I have another example that is much more nourishing, which uses HTML and a custom XML namespace in the same page. You will need a browser other than IE to view this.

farmcode.org/sourcecode/cssNamespaces/cssNamespaces.xml

UPDATE: Looks like IE9 is supporting this!

Categories: CSS

CSS3: Using the fun stuff in real life

by James Diacono 19. April 2010 12:08

Sweep IE6 under the carpet

Do whatever you can to remove IE6 support from your website’s build spec. Proper CSS selectors like the direct child (ul > li), the :hover state for elements other than anchors, and attribute selectors (a[href*=”http://”]do not work in IE6. Then, add ie6updatein a conditional comment and voila! IE6 users see a totally legit looking alert bar across the top of their screen telling them that the page below looks horrible because they have an old browser and need to upgrade. Now you are ready to begin.

CSS3 is only sort of supported

CSS3 is currently a working draft. Microsoft hence decided to implement barely any of its features in IE8, and as a result your CSS3 magic is restricted to ‘modern’ (real) rendering engines, like WebKit (Google Chrome, Safari) and Gecko (Firefox). However, the developers of these engines understand that CSS3 is a draft and as such the interface can be changed without warning. As a safeguard they apply a prefix to the drafted properties they want to support. These are known as:

Vendor-specific extensions

If you’ve ever seen anything like -moz-border-radius: 6px; you know what I mean. Vendor-specific extensions are a standardised and accepted (however occasionally non-validating) way of implementing future rules without fear of breaking anything. If you want to use CSS3 properties you will most likely have to include the same property with a prefix right after (excepting the few properties like opacity and border-radius). Your rules will look something like this:

.box {
	-webkit-box-shadow:2px 2px 5px gray;
	-moz-box-shadow:2px 2px 5px gray;
	box-shadow:2px 2px 5px gray;
	}

I know that hurts, but at least your repitition of code is localised.  And it is future-friendly – as browsers start supporting CSS3 your advanced styles will begin to appear!  A shadow on a header here, a rounded corner there, an opacity somewhere. Patience. 

You’ll notice there’s no -ie-border-radius property above. This is very sad. This leads us to our next restriction in using CSS3:

Don't force a design

Think about it - why must the design for a site look the same in IE as Chrome? What if they looked different? Someone who sees the site in IE is not going to know what they're missing. If a design feature can't be implemented in IE that's no reason not to implement it in WebKit, so long as it degrades gracefully.

For this to work you need to be close to the designers (or be the designer) and have laid back superiors - it can't really be done when you're dealing with long chains of design approval. Convince everyone that the site is going to look better in Chrome (happy face!), not worse in IE (ANGRY FACE).

Validating CSS3

By default, the W3C's CSS Validator does not recognise CSS3. You must specify that you are validating CSS3 by clicking "More Options" on the validator page and selecting the CSS level 3 profile.

That’s it! Go forth and play:

CSS3 Goodies you have got to check out:

Note on this site

This post is pretty much a press release for the recent redesign of FARMCode.org – CSS3 allowed me to code the site exactly how I wanted in Google Chrome, translate it across to Firefox in like 5 minutes and then conduct quick damage control for IE (no rounded corners there).

Categories: CSS