Best css questions in September 2011

Why are dashes preferred for CSS selectors / HTML attributes?

20 votes

In the past I've always used underscores for defining class and id attributes in HTML. Over the last few years I changed over to dashes, mostly to align myself with the trend in the community, not necessarily because it made sense to me.

I've always thought dashes have more drawbacks, and I don't see the benefits:

Code completion & Editing

Most editors treat dashes as word separators, so I can't tab through to the symbol I want. Say the class is "featured-product", I have to auto-complete "featured", enter a hyphen, and complete "product".

With underscores "featured_product" is treated as one word, so it can be filled in one step.

The same applies to navigating through the document. Jumping by words or double-clicking on class names is broken by hyphens.

(More generally, I think of classes and ids as tokens, so it doesn't make sense to me that a token should be so easily splittable on hyphens.)

Ambiguity with arithmetic operator

Using dashes breaks object-property access to form elements in JavaScript. This is only possible with underscores:

form.first_name.value='Stormageddon';

(Admittedly I don't access form elements this way myself, but when deciding on dashes vs underscores as a universal rule, consider that someone might.)

Languages like Sass (especially throughout the Compass framework) have settled on dashes as a standard, even for variable names. They originally used underscores in the beginning too. The fact that this is parsed differently strikes me as odd:

$list-item-10
$list-item - 10

Inconsistency with variable naming across languages

Back in the day, I used to write underscored_names for variables in PHP, ruby, HTML/CSS, and JavaScript. This was convenient and consistent, but again in order to "fit in" I now use:

  • dash-case in HTML/CSS
  • camelCase in JavaScript
  • underscore_case in PHP and ruby

This doesn't really bother me too much, but I wonder why these became so misaligned, seemingly on purpose. At least with underscores it was possible to maintain consistency:

var featured_product = $('#featured_product'); // instead of
var featuredProduct = $('#featured-product');

The differences create situations where we have to translate strings unnecessarily, along with the potential for bugs.

So I ask: Why did the community almost universally settle on dashes, and are there any reasons that outweigh underscores?

There is a related question from back around the time this started, but I'm of the opinion that it's not (or shouldn't have been) just a matter of taste. I'd like to understand why we all settled on this convention if it really was just a matter of taste.

Code completion

Whether dash is interpreted as punctuation or as an opaque identifier depends on the editor of choice, I guess. However, as a personal preference, I favor being able to tab between each word in a CSS file and would find it annoying if they were separated with underscore and there were no stops.

Also, using hyphens allows you to take advantage of the |= attribute selector, which selects any element containing the text, optionally followed by a dash:

span[class|="em"] { font-style: italic; }

This would make the following HTML elements have italic font-style:

<span class="em">I'm italic</span>
<span class="em-strong">I'm italic too</span>

Ambiguity with arithmetic operator

I'd say that access to HTML elements via dot notation in JavaScript is a bug rather than a feature. It's a terrible construct from the early days of terrible JavaScript implementations and isn't really a great practice. For most of the stuff you do with JavaScript these days, you'd want to use CSS Selectors for fetching elements from the DOM anyway, which makes the whole dot notation rather useless. Which one would you prefer?

var firstName = $('#first-name');
var firstName = document.querySelector('#first-name');
var firstName = document.forms[0].first_name;

I find the two first options much more preferable, especially since '#first-name' can be replaced with a JavaScript variable and built dynamically. I also find them more pleasant on the eyes.

The fact that Sass enables arithmetic in its extensions to CSS doesn't really apply to CSS itself, but I do understand (and embrace) the fact that Sass follows the language style of CSS (except for the $ prefix of variables, which of course should have been @). If Sass documents are to look and feel like CSS documents, they need to follow the same style as CSS, which uses dash as a delimiter. In CSS3, arithmetic is limited to the calc function, which goes to show that in CSS itself, this isn't an issue.

Inconsistency with variable naming across languages

All languages, being markup languages, programming languages, styling languages or scripting languages, have their own style. You will find this within sub-languages of language groups like XML, where e.g. XSLT uses lower-case with hyphen delimiters and XML Schema uses camel-casing.

In general, you will find that adopting the style that feels and looks most "native" to the language you're writing in is better than trying to shoe-horn your own style into every different language. Since you can't avoid having to use native libraries and language constructs, your style will be "polluted" by the native style whether you like it or not, so it's pretty much futile to even try.

My advice is to not find a favorite style across languages, but instead make yourself at home within each language and learn to love all of its quirks. One of CSS' quirks is that keywords and identifiers are written in lowercase and separated by hyphens. Personally, I find this very visually appealing and think it fits in with the all-lowercase (although no-hyphen) HTML.

How to properly vertically align an image

17 votes

How to properly vertical-align this image in the .frame element:

<div class="frame" style="height: 25px;">
    <img src="http://jsfiddle.net/img/logo.png" />
</div>

.frame's height is fixed and image's height is unknown. I can add new elements in .frame if that's the only solution. I'm trying to do this on IE≥7, Webkit, Gecko.

See the jsfiddle here: http://jsfiddle.net/4RPFa/61/

The only (and the best cross-browser) way as I know is to use an inline-block helper with height: 100% and vertical-align: middle on both elements.

So there is a solution: http://jsfiddle.net/kizu/4RPFa/74/

Or, if you don't want to have an extra element in modern browsers and don't mind using IE expressions, you can use a pseudo-element and add it to IE using a convenient Expression, that runs only once per element, so there won't be any perfomance issues:

The solution with :before and expression() for IE: http://jsfiddle.net/kizu/4RPFa/76/


How it works:

  1. When you have two inline-block elements near each other, you can align each to other's side, so with vertical-align: middle you'll get something like this:

    Two aligned blocks

  2. When you have a block with fixed height (in px, em or other absolute unit), you can set the height of inner blocks in %.

  3. So, adding one inline-block with height: 100% in a block with fixed height would align another inline-block element in it (<img/> in your case) vertically near it.

JavaScript to avoid widows

13 votes

A common problem when working with typography in HTML/CSS is something we call "horunge" in Swedish ("widow" in english).

What it is:

Let's say you have a box with a width of 200px and with the text "I love typograpy very much". Now the text breaks and becomes:

I love typography very
much

As a designer I don't want a word bastard (single word / row). If this was a document/PDF etc. I would break the word before very and look like this:

I love typography
very much

which looks much better.

Can I solve this with a CSS rule or with a javascript? The rule should be to never let a word stand empty on a row.

I know it can be solved by adding a <br /> but that's not a solution that works with dynamic widths, feed content, different translations, browser font rendering issues etc.

Update (solution) I solved my problem with this jquery plugin: http://matthewlein.com/widowfix/

There's a whole article on it here:

http://www.learningjquery.com/2008/07/three-quick-ways-to-avoid-widows

Invert/change logo on scroll

12 votes

An article over on askthecssguy.com shows how to change/invert an image on scroll using fixed backgrounds: http://askthecssguy.com/articles/mike-asks-the-css-guy-about-a-scrolling-trick-with-background-images/

My goal takes this concept further by having the image float over other elements (in this case images).

You can see the result here: http://playground.iamkeir.com/invert-logo/v2/

However, my implementation uses superfluous elements and, so, I was wondering if anyone had any ideas/suggestions of another way to achieve this?

Javascript is certainly an option but I worry it would not be lean/elegant. Someone also suggested using Canvas.

Any ideas welcomed! Thank you.

You can avoid extra markup by using :after CSS pseudo element. Thus, your final markup will look like:

<ul>
        <li class="light">
            <img src="http://farm3.static.flickr.com/2802/4253151258_7d12da9e1c_z.jpg" />
        </li>
        <li class="dark">
            <img src="http://farm1.static.flickr.com/31/66005536_d1c5afca29_z.jpg?zz=1" />
        </li>
        <li class="light">
            <img src="http://farm4.static.flickr.com/3574/3646151231_0c68f4f974_z.jpg" />
        </li>
        <li class="dark">
            <img src="http://farm4.static.flickr.com/3432/3310214210_813d13c899_z.jpg" />
        </li>
    </ul>

And the altered CSS will be:

.dark:after,
.light:after,
.dark .after,
.light .after {
    position: absolute;
    display: block;
    content: '';
    top: 0; left: 0;
    height: 100%;
    width: 76px;
    background: transparent url(logo-white.png) no-repeat fixed 0 0;
    z-index: 5;
}

.dark:after,
.dark .after {
    background-image: url(logo-black.png);
}

Notice that there is .after class there. This is to make it work in IE<8, which, sadly, requires to use an expression:

.dark,
.light {
    behavior: expression( !this.before ? this.before = this.innerHTML = '<div class="after"></div>' + this.innerHTML : '' );
}

While using expressions is generally discouraged, this one shouldn't affect the performance too much, since it is fully evaluated only once, and when the element is created, the condition returns false.

There is one pitfall, though. If IE8 works in IE8/IE8 mode, the pseudo-elements will be under the images, unless you set negative z-index for the latter, which isn't always acceptable.

You can look at working example here.

Besides seeing, is there any way to know which font is currently applied on an HTML element

11 votes

Consider that I have this CSS rule for an anchor tag:

font-family: Helvetica, Verdana, Calibri, Arial, sans-serif;

Of course by watching at what is rendered in the browser, I can judge which of these fonts has already been used (applied) to format the current anchor element's text.

However, I need to know which font is currently in use via JavaScript (jQuery for example). This jQuery code doesn't help me:

$('#anchor-id').css('font-family');

because it returns 'Helvetica, Verdana, Calibri, Arial, sans-serif;'. Is there a way to know which font is in action now?

Update: Based on @MC answer, I created this fiddle and you can check that it's working just nice and quite.

First, you need to test if a font has been installed. I have used some scripts on the internet which will test if a font is installed or not.

Include this snippet of code somewere (thanks to Lucas Smith):

var Font = {

    isInstalled : function (name) {
        name = name.replace(/['"<>]/g,'');

        var body = document.body;
        var test = document.createElement('div');
        var installed = false;
        var teststring = "mmmmmmmmwwwwwwww";
        var template = '<b style="display:inline !important; width:auto !important; font:normal 10px/1 \'X\',sans-serif !important">' + teststring + '</b><b style="display:inline !important; width:auto !important; font:normal 10px/1 \'X\',monospace !important">' + teststring + '</b>';
        var ab;

        if (name) {
            test.innerHTML = template.replace(/X/g, name);
            test.style.cssText = 'position: absolute; visibility: hidden; display: block !important';
            body.insertBefore(test, body.firstChild);
            ab = test.getElementsByTagName('b');
            installed = ab[0].offsetWidth === ab[1].offsetWidth;
            body.removeChild(test);
        }
        return installed;
    }
}

In addition, use the following snippet (I wrote that myself) to get the font-family value and split that value into parts. Each part is a font, as they are separated by a comma in the CSS code (e.g. font-family: "Nimbus", "Courier New";):

function workingFont(element) {
    var fontString = $(element).css('font-family');
    var fonts = fontString.split(",");
    for (var f in fonts) {
        if (Font.isInstalled(fonts[f])) {
            return fonts[f];
        }
    }
}

As you can see, the first installed font will be returned.

Use workingFont(element), where element is the element id, class or tagname. This is part of the jQuery API. Notice you must have jQuery included to get the aforementioned script working.

Update: I created this jsfiddle to test it.

CSS Selector "(A or B) and C"?

10 votes

This should be simple, but I'm having trouble finding the search terms for it.
Let's say I have this:

<div class="a c">Foo</div>
<div class="b c">Bar</div>

In CSS, how can I create a selector that matches something that matches "(.a or .b) and .c"?

I know I could do this:

.a.c,.b.c {
  /* CSS stuff */
}

But, assuming I'm going to have to do this sort of logic a lot, with a variety of logical combinations, is there a better syntax?

is there a better syntax?

No. CSS' or operator (,) does not permit groupings. It's essentially the lowest-precedence logical operator in selectors, so you must use .a.c,.b.c.

How can I achieve a slot machine spinning effect with CSS3 & jQuery?

9 votes

I am creating a demo application that randomly selects a venue when a button is clicked. Once the button is clicked I want to have the venues scroll through with a slot machine spinning animation using CSS3 and jQuery before a venue is selected.

I thought about using -webkit-keyframes and changing the background position, but it's not the ideal animation I would like.

@-webkit-keyframes spin{  
  0% {  
        background-position: 0, 0 0;
        -webkit-transform: rotateX(0deg);
     }
  100% { 
        background-position: 0, 0 -640px;
        -webkit-transform: rotateX(360deg);
     }
}

.rotating{
    -webkit-animation: spin .5s infinite linear;
    -webkit-transition: background-position .7s;
}

Can anyone give any insight on how this can be achieved? Here is what I have so far. Any help is appreciated.

Thank You

After much research plagiarising I've come up with this. Hopefully it helps in some shape or form.

http://jsfiddle.net/DnTX6/

Ellipsis for overflow text in dropdown boxes

8 votes

I'm fixing the width of one of my dropdown boxes (yes I know there are cross-browser issues with doing this).

Is there a non-js way to cut off overflowing text and append ellipses? text-overflow:ellipsis doesn't work for <select> elements (at least in Chrome).

Example here: http://jsfiddle.net/t5eUe/

HTML is very limited in what it specifies for form controls. That leaves room for operating system and browser makers to do what they think is appropriate (like the iPhone’s modal select which, when open, looks totally different from the traditional pop-up menu).

It looks like most operating systems cut the selected option off without an elipsis. If you were able to change how the text gets cut off, it would look strange since that’s not how select boxes work in the rest of the operating system.

If it bugs you, you can use a customizable replacement, like Chosen, which looks distinct from the native select.

Or, file a bug against a major operating system or browser! For all we know, the way text is cut off in selects might be the result of a years-old oversight that everyone copied, and it might be time for a change.

Overflow: hidden does not apply in Firefox 5 when set via JavaScript

8 votes

This is confirmed to be a bug in Firefox and you can learn more about it at https://bugzilla.mozilla.org/show_bug.cgi?id=686247

I am setting overflow to hidden via jQuery but it does not get applied in Firefox 5 while in other browsers it does get applied well. Please test this jsfiddle to see the problem yourself: http://jsfiddle.net/f4HJd/ And here is an image of how it looks in Firefox 5: http://i.stack.imgur.com/70zfy.png and an image of that in Chrome to compare: http://i.stack.imgur.com/eKVPB.png What is wrong with overflow in FF5?

EDIT:

After some tests I found out that the overflow property does get applied to elements that have been added dynamically via JavaScript. So, that means we can workaround the bug by replacing the element in question with its copy and applying overflow: hidden to it as follows in jQuery:

$('textarea').replaceWith($('textarea').clone().css('overflow', 'hidden'));

Just as a side note, we could even avoid replacing the element when possible like so:

// for all browsers
$('textarea').css('overflow', 'hidden');
// for FF only
if ($.browser.mozilla) $('textarea').replaceWith($('textarea').clone());

EDIT 2:

As further tests showed, overflow: hidden also get applied well when the position property is set to absolute or when the display property is set to either block or inline-block, via CSS statically or via JavaScript. So, something like this can easily help out:

$('textarea').css({ display: 'inline-block', overflow: 'hidden' });

EDIT 3:

The problem only appear to be regarding textarea elements. I tested it on DIV elements and the content get clipped well. So, I suspect it is because textarea elements are inline and the overflow property is meant to work for block-level elements.

This appears to be a bug in Firefox. The call from jQuery to set overflow equal to hidden doens't seem to work in Firefox unless you set the textarea's css overflow to a value in your css or style attribute first, then tell jQuery to set overflow to hidden.

textarea {
    width: 100px;
    height: 100px;
    overflow:auto;
}

(function ($) {
    $(document).ready(function () {
        $('textarea').css('overflow', 'hidden');
    });
})(jQuery);

Although, I am curious why you don't just create a css class for that textarea, instead of relying on javascript to hide it's scrollbars in the first place.

What does style.display = '' actually do?

8 votes

After researching this issue for a couple of hours, I found that one of the most efficient ways to toggle a page element's display (in HTML) is to do something like:

// showing
document.getElementById('element').style.display = '';

// hiding
document.getElementById('element').style.display = 'none';

Simple question: What does style.display = '' actually do?

Does it "reset" the original display property?

Or does it remove the display property, thereby using the default style for display?

..........................................

Would be nice to know: Does anyone know of any links to any kind of documentation about this?

(Yes, I have Google-d this issue, but I'm probably not entering the right search term and keep coming up with completely un-related search results.)

Thanks for any suggestions or links.

Yes, it resets the element's display property to the default by blanking out the inline "display: none", causing the element to fall back on its display property as defined by the page's ranking CSS rules.

For giggles, here's the Google query I used for verification of my answer: javascript style display empty string default

...and a couple of links where this is mentioned:

http://jszen.blogspot.com/2004/07/table-rowsrevealed.html

http://www.harrymaugans.com/2007/03/05/how-to-create-a-collapsible-div-with-javascript-and-css/ (not in the article, but in the comments section)

How to extend jQuery.css from plugin

8 votes

I have written a very simple plugin that allows me to use 0xffccaa format for css colours instead of '#ffccaa' (mostly to avoid writing quotes - but also to allow easy modification of colours by simply adding to it as an integer).

I am implementing as $().xcss({}), but would prefer to just use $().css({}).

How can I extend the functionality of the $.fn.css function, and are there any pitfalls I need to watch out for?

Also, I guess I will want to do the same for $.animate.

Fiddle: http://jsfiddle.net/hB4R8/

// pugin wrapper
(function($){ $.fn.xcss = function(opts){
    // loop through css color properties 
    $.each(['background', 'backgroundColor','background-color', 'color', 'borderColor','border-color'],function(i,v){
        // if set as number (will be integer - not hex at this point)
        // convert the value to `#ffccaa` format (adds padding if needed)
        if(typeof opts[v] === 'number')
            opts[v] = ('00000'+opts[v].toString(16)).replace(/.*([a-f\d]{6})$/,'#$1')
    })
    // run css funciton with modified options
    this.css(opts)
    // allow chaining
    return this
} })(jQuery)

// test the plugin
$('body').xcss({
    'background-color': 0xffccFF,
    color: 0xccffcc,
    border: '3px solid red',
    borderColor:0x0ccaa,
    padding:50
}).html('<h1>This should be a funny color</h1>')

This seems work for me: http://jsfiddle.net/frfdj/

(function($) {
    var _css = $.fn.css; // store method being overridden
    $.fn.css = function(opts) {
        $.each(['background', 'backgroundColor', 'background-color', 'color', 'borderColor', 'border-color'], function(i, v) {
            if (typeof opts[v] === 'number') opts[v] = ('00000' + opts[v].toString(16)).replace(/.*([a-f\d]{6})$/, '#$1')
        })
        return _css.apply(this, [opts]); // call original method
    }
})(jQuery)

Put CSS and JavaScript in files or main HTML?

8 votes

Although it is always recommended to put JavaScript and CSS code into appropriate files (as .js and .css), most of major websites (like Amazon, facebook, etc.) put a significant part of their JavaScript and CSS code directly within the main HTML page.

Where is the best choice?

http://developer.yahoo.com/performance/rules.html#external

Yahoo (even though they have many inline styles and scripts), recommends making them external. I believe google page speed used to (or still does?) do the same as well.

It's really a logical thing to have them separate. There are so many benefits to keeping CSS and JS separate to the HTML. Things like logical code management, caching of those pages, lower page size (would you rather a ~200ms request for a 400kb cached resource, or a 4000ms delay from having to download that data on every page?), SEO options (less crap for google to look through when scripts/styles are external), easier to minify external scripts (online tools etc), can load them synchronously from different servers....

That should be your primary objective in any website. All styles that make up your whole website should be in the one file (or files for each page, then merged and minified when updated), the same for javascript.

In the real world (not doing a project for yourself, doing one for a client or stakeholder that wants results), the only time where it doesn't make sense to load in another javascript resource or another stylesheet (and thus use inline styles/javascript) is if there's some kind of dynamic information that is on a kind of per-user, per-session or per-time-period that can't be accomplished as simply any other way. Example: when my website has a promotion, we dump a script tag with a small JSON object of information. Because we don't minify and merge multiple files, it makes more sense to just include it in the page. Sure there are other ways to do this, but it costs $20 to do that, whereas it could cost > $100 to do it another way.

Perhaps Amazon/Facebook/Google etc use so much inline code is so their servers aren't taxed so much. I'm not too sure on the benchmarking between requesting a 1MB file in one hit or requesting 10 100KB files (presuming 1MB/10 = 100KB for examples' sake), but what would be faster? Potentially the 1MB file, BUT smaller requests can be loaded synchronously, meaning each one of those 10 requests could come from a separate server/domain potentially, thus reducing overall load time.

Further, google homepages for example seem to dump a JSON array of information for the widgets, presumably because it compiles all that information from various sources, minifies it, caches it, then puts in on the page, then the javascript functions build the layout (client side processing power rather than server-side).

What's the opposite of '!important' in CSS?

8 votes

I'm building a jQuery plugin that uses CSS styles to add colors and margins to nested DIV tags. Since I'd rather keep the plugin as a single file, my code adds these colors and margins directly as CSS attributes to the DIVs using jQuery's .css() method. (The values for these attributes can be customized when the plugin is initialized.)

However, I also wanted to give users the power to style these DIVs using their own stylesheets, so I'm also adding classes to each group of DIVs (for which the names can also be customized). This seemed like the best way to provide the best of both worlds.

The only drawback seems to be that inline style="..." attributes (generated by jQuery's .css() method) always override class styles set in the external stylesheet. I can, of course, use !important styles in the stylesheet, but doing this again and again is cumbersome.

So: what I really want is a way to make the inline styles automatically take a lower priority than the external class styles, without having to make the external class styles !important.

I have not read about such a thing. Any suggestions? (Or: is there another approach I should be taking to style my DIVs in the plugin?)

What's the opposite of !important in CSS?

There isn't an exact opposite, but there are lower precedence selectors.

w3c spec defines the cascade, might as well read it.

inline styles have highest precedence, and you're after a low-precedence style, you'll need to add CSS via a stylesheet or style element.

Because you're using jQuery, adding a custom style element is very easy:

$('<style type="text/css">.foo {color: #FF0000;}</style>').prependTo('head');

The issue you're then going to find is that a user who has specified .foo in a stylesheet will need a higher specificity to win out over the style element, so I'd recommend using an additional class for each element so that a user can override the defaults:

.foo.override { color: #0000FF; }

In all cases you're going to want to carefully pick your selectors to have the least specificity possible.

CSS alignment problem

5 votes

How can I make my registration fields like this

enter image description here

How can I achieve this via CSS? I mean, that my textboxes should be aligned from label's end to the page's end...

EDIT

Here is my view part

<div id="member-search">

<h5>Last Name:</h5>
@Html.TextBox("member-last-name")
</div>
<div>
<h5>Pass:</h5>
@Html.TextBox("member-pass")
</div>

<input type="submit" value="Search" class="button"/>
</div>

In CSS I tried a lot, but with no success. width:auto doesn't help and I don't find solution for this. Thanks for help.

With changes to your view you can achieve this. My answer is based on the following answer: How to make text input box to occupy all the remaining width within parent block?

You can look at the modified version of the answer at http://jsfiddle.net/626B2/63/

HTML:

<div id="parent">
    <div id="inner">
        <label>UserName</label><span><input id="text" type="text" /></span>
    </div>
    <div id="inner">
        <label>pass</label><span><input id="text" type="text" /></span>
    </div>
    <input id="submit" type="button" value="Submit" />
</div>

CSS:

#inner {
    display: table;
    width: 100%;
}
label {
    display: table-cell;
    white-space:nowrap;

}
span {
    display: table-cell;
    width: 100%;
    padding: 0px 10px;
}
#text {
    width: 100%;
}