Posts Tagged ‘CSS’

Responsive Web Design for Mobile

Friday, July 2nd, 2010

Respon­sive web design is unde­ni­ably the new hot­ness in CSS. If you’re not famil­iar with the tech­nique, go and read Ethan Marcotte’s amaz­ing arti­cle over on A List Apart. What Mar­cotte has cre­ated is a way to cre­ate one design that adapts to dif­fer­ent res­o­lu­tions using media queries.

There are count­less advan­tages to build­ing sites in this way, but arguably the most com­pelling rea­son is the abil­ity to share one lay­out across both desk­top and mobile browsers. How­ever, if you’re new to mobile devel­op­ment there are a cou­ple of tricks you’ll need to use in order to make this work. It wasn’t really in the scope of Marcotte’s arti­cle to cover the mobile-specific aspects of his tech­nique, so I fig­ured a quick post was in order to fill in the gaps.

The exam­ple site we’ll be look­ing at is a hypo­thet­i­cal site for food­ies called Fork’d. When you look at it in a nor­mal sized desk­top browser, It’s got a ver­ti­cal nav­i­ga­tion list and three columns of con­tent. If you resize the win­dow to be a fair bit nar­rower, you’ll see that the floats dis­ap­pear, and the nav­i­ga­tion as well as all of the con­tent is lined up in a sin­gle col­umn. This is the lay­out we want our mobile users to see. How­ever, what they’re actu­ally going to see is this:

the site renders very small

For­tu­nately, we just need a tiny sprin­kling of pixie dust to make this work the way we expect it to. We’ll just add this meta tag to our page:


<meta name="viewport" content="width=device-width, initial-scale=1.0">

(For way more info on view­ports, check out Apple’s doc­u­men­ta­tion on the sub­ject.)

Once we put that in place, the Fork’d site ren­ders like this:

the site renders at the correct resolution

Per­fect! We now have one lay­out that works across dif­fer­ent desk­top screen res­o­lu­tions as well as (high-end) mobile devices, and the only extra trick we had to employ was to add a sin­gle meta tag.

Ugly font-variant bug

Thursday, April 22nd, 2010

Here’s an annoy­ing lit­tle bug that man­i­fests when you try to set a CSS font-variant prop­erty (say, small-caps) with a font that doesn’t pro­vide the requested vari­ant. For instance, here is some text in League Gothic, pulled in via @font-face:

Sample of league gothic text, rendered normally

League Gothic doesn’t have its own small caps vari­ant. So what hap­pens when you tell the browser to give you one any­way? Here it is with font-variant: small-caps applied as ren­dered in Firefox:

Sample of league gothic small caps, rendered correctly in Firefox

So far, so good. But here’s what you get when you add small caps to League Gothic in Webkit:

Sample of league gothic small caps, which falls back to the default font in Webkit

Whoops! Webkit-based browsers (I tested this in Safari, Webkit Nightly, and Chrome for OSX), when they don’t find the spec­i­fied vari­ant in the font itself, just go to the next font in the stack. In this case, it’s the browser’s default font.

So which behav­ior is cor­rect? The CSS2 spec essen­tially left it up to imple­men­tors to decide whether or not they would dynam­i­cally scale the font to imple­ment small caps. CSS3 removes the ambiguity:

If a gen­uine small-caps font is not avail­able, user agents should sim­u­late a small-caps font, for exam­ple by tak­ing a nor­mal font and replac­ing the low­er­case let­ters by scaled upper­case char­ac­ters. (CSS fonts mod­ule level 3)

Although a typo­graphic purist might take issue with this behav­ior (Bringhurst rails against the prac­tice of “rolling your own” vari­ants by dynam­i­cally scal­ing the exist­ing face), this is what the spec says browsers are sup­posed to do. And in fact, this is what Fire­fox does. Webkit, on the other hand, checks each font in the stack in order until it finds one that sup­plies the desired vari­ant. As in the exam­ple above, if there’s noth­ing else in the stack, it will fall back on the browser’s default font.

Unfor­tu­nately, there aren’t really any workarounds for this bug. But it should serve to remind you yet again that it’s super-important to put a good deal of thought into your font stack. Always try to build a stack where all of the fonts are as sim­i­lar as pos­si­ble, so when some­thing like this hap­pens, your design doesn’t break too badly.

For ref­er­ence, or if you’d like to see how your browser of choice han­dles these cases, here are some test cases together on a sep­a­rate page.

Font-face Support Table

Friday, December 4th, 2009

I’ve been sit­ting on this for a lit­tle while, so I thought I’d just go ahead and pub­lish it. For an in-depth expla­na­tion of how I got these results, check out this post. In a nut­shell, it shows that all of the main desk­top browsers sup­port some kind of @font-face for­mat, so as long as you use some­thing like the Bul­let­proof font-face syn­tax, your fonts will ren­der in all of the the major browsers (e.g. those with > 3% mar­ket share). On mobile, it’s still a Mobile Safari-only party.

Web­font for­mat sup­port by browser
Embed­ded Open Type (.eot) True­Type (.ttf) Open­Type (otf) Web Open Font For­mat (.woff) SVG (.svg)
Mobile Browsers1
1 I haven’t had a chance to test Mozilla’s portable offerings
Mobile IE (≤ WinMo 6.5) No No No No No
Opera Mini (≤ v4.2) No No No No No
Opera Mobile (9.7 Beta WinMo) No No No No No
Palm WebOS No No No No No
Mobile Safari (3.1) No No No No Yes!
Android (≥ 2.2 SDK) No Yes Yes No No
Desk­top Browsers (Incom­plete. I’ll be fill­ing this in more over time)
IE (≥ 5.5) Yes No No No No
Fire­fox No Yes (≥ 3.5) Yes (≥ 3.5) Yes (≥ 3.6) No
Safari No Yes (≥ 3.1) Yes (≥ 3.1) No Yes (≥ 3.1)
Opera No Yes Yes No Yes
Chrome No No No No Yes (≥ 3.0)

Shiny CSS-only iPhone Buttons

Friday, November 27th, 2009

Just a quickie: I came up with these CSS-only iPhone-style but­tons as part of a big­ger pet project I’m work­ing on. They make heavy use of -webkit-gradient instead of the typ­i­cal PNG-based solu­tion you typ­i­cally see out there, such as in iUI.

The CSS is here, and be sure to check out the exam­ple but­tons.

The one thing I’m not crazy about when you use these styles on an actual device is that the nor­mal :active state doesn’t get trig­gered, so I kind of had to half-ass it with a :hover so you’d see the “active” style as the but­ton sheet eases out (if you’ve wired the tran­si­tions together).

Enjoy, and please let me know if you find them useful.

Webfonts and Mobile Devices

Tuesday, November 10th, 2009

If you pay even a lit­tle atten­tion to emerg­ing trends in Web Stan­dards, you’re no doubt famil­iar with the explo­sion in inter­est in the CSS @font-face prop­erty. This prop­erty goes back to CSS2, and has been sup­ported in IE as far back as 5.5, but @font-face sup­port is being added at a rapid pace to other browsers, hence the recent surge of interest.

As some­one who spends his days devel­op­ing for mobile plat­forms, I wanted to check on how @font-face sup­port was pro­gress­ing in mobile browsers. Read on to see what I found out.

Method­ol­ogy

I put together a test page I used to check the extent of @font-face support.

I made test ele­ments and sep­a­rate font fam­i­lies for each font for­mat being tested (e.g. there’s a font fam­ily called “Chunk­Five SVG” that will only be applied to the span#SVG test ele­ment. View source on the sam­ple page for more details). I checked for @font-face sup­port with three cri­te­ria (two automated):

  1. Ask each test ele­ment what font-family it thinks it is being ren­dered with. This is done via the window.getComputedStyle() method (and why I’m stick­ing with test­ing W3C com­pli­ant browsers at the moment). If all goes well, the return value should be some vari­ant of ChunkFive.
  2. Check to see if the ren­dered text is wider than text ren­dered in the browser’s default font. For the test to pass, it has to be wider, since there are font size bugs in Mobile Safari (see below).
  3. Eye­ball it. In some cases, the cri­te­ria above aren’t met, so the @font-face imple­men­ta­tion is incor­rect, but it’s close enough to be saved with some extra TLC.

I also included a test case based on Paul Irish’s Bul­let­proof @font-face syn­tax as a bit of a san­ity check and for the sake of hav­ing a less con­trived exam­ple. Lastly, I threw in sam­ples of Cufon and sIFR text, just for comparison.

All that said, here’s what I came up with.

Results

Mobile Safari 3.0

Sup­port for @font-face in Mobile Safari is cur­rently bro­ken in sev­eral frus­trat­ing ways:

  1. Cer­tain for­mats (e.g. TTF & OTF), when applied, falsely report that they have been suc­cess­fully applied. That is, if you check the value of font-family from get­Com­put­ed­Style() on that ele­ment, it will return the @font-face value, even though it doesn’t ren­der as such. (Update 11/13: As Paul Irish cor­rectly pointed out in the com­ments to this post, Opera is actu­ally the only browser that returns the font that’s actu­ally used when getComputedStyle() is called.)
  2. What’s worse, is that when this sit­u­a­tion occurs, if no fall­back font-family is spec­i­fied, the text will ren­der with the browser’s default font-family (as you’d expect), but it does so at less than the default font size. For­tu­nately, if you spec­ify a fall­back value in the font-family dec­la­ra­tion, it will ren­der the fall­back type­face at the cor­rect size, so always remem­ber to pick a degra­da­tion path for your fonts.
  3. Another issue with text size arises if you use the SVG for­mat to get around the lack of sup­port for other for­mats on the iPhone. While you can indeed use SVG fonts in your font-face rules on the iPhone, text ren­dered in SVG fonts will ren­der at smaller than expected sizes. So if you opt for this strat­egy, just plan for this con­se­quence, and cor­rect the font sizes accord­ingly. Desk­top browsers that sup­port SVG fonts (Safari & Chrome) don’t exhibit this bug, so you need to tar­get this font-size fix to mobile browsers. You can eas­ily han­dle this case with a @media query in your stylesheet. Users of the Bul­let­proof Syn­tax will see this bug, since it will fall through to SVG on Mobile Safari.
    Mobile Safari renders SVG text too smallSVG fonts on Mobile Safari ren­der too small out of the box.
  4. Another (pos­si­bly more aca­d­e­mic) issue is that call­ing getComputedStyle() on text ren­dered with an SVG font will not return the font-family value in your @font-face dec­la­ra­tion, even though it ren­ders with that font fam­ily. This could prove trou­ble­some if you’re using Javascript to test the suc­cess of your font rendering.

So if you need to use @font-face on Mobile Safari today, you should be sure to include an SVG ver­sion in your @font-face dec­la­ra­tion, and you should patch any text size bugs with a @media query. (If you’re not famil­iar with @media queries, you should read up on them.)

Inci­den­tally, Opera 10 on the desk­top also shows a slight vari­a­tion in font-size when using SVG fonts as well. How­ever, since it sup­ports True­Type and Open­Type for­mats, this shouldn’t cause any par­tic­u­lar issues if you’re using the bul­let­proof syn­tax (that’s why it’s bul­let­proof, yo).

Android 2.0 SDK

Short and not so sweet: There is no sup­port in the Android 2.0 SDK for any web­font for­mat. If you’re tar­get­ing Android, use Cufon.

Palm WebOS

Like Android, there is cur­rently no sup­port what­so­ever for @font-face in WebOS. Addi­tion­ally, in my (not at all exten­sive) tests, Cufon didn’t even appear to work at all (as in no text was rendered).

Sum­mary

In short, if you want your mobile site to join the Nice Web Type band­wagon, you have a lit­tle more work to do than for your desk­top site. Of all of the mod­ern WebKit-based mobile browsers, only Mobile Safari pro­vides any kind of @font-face sup­port. And even that sup­port is buggy and incom­plete. How­ever, if you are aware of these lim­i­ta­tions ahead of time (which you ought to be by this point in the post), you have a cou­ple of tricks in your back pocket to keep things run­ning smoothly.

What’s Next?

In the next lit­tle while, I’ll extend these tests to cover IE on WinMo and also do a sim­i­lar write-up for @font-face sup­port in desk­top browsers and tab­u­late all of the results in a lit­tle more for­mal manner.

Update: In case any­one wants to take a look under the hood of these tests with­out jump­ing through hoops in Fire­bug or View Source, the test code is up on Github.

The Rounded Corners of Tomorrow… Today!

Thursday, October 2nd, 2008

Hey, you know what can be a real pain in the tail? CSS rounded cor­ners. Of course there are battle-tested, work­horse solu­tions out there, like slid­ing doors, or a hand­ful of Javascript-based alter­na­tives. But rounded cor­ners are such a com­mon ele­ment of web design and seem like a nat­ural exten­sion of the designer’s exist­ing toolkit that it only makes sense that there should be a way to imple­ment them with pure CSS. The good news is that border-radius is indeed com­ing in CSS3. The bet­ter news is that you can start using it today, as long as you’re only tar­get­ing Gecko & Webkit. Before we get to that though, let’s look at the way it’s sup­posed to work accord­ing to the spec.

As you might expect, the border-radius prop­erty is used a lot like border. That is, you can spec­ify one value for each cor­ner (border-radius: 10px;), one value per cor­ner (border-radius: 1px 2px 3px 4px;), or val­ues for oppo­site cor­ners (border-radius: 5px 10px). It actu­ally gets more com­pli­cated, since in addi­tion to describ­ing cor­ners with one radius (i.e. those with semi-circular curves), you can make ellip­ti­cally rounded cor­ners by nam­ing two radii. For more detail on this, take a look at the draft spec. Lastly, you can use a prop­erty for each cor­ner, border-top-left-radius: 2em;, etc. So, assum­ing there aren’t any major changes in the spec, expect this to be what gets imple­mented as part of CSS3, and what you’ll ulti­mately using in your code.

But what about now? Here? Today? It hap­pens that two of the standards-aware, forward-thinking ren­der­ing engines have devel­oped pro­pri­etary exten­sions to CSS that should stand in for border-radius until cer­tain ambi­gu­i­ties in the spec can be resolved, and the prop­erty is implented accord­ing to the stan­dard. So if you want to use border-radius in your code today, you’ll have to use both the Mozilla– and Webkit-specific CSS prop­er­ties. For­tu­nately, both of the pro­pri­etary exten­sions work in the cur­rent major releases of their respec­tive browsers.

If you’re mak­ing a box with four cor­ners of the same radius, the syn­tax is the same in Mozilla and Webkit:

-moz-border-radius: 10px; /* 4 corners of radius = 4px*/
-webkit-border-radius: 10px; /* Same as Mozilla */

To spec­ify dif­fer­ent radii for each cor­ner, things diverge somewhat.

/* Mozilla: */
-moz-border-radius: 1px 2px 3px 4px;
/* Webkit:
    (The four declarations below amount to the
    same thing as the single rule above) */
-webkit-border-top-left-radius: 1px;
-webkit-border-top-right-radius: 2px;
-webkit-border-bottom-right-radius: 3px;
-webkit-border-bottom-left-radius: 4px;

And that’s the guts of it. So to make a tabbed nav­i­ga­tion list, you would use a dec­la­ra­tion along the lines of the fol­low­ing (and see the below code in action.):

li {
  border: 1px solid #587402;
  border-bottom: none;
  border-radius: 0 10px 0 10px;
  -moz-border-radius: 10px 10px 0 0;
  -webkit-border-top-left-radius: 10px;
  -webkit-border-top-right-radius: 10px;
  list-style-type: none;
  float: left;
  padding: .5em 1em 0 1em;
}

There you have it. But there are just a cou­ple of other things I want to point out. If the con­tainer you’re round­ing the cor­ners of has only text con­tent and a back­ground in it, the back­ground will clip to the rounded cor­ners. And indeed, accord­ing to the spec, any the con­tents of a block-level ele­ment on which a border-radius is set should clip do the same as long as you set overflow: hidden on those con­tents. How­ever, the imple­men­ta­tions just aren’t there yet. Instead, with any­thing over and above plain HTML text (for instance, an img or iframe) inside such a con­tainer, the square cor­ners will peek out­side of the rounded con­tainer. (Exam­ple)

One solu­tion would be to make the bor­der thick enough that the cor­ners of the inner ele­ment can’t poke through the outer bor­der (like so). Though inel­e­gant, this will work just fine if you don’t need every­thing to round nicely. And this method should suf­fice for what­ever kind of con­tent you’re try­ing to stuff into your nicely rounded box.

How­ever, if it’s an image you’re putting in the box and you need the inner cor­ners to be rounded as well as the outer cor­ners, then the only answer (for now) is to set the image as a back­ground. Still, if the lan­guage of the spec is any indi­ca­tion, it won’t always be this way.

For the poor soul who is try­ing to squeeze iframe con­tent into a rounded cor­ner box, you’re essen­tially out of luck at the moment. You can cer­tainly use the thick bor­der method I described above, but short of that, you’ll have to look to the bleed­ing edge. That is to say, you’ll need some­thing which isn’t yet in any production-quality browser, but that is cur­rently in the Webkit nightlies. I speak of the arcane meth­ods of -webkit-mask-image. This prop­erty can take a png or an svg as its url, and pretty much any­thing you apply it to will play nice and clip to the shape of the image. See for your­self. Still, this last bit is obvi­ously not any­thing any­body will be using in pro­duc­tion code for some time to come.

After read­ing all of this, if noth­ing else, I do hope that you’ve come away with a bet­ter idea of some of the great things that the CSS work­ing group has in store for you, the devel­oper. But even moreso, hope­fully there’s some­thing in all of this mess that you’ll be able to put to use today.

What I’m Reading: 3/24

Monday, March 24th, 2008
  1. Nine Tech­niques for CSS Image Replace­ment: If you spend any time at all play­ing with CSS, you know that there are a full bajil­lion tech­niques for replac­ing text with an image. It’s a lot to remem­ber, and I’ll fess up that I tend to use what­ever one I hap­pened to have read about most recently rather than tak­ing a con­sid­ered approach to which of them might be the best solu­tion for a given sit­u­a­tion. No more! The above-linked post does a great job of run­ning through the pros and cons of the 9 (9!) major tech­niques, and from now on you (mean­ing “I”) no longer have any excuse to not use the best, seman­tic, most acces­si­ble one at every opportunity.
  2. Drugs, Bugs, and IE8: A pre­dictably good read from Eric Meyer, but I link to it mainly to have an excuse to echo the fol­low­ing point: There are a lot of beta browsers out there right now (one less, now that Safari 3 has shipped). If you’re test­ing your sites in them and some­thing ren­ders in any way other than what you were expect­ing, sub­mit a bug report. Don’t change your code.
  3. Opti­miz­ing Page Load­ing in the Web Browser: For the browser builders, net­work latency is at least as big a prob­lem as con­nec­tion speed.
  4. A Japan­ese RPG Primer: The Essen­tial 20: Last week, Gama­su­tra pub­lished this list of the best of the best in Japan­ese RPGs through­out the ages. It’s a top-20, so it’s not exhaus­tive, but it’s sure as hell exhausting–i’ve been chip­ping away at this beastie since last week. Any­way, if you’re at all into JRPGs, it’s a really fun read. It’s also neat to see some old favorites put into con­text along­side some sem­i­nal games that you may never have been exposed to.