Articles in the ‘CSS3’ Category

CSS3 Object-fit Polyfill

TL;DR; I’ve made a polyfill for CSS3 Object-fit. Download it from Github here:

The need for object-fit

A month ago, I was looking into creating a responsive grid full of images for a client. The width of the columns would vary depending upon device, and the dimensions and aspect ratio of the provided images could not be guaranteed.

The issue for me is keeping the images looking great, without skewing the dimensions and distorting the results, but I also needed them to expand or shrink to fit the boxes that they had been provided with.

A skewed picture

Knowing CSS, the property background-size: cover|contain would do this perfectly (See this A List Apart article for lots more detail), but this is for background images, and semantically, the images in my grid are part of the content, so should not be background images.
Looking for an equivalent, I found Object-fit: part of the CSS3 Image Values and Replaced Content spec. Unfortunately, browser support for this is very poor; this is the current browser implementation of this property:

As you can see, as of September 2012, only Opera support this feature! Side note: there is one other browser (there has to be for this to be for the spec to reach candidate recommendation) which is the HP TouchPad, not very useful for the majority of users

This isn’t going to get anyone very far, given that over 90% of all browser usage doesn’t support this feature. So, whilst browsers catch up, we have to use a polyfill to re-create this functionality with JavaScript.

Object-fit polyfill

The polyfill is based on jquery-object-fit by Simon Schmid, to which I’ve made some improvements:

  • Added support for cover
  • Fixed the implementation for IE and Firefox
  • Added feature detection so it uses the native implementation where possible
  • Made it re-calculate on resizing the browser for responsive layouts
  • Added a more tests to the suite

The results

Object-Fit tests

Object-fit grid of images

A responsive grid of images with the correct aspect ratios

What you get is a simple polyfill for object-fit which follows the spec as closely as it can. There is one main difference:

  • In a native implementation the image size remains the same and the picture within the image changes its dimensions, revealing grey letterboxed content. In the poly fill, an extra div is created around the image to take its dimensions and then the image is resized within that to provide the effect.

The source code is on github so please contribute if you can. I’ll be keeping this up-to-date so follow me @steveworkman on Twitter for the latest updates.

My thanks to Chris Mills of Opera for his articles and helping to explain how on earth all this works, and to Tab Atkins and the CSS WG for spelling it out. Hopefully there will be some more work on this feature soon. You can track the status of its implementation in Gecko (Firefox) and Webkit (Chrome et al) on their bug trackers (see links).

Please, let me know what you think in the comments and on github.

CSS Bookshelf – now on github

My CSS bookshelf is now available on github as an easy download if you want one yourself. Given that the code is now 2 years old it’s showing its age somewhat, so I’ll give it a spruce up over the next few weeks. Things like:

  • Removing the jQuery dependency (as I know a lot more JS now)
  • Using a CSS pre-processor on the stylesheet
  • Adding CSS gradients for the spines of the books, because there’s no need for images for most of them

Take a look at the project and let me know what you think in the comments

Problems loading local fonts with font-family

I’m investigating a problem with loading locally installed fonts in Windows 7. It’s a weird one this, and it only seems to affect Firefox and IE9/10, or, those browsers that use DirectWrite.

The problem

Font rendering comparison

Font rendering comparison: clockwise Chrome 16, IE10pp2, IE8, Firefox Aurora 9

This image shows the beautiful Univers font in four different browsers. Each of them are rendering the following CSS:

#univers55, #univers55bold, #univers45, #univers45bold { font-size:3em;}
#univers55 { font-family:"Univers 55", serif; }
#univers55bold { font-family: "Univers 55", serif; font-weight:bold; }
#univers45 { font-family: "Univers 45 Light", serif; }
#univers45bold { font-family: "Univers 45 Light", serif; font-weight:bold; }

Now, Univers 45 is a light-weight font, an should be a good 10 points lighter than Univers 55, you can see this in Chrome and IE8 (top-left and bottom right). In Firefox and IE10, Univers 45 looks heavier than Univers 55, and the bold version actually appears to be the same size. That just isn’t right. So I called for reinforcements: step up Paul Rouget (Mozilla) and Martin Beeby (Microsoft).

Further investigation

I raised a bug against Firefox core with a test case on jsfiddle and got some good responses. Martin and Paul both asked:

@steveworkman @paulrouget could you include the font-face code in the fiddle for Univers 55 and Univers 45 Light

So, they thought it was something to do with the way I was including the font in the CSS. So, let’s put it in and see what happens:

Font-face rule comparison

Font rendering comparison with the font-face rule added

The rendering appears to have corrected itself. Univers 45 and 55 are now properly weighted in Chrome, IE10 and Firefox. So, what happened? Well, Jonathan Kew sheds a little light on the problem:

Note that the @font-face rules shown in your second image are incorrect (e.g. ‘src: “Univers 55″‘ is invalid; did you mean “src: local(‘Univers 55’)”?), and as a result you’re not getting Univers at all in some of those examples, you’re getting fallback to the default sans-serif font, probably Arial. Look at the shape of the “5”, for example.

Also note that under the DirectWrite model, font families are organized differently from the old GDI model. Family names like “Univers 45 Light” are not generally used; instead, all the faces belong to a single family, with distinct font-weight values. (But I haven’t examined the Univers family to see exactly how they’re organized.)

So, yes, a little stumble over the “local(‘font-name’);” issue, but otherwise it appears to be fine. The second part where he mentions that in Windows 7, font families are organised differently, and so may be under a different name intrigued me. So, I took a look:

Univers Font Families

Univers Font Families

Univers 45 Fonts

Univers 45 Fonts

Univers 55 Fonts

Univers 55 Fonts

So, this is where it goes a bit fuzzy. I can address the “Univers 45 Light” font directly through font-face, but I can’t access the “Univers 55 Normal” font, though I can access the whole font family by looking for “Univers 55”. That doesn’t feel right to me, and needs more investigation. Still, I can at least get it to render the font when using font-face. So, is that it? Bug closed?

Why can’t I just use font-family?

This is the question that I want answering, and Martin has kindly volunteered to look into. Loading a local font through font-family should work in exactly the same way as @font-face and src: local(); – but in Firefox and IE 9/10 it’s not.

So, web community, do you know why this doesn’t work? Can you make it work with the test case? Please help! Leave a comment, send me a tweet or update the test case and make it work!

UPDATE 1st November 2011:

 Jonathan Kew has responded again with some more words of wisdom for me:

The @font-face and non-@font-face cases there aren’t comparable. When you say

font-family: "Univers 55";

without the use of @font-face, you’re requesting that _font family_, which may have multiple faces with different weights. What you’ll get when you use font-weight:bold along with this depends which faces have been grouped under that family name – which may well differ between GDI and DirectWrite environments. And if there’s no “bold” face in the family, then the browser will artificially “embolden” the text. (You can tell exactly which font is really being displayed using the “font-info” add-on, btw.) I suspect you might get a true bolder face in one case and synthetic bold in the other, but that depends very much on the structure of the font families you’re using.

In the @font-face case, you’re defining your own font families (independently of how the OS or the font designer organized things), and your CSS only assigns them a single (normal-weight) face each, which means that when your styles ask for font-weight:bold, you should be getting synthetic emboldening rather than a real face with a heavier weight.

To see what faces are supposed to be available within each family, look in the Windows Fonts folder – IIRC, this should reflect the DirectWrite organization of the fonts. Do you see separate “Univers 45” and “Univers 55” families? What faces exist in each?

So, I looked back at the spec and re-engineered the @font-face CSS, and the non-font-face CSS. The non-font-face CSS was definitely wrong, so I updated that, but the @font-face CSS still wasn’t working. I looked at the font libraries as they are in Windows, and identified the following named structure:

  • Univers 45
  • Univers 45 Light
  • Univers 45 Light Oblique
  • Univers 55
    • Univers 55 Black
    • Univers 55 Normal
    • Univers 55 Oblique

    Given the advice Jonathan gave me, the correct font-family should be “Univers 45” and “Univers 55”, and the correct fonts for @font-face should be “Univers 45 Light” and “Univers 55 Normal”. That gave the following results in Firefox and IE10

    Font-face comparison IE10 and Firefox 9

    Firefox Aurora 9 (left) fails to find the font, IE10 pp2 (right) finds the font

    IE is finding the correct font, but Firefox isn’t and is falling back to the serif font. I used the font finder plugin to look at which fonts were being used on the page, and the answer surprised me. When loading the Univers 55 font-family, the normal weight font is titled “Univers 55 Roman”, instead of “Univers 55 Normal”, and the bold version is “Univers 75 Black”, instead of “Univers 55 Black”.

    So, I took a look at the system file properties for the font, and lo-and-behold, the detailed properties were different to the name of the font:

    Univers 55 detail

    The file name says "Normal", but the properties say "Roman"

    I quickly looked to see if Firefox was looking for the title property instead of the file name, and I was right. If you’ve got the Univers font you can see the jsFiddle test case for this, otherwise, the final result is below:

    Corrected Font-Face

    With the extra @font-face rule, Aurora renders correctly like IE10

    The @font-face code goes like this:

    @font-face {
    	font-family: MyUnivers55;
    	src: local('Univers 55 Roman'), local('Univers 55 Normal');
    @font-face {
    	font-family: MyUnivers55;
    	src: local('Univers 75 Black'), local('Univers 55 Black');
    @font-face {
    	font-family: MyUnivers45;
    	src: local('Univers 45 Light');

    It looks to me like IE and Firefox use different properties to identify fonts under Windows 7: IE looks at the name in the file system and Firefox looks at the Title attribute of the file.

    Amazingly, it looks like the spec doesn’t care which one is right, and advises you to include both as different platforms use different naming conventions. What surprises me is that two browsers look for a different name on the same platform, as this could cause naming clashes; the Univers 55 Black is titled Univers 75 Black – so if there was also a Univers 75 Black titled Univers 85 Black, browsers are going to retrieve the wrong font.

    So, Microsoft, Mozilla, please sort it out 🙂 Who is right?