Skip to content
This repository

Reassess IR techniques #1149

Closed
necolas opened this Issue July 29, 2012 · 23 comments

9 participants

Nicolas Gallagher Marcus Sergio Cerrutti Matt Kantor brianblakely Max West Philip Klauzinski Miloš Gavrilović David Murdoch
Nicolas Gallagher
Owner

Various issues need to be considered and the pros/cons of techniques reassessed:

#1108
#1125
#1144

Nicolas Gallagher
Owner

​I've been playing around with another IR technique. It's a hybrid approach; not sure if it's been thought of before. Below is its simplest form (without any extra cruft that you might need for button or hiding child br in IE 6/7):

.ir {
    overflow: hidden;
    *text-indent: -999em;
}

.ir:before {
    content: "";
    display: block;
    width: 0;
    height: 100%;
}

Demo / Test case

The pseudo-element forces the content downwards without covering up the background of the element. Then the overflow is hidden. For IE 6/7, we fall back to the text-indent method.

From what I've learnt so far...

Pros:

  • Works in IE6+ (although better in IE8+).
  • Replaces any content in IE8+, including inner HTML.
  • Nothing new for people to learn. Works just like all "traditional" IR techniques (unlike NIR, which needs you to add the image using content and use margins for sprite positioning).
  • Doesn't draw an out-of-element box any greater than is needed in modern browsers (so that iPad1 issue Scott was trying to work around seems like to be avoided). You can even mix in something like font: 10px/1 a; to reduce the size of the "off-screen" box, if you really need to.
  • Doesn't have any potential SEO problems from font-size:0.
  • Doesn't care about any minimum font-size that a browser might have.
  • Doesn't have any potential failed-IR problems from inherited styles, like text being positioned within the element's visible box (i.e., if you use other properties like text-stroke).
  • Doesn't appear to require !important anywhere.

Cons:

  • Doesn't work when images are off or fail to load (same as every other IR technique apart from NIR).
  • Needs to nuke padding, otherwise bottom-padding can result in some text still showing. Alternatively, defend against padding by adding > 100% height.
  • Still suffers from the inline-block bug in IE 6/7 due to the text-indent fallback for those browsers.
  • Won't work on input elements (does anyone still use these with IR? they shouldn't).
  • Potential for some differences between IE 6/7 and modern browsers...but this is already the case with both the text-indent and "font crushing" methods.
  • If there is a non-rare, non-IE browser out there that doesn't support pseudo-elements, then it's not going to work.

I could do with some people to help test this out a bit more (across different browsers, inc. mobile) and find any additional problems. Also, opinions about this.

cc @h5bp/html5-boilerplate @scottkellum @brendanf @chriseppstein @scottjehl

Marcus

Looks identical in Google Chrome Canary (Windows), Android 4.1.1 browser, and Chrome for Android 4.x

Sergio Cerrutti

Why do you think it's better than this one?

.hide-text {
  text-indent: 100%;
  white-space: nowrap;
  overflow: hidden;
}

I prefer to avoid pseudo-elements for tricks (just for visual things), it's a fact that they are very slow when browsers renders them and parse the selector.

Nicolas Gallagher
Owner

Why do you think it's better than this one?

Because that method is pretty buggy

I prefer to avoid pseudo-elements for tricks (just for visual things), it's a fact that they are very slow when browsers renders them and parse the selector.

Where is the data to back that up? Pseudo-elements are already used everywhere that the clearfix hack is used. And rendering a pseudo-element isn't going to be as slow as loading an image. It seems like an non-issue.

Sergio Cerrutti

There is no link to show you this thing (sorry), but I had time to test them with Chrome's CSS profiler tool creating a list of a lot of elements with a before (doing a lot of visual things) and another HTML replacing before with span nodes with the same behavior. Chrome's profiler tool said both ::after and ::before pseudo-elements are 5-10% slower (while parsing) than a normal HTML node. Of course I don't know why but maybe you can give it a try.

Anyway, I have test it just in Chrome so it could differ in other browsers.

So, having a trick without pseudo-element it's faster than with it, more if we use it in a large website with a lot of IRs.

One more thing, why the way I said is buggy, I never had problems with it since I use it.

Nicolas Gallagher
Owner

I'm not going to lose any sleep over 2ms + 10%.

I never had problems with it since I use it.

I did a bunch of tests of it last time we looked at IR in HTML5 Boilerplate, it has plenty of issues and edge-case problems that make it unsuitable to roll into this project: aa0396e

Matt Kantor

Another con (probably a small one):

  • Makes the ::before pseudo-element unusable for other purposes.
brianblakely

@mkantor I thought about that too, but I think you likely won't need it for IR elements, or can simply use ::after.

Personally, I'm favoring the font-crush, unless someone can authoritatively tell me that it will kill SEO. For the time being, losing IE7 support again is too big.

Nicolas Gallagher
Owner

losing IE7 support again is too big

IE 6/7 are both supported by this technique as it includes the same old negative text-indent method for them. The font-crushing method actually leaves a bit of residue in IE6/7.

brianblakely

@necolas Ah, I meant in the case of inline-block'd elements, which was major thorn in my side until your excellent font-crush solution.

Nicolas Gallagher
Owner

I meant in the case of inline-block'd elements

Yeah, that kinda sucks if you need IE 6/7 support with inline blocks. Hmmm

Max West

Not sure if this is what you're looking for. The code above doesn't hide text for me, but this does:

.ir {    
    *text-indent: -999em;
    background-image: url('https://www.google.de/logos/2012/opening_ceremony-2012-sr.png');
    width: 114px;     
    height: 41px;
}

.ir:before {     
    content: "";
    margin-left: -999em;
}

Here's the Fiddle: http://jsfiddle.net/maxw3st/bLfUK/
I only tested this in Firefox and Chrome. Looked the same in both.

Philip Klauzinski

I know this isn't for mobile, but FYI.. using negative ems to hide text doesn't work on Android ICS. I had to use negative px values for it to actually hide, e.g. -999px (Droid Razr ICS).

Nicolas Gallagher
Owner

The code above doesn't hide text for me, but this does.

How does it not hide text? Did you open the fiddle? Your example isn't much different to just using negative text-indent. It has pretty much all the same problems.

I know this isn't for mobile...

It is for mobile. But the negative text-indent is only for IE 6/7

Sergio Cerrutti

That performance is importante in large websites, but you're right, it's nothing in real cases.
I've tested in my Android 2.3.6 Browser and it's perfect as it's in Chrome21, Canary23, Firefox15, Opera12 and Safari6, all of them in a Mac.

Thank you necolas!

Sergio Cerrutti

I've used this for text replacement (which finally is the same) and the behavior is perfect:

h2 {
  background-color: rgb(245, 245, 245);
  height: 48px;
  border-bottom: 1px solid rgb(222, 222, 222);
  position: relative;
  overflow: hidden;
}
  h2:after {
    content: "Elige un método de pago";
    position: absolute; top: 0; left: 24px;
    font-size: 18px; font-weight: bold; line-height: 48px;
  }
  h2:before { content: ""; display: block; width: 0; height: 100%; }
Nicolas Gallagher necolas closed this issue from a commit August 21, 2012
Nicolas Gallagher New image replacement approach
This approach uses a pseudo-element to force the element's content
downwards without covering the background of the element. The overflow
is hidden. For IE 6/7, fallback to the cruder `text-indent` method.

Known advantages:

* Works in IE6+ (although better in IE8+).

* Replaces any content in IE8+, including inner HTML.

* Nothing new for people to learn. Works just like all "traditional" IR
  techniques (unlike NIR, which needs you to add the image using a
  pseudo-element's `content` and relies margins for sprite positioning).

* Doesn't draw a large out-of-element box in modern browsers. You can
  even mix in something like `font: 10px/1 a` to reduce ce the size of
  the "off-screen" box, if you really need to.

* Doesn't have any potential SEO problems from `font-size:0`.

* Doesn't care about any minimum font-size that a browser might have.

* Doesn't have any potential failed-IR problems from inherited styles,
  like text being positioned within the element's visible box (i.e., if
  you use other properties like `text-stroke`).

Known issues:

* Doesn't work when images are off or fail to load (same as every other
  IR technique apart from NIR).

* If the IR'ed element has bottom-padding, then either it needs to be
  removed or the height of the pseudo-element needs to be bumped up
  (e.g., set to 200%).

* Doesn't avoid the `inline-block` bug in IE 6/7 due to the text-indent
  fallback for those browsers.

* Doesn't work on input elements (but they shouldn't be the subject of
  IR anyway).

* There is the potential for some final-result differences between
  IE 6/7 and modern browsers, but this is already the case with other IR
  techniques.

Fix gh-1149
adecc5d
Nicolas Gallagher necolas closed this in adecc5d August 21, 2012
Miloš Gavrilović

@necolas hey man, do you think this is bug or am I using .ir class wrong?

.ir class is not working with input[type=submit] as seen on this fiddle:

http://jsfiddle.net/8BSL3/

David Murdoch

adecc5d

Known issues:
...

  • Doesn't work on input elements (but they shouldn't be the subject of IR anyway). ...

Use a button: http://jsfiddle.net/musicisair/8BSL3/1/

Miloš Gavrilović

Yup, I knew there is something I was missing here... :) Thanks!

Miloš Gavrilović

@davidmurdoch Hmmm it seems this is not working in firefox? O_O

http://i.imgur.com/BwXzl.png

Nicolas Gallagher
Owner

You havent set any dimensions on the element that is receiving IR

Miloš Gavrilović

Look again in css field: http://jsfiddle.net/musicisair/8BSL3/1/

a, button {
    display: block;
    width: 128px;
    height: 128px;
    background-image: url('http://2.bp.blogspot.com/_6rROSHI_zZ4/SfY4yPxlHFI/AAAAAAAABpY/0iPyrZOreHc/S220/cat_avatar_0065_www.free-avatars.com.jpg');
}
Nicolas Gallagher
Owner

Oh yeah, I see. You'll have to use an element within button then, and file a bug with the Firefox team :). Thanks.

Logan Franken loganfranken referenced this issue in ucla/WebBlocks October 08, 2012
Closed

Image Replacement #60

Nicolas Gallagher necolas referenced this issue in csswizardry/inuit.css October 24, 2012
Closed

Sprite not working in IE7 #46

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.