Best css questions in October 2011

What is the least horrible way to center an element with CSS?

19 votes

I have html that looks like this:

<!DOCTYPE html> 
<head>
    <meta charset="utf-8">

    <!--[if lte IE 8]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
</head> 

<body>

<header>
  <h1>Some title thing, who knows</h1>
  <nav>
    <ul>
      <li><a href="one/">One</a></li>
      <li><a href="two/">Two</a></li>
      <li><a href="three/">Three</a></li>
    </ul>
  </nav>
</header>

</body>
</html>

If I give header an auto margin and a width, it's horizontally centered. What's the least horrible way to ensure that it's vertically centered, as well?

I am aware of the following articles which provide some discussion of the topic:

Since this question was tagged CSS3, here's a "least horrible" solution using CSS3's "flexbox". Unfortunately only recent versions of Safari, Chrome and Firefox support it.

html, body {
  margin:0;
  padding:0;
  height:100%;
  background:#eee;
}
header {
  width:30em;
  background:#fff;
}
body {  
  display:box;
  box-pack:center;
  box-align:center;
  box-orient:horizontal;
}

A more complete demo can be found here.

Determine Maximum Possible DIV Height

14 votes

Is there a recommended way to determine the maximum height that a DIV can be set and remain visible per browser? This doesn't appear to be documented anywhere and is highly implementation specific.

For example, see the following test script:

http://jsfiddle.net/NP5Pa/2/

This is a simple test to find the maximum value you can set a DIV style height attribute before the corresponding clientHeight of the element becomes 0. You can confirm this by clicking "Find Max" then incrementing the found height by 1 and clicking "Set Height".

Some examples (Win7/64):

Chrome (14.0) :    134,217,726 px
Safari (5.1)  :    134,217,726 px
IE (9.0)      :     10,737,418 px
FF (7.0.1)    :     17,895,697 px

It's not surprising the WebKit produces the same result, I guess - more surprising that IE and FF are so different.

Is there a better way? And do you get different results in 32bit systems?

--EDIT: Updated the fiddle to stop at 10,000,000,000 (and get there quicker) for Opera. That's a lot of pixels.

This is your code, modified to use binary search (so it's much quicker).

http://jsfiddle.net/thai/zkuGv/4/

It begins at 1 pixel and doubling its size until the it hits the maximum (I use 253, which is the biggest integer that can be stored in JavaScript without losing precision and would make the binary search buggy), or the div collapses to zero pixel.

Suppose we set the div to size h and it disappears, then the maximum size must be between h/2 and h. We binary search from there for a height h that does not make the div disappear when set to height h, but disappears when set to h+1.

Then we can come to a conclusion for Opera: 2147483583 pixels.

How do you tweak "-webkit-" prefixed CSS properties in jQuery?

12 votes
    $(this).css({
        -webkit-transform:'rotate(180deg)',
        -moz-transform: 'rotate(180deg)',
        -o-transform: 'rotate(180deg)',
        -ms-transform: 'rotate(180deg)'
    });

This is throwing the error:

Uncaught SyntaxError: Unexpected token -

I'm really hoping I dont have to install the jQuery Rotation plugin just for this one instance.

$(this).css({
    '-webkit-transform':'rotate(180deg)',
    '-moz-transform': 'rotate(180deg)',
    '-o-transform': 'rotate(180deg)',
    '-ms-transform': 'rotate(180deg)'
});

Do I need to wrap quotes around font family names in CSS?

11 votes

I remember hearing a long time ago that it was considered "best practice" to wrap quotes around font names that contain multiple words in the CSS font-family property, like this:

font-family: "Arial Narrow", Arial, Helvetica, sans-serif;

For the heck of it, I tried removing the quotes from "Arial Narrow" and Safari and Firefox don't have any problem rendering it.

So, is there any logic to this rule of thumb, or is it just a myth? Was it an issue with older browsers that no longer applies to the current versions? I've been doing this for so long that I never stopped to think if it was actually necessary.

The CSS 2.1 spec tells us that:

Font family names must either be given quoted as strings, or unquoted as a sequence of one or more identifiers. This means most punctuation characters and digits at the start of each token must be escaped in unquoted font family names.

It goes on to say:

If a sequence of identifiers is given as a font family name, the computed value is the name converted to a string by joining all the identifiers in the sequence by single spaces.

To avoid mistakes in escaping, it is recommended to quote font family names that contain white space, digits, or punctuation characters other than hyphens:

So yes, there is a difference, but one that's unlikely to cause any problems. Personally, I have always quoted font names when they contain spaces. In a few (presumably very rare) cases, the quotes are absolutely required:

Font family names that happen to be the same as a keyword value ('inherit', 'serif', 'sans-serif', 'monospace', 'fantasy', and 'cursive') must be quoted to prevent confusion with the keywords with the same names.

"Export" styling of HTML elements

11 votes

I often find nice stylings on the web. To copy the style of an element I like, I inspect that element with Google Chrome Developer Tools, look at the various CSS properties, and copy them manually to my own stylesheets.

Is it possible to easily "export" all style properties of a given HTML element from the browser?

Here is the code for an exportStyles() method that should return a CSS string including all inline and external styles for a given element, except default values (which was the main difficulty).

For example: console.log(someElement.exportStyles());

Since you are using Chrome, I did not bother making it compatible with IE. Actually it just needs that the browsers supports the getComputedStyle(element) method.

Element.prototype.exportStyles = (function () {  

    // Mapping between tag names and css default values lookup tables. This allows to exclude default values in the result.
    var defaultStylesByTagName = {};

    // Styles inherited from style sheets will not be rendered for elements with these tag names
    var noStyleTags = {"BASE":true,"HEAD":true,"HTML":true,"META":true,"NOFRAME":true,"NOSCRIPT":true,"PARAM":true,"SCRIPT":true,"STYLE":true,"TITLE":true};

    // This list determines which css default values lookup tables are precomputed at load time
    // Lookup tables for other tag names will be automatically built at runtime if needed
    var tagNames = ["A","ABBR","ADDRESS","AREA","ARTICLE","ASIDE","AUDIO","B","BASE","BDI","BDO","BLOCKQUOTE","BODY","BR","BUTTON","CANVAS","CAPTION","CENTER","CITE","CODE","COL","COLGROUP","COMMAND","DATALIST","DD","DEL","DETAILS","DFN","DIV","DL","DT","EM","EMBED","FIELDSET","FIGCAPTION","FIGURE","FONT","FOOTER","FORM","H1","H2","H3","H4","H5","H6","HEAD","HEADER","HGROUP","HR","HTML","I","IFRAME","IMG","INPUT","INS","KBD","KEYGEN","LABEL","LEGEND","LI","LINK","MAP","MARK","MATH","MENU","META","METER","NAV","NOBR","NOSCRIPT","OBJECT","OL","OPTION","OPTGROUP","OUTPUT","P","PARAM","PRE","PROGRESS","Q","RP","RT","RUBY","S","SAMP","SCRIPT","SECTION","SELECT","SMALL","SOURCE","SPAN","STRONG","STYLE","SUB","SUMMARY","SUP","SVG","TABLE","TBODY","TD","TEXTAREA","TFOOT","TH","THEAD","TIME","TITLE","TR","TRACK","U","UL","VAR","VIDEO","WBR"];

    // Precompute the lookup tables.
    for (var i = 0; i < tagNames.length; i++) {
        if(!noStyleTags[tagNames[i]]) {
            defaultStylesByTagName[tagNames[i]] = computeDefaultStyleByTagName(tagNames[i]);
        }
    }

    function computeDefaultStyleByTagName(tagName) {
        var defaultStyle = {};
        var element = document.body.appendChild(document.createElement(tagName));
        var computedStyle = getComputedStyle(element);
        for (var i = 0; i < computedStyle.length; i++) {
            defaultStyle[computedStyle[i]] = computedStyle[computedStyle[i]];
        }
        document.body.removeChild(element); 
        return defaultStyle;
    }

    function getDefaultStyleByTagName(tagName) {
        tagName = tagName.toUpperCase();
        if (!defaultStylesByTagName[tagName]) {
            defaultStylesByTagName[tagName] = computeDefaultStyleByTagName(tagName);
        }
        return defaultStylesByTagName[tagName];
    }

    return function exportStyles() {
        if (this.nodeType !== Node.ELEMENT_NODE) {
            throw new TypeError("The exportStyles method only works on elements, not on " + this.nodeType + " nodes.");
        }
        if (noStyleTags[this.tagName]) {
            throw new TypeError("The exportStyles method does not work on " + this.tagName + " elements.");
        }
        var styles = {};
        var computedStyle = getComputedStyle(this);
        var defaultStyle = getDefaultStyleByTagName(this.tagName);
        for (var i = 0; i < computedStyle.length; i++) {
            var cssPropName = computedStyle[i];
            if (computedStyle[cssPropName] !== defaultStyle[cssPropName]) {
                styles[cssPropName] = computedStyle[cssPropName];
            }
        }

        var a = ["{"];
        for(var i in styles) {
            a[a.length] = i + ": " + styles[i] + ";";
        }
        a[a.length] = "}"
        return a.join("\r\n");
    }

})();

This code is base on my answer for a slightly related question: Extract the current DOM and print it as a string, with styles intact

How do browsers resolve conflicting classes?

10 votes

I know it's possible to specify multiple classes on an element in HTML:

<div class='one two'>Text</div>

It seems like classes are accessible from Javascript as a single string.

What happens when the classes are specified with conflicting properties? For instance

div.one {
  background-color: red; 
  color: blue;
}
div.two {
  background-color: green;
}

Will the result depend on the order the classes are specified in? For instance could I reasonably expect the div above to appear with blue text and a green background, because the two class becomes evaluated second, overwriting the background-color property?

Read about specificity:

Short answer: if two selectors have the same specificity, the last one to be declared wins.

@font-face and wrong letter tracking/spacing

9 votes

I've encountered a problem using @font-face while building a website. The font's installed on my PC, I've downloaded it from fontsquirrel.com.

If I use the version that's installed in my PC (Journal), all is well as you can see from the following screenshot:

However, as soon as I switch to the @font-face version, the letters' tracking (expecially Ts) is different and looks broken:

Here's the code for the @font-face (font-face kit downloaded from font squirrel):

@font-face {
font-family: 'JournalRegular';
src: url('journal-webfont.eot');
src: url('journal-webfont.eot?#iefix') format('embedded-opentype'),
     url('journal-webfont.woff') format('woff'),
     url('journal-webfont.ttf') format('truetype'),
     url('journal-webfont.svg#JournalRegular') format('svg');
font-weight: normal;
font-style: normal;
}

And here's the item (a div) styling:

#assignment-text {
font-family: Journal, JournalRegular, serif;
font-size: 3em;
text-align: center;
width: 340px;
position: absolute;
top: 200px;
left: 320px;
color: #000;
}

Using Journal everything is fine on my PC. Forcing JournalRegular (by commenting Journal) breaks spacing. I am developing in local. Tested in: Windows 7 PC (with font installed): Firefox 7, Chrome, Opera, IE9. Macbook (without font installed): Firefox, Safari.

Is this a known issue? I've searched but I can't seem to find a solution.

I've had similar problems with fonts I converted on font-squirrel. One of those times, going back to the generator and playing on the expert options, notably "Remove Kerning" solved it.

How to determine if width has px or %

8 votes

How can i tell if a css property such as width ex: width:100% has px or % assigned to it. in chrome for example if i have width:250px; and i do $('div').width() i get 250 whereas if i use percentage, i just get the width in px for the percentage based on my screen resolution.

This should work.

var value = $('#id').get(0).style.width;
var hasPx = value.indexOf('px') >= 0;
var hasPct = value.indexOf('%') >= 0;

JSBin: http://jsbin.com/asewit/2/edit#javascript,html

How can I set the hotspot to the center of a custom cursor?

8 votes

I'm using a custom cursor (png image) on a web page using cursor CSS attributes. I'd like to know if i can center the cursor position (like the cross-hair cursor in Windows) and not using the default top-left position.

One solution will be to hide the cursor and create a div with the custom cursor which will follow the cursor position but maybe someone has a better solution.

If your cursor is in .cur format (only .cur and .ani are supported in IE), then whichever program you use to create the .cur can set the hotspot in the header.

If you're using any other image type, CSS 3 allows the x and y values of the hotspot to be set:

#myEl { cursor: url(mycursor.png) <x> <y>; } 

Supported in:

  • Firefox 1.5+
  • Safari 3+
  • Chrome 1+

References

Tool for checking unused CSS selectors?

8 votes

I have read some answers on Stack Overflow about this topic.

I know there is an extension called Dust-Me Selectors for Firefox and also that it doesn't look at dynamic HTML generated by JavaScript.

So I just want to know, is there no tool on Earth, that can identify all unused selectors from a stylesheet, attached to several pages, properly, with running all the JavaScript and checking selectors?

And is the only option to do this is manually checking files and finding unused selectors?

Also I have seen, I think NetBeans provides a warning message when writing Java code, if a library is not under use. So is there no NetBeans, Eclipse or Dreamweaver plugin to search for the selectors?

And is there a tool to check for unused selectors in the same file. I mean if all JS, HTML and CSS code is in the same file.

Thanks...

I think that http://unused-css.com will do exactly what you want.

https://github.com/geuis/helium-css can help

as well as: http://razorfast.com/2010/11/21/announcing-cssess-the-bookmarklet-that-finds-unused-css-selectors/

Is it possible via CSS 3 to set the color of text in an element using the text content

7 votes

Okay, so this is more of a question that has lots of solutions that are not CSS, but I'm looking for doing this more from a theoretical perspective. I have an application for it, but its not worth coding it out in any other way.

The (Fun) Question

How do you color the text of an element using the text of the element? I have an element, all on it's own, which will contain a hex value for a color, and I want the text to be that color, but I want to do it only using CSS (likely only can be done using CSS 3).

Sample HTML

<div class="color_contents">#0000FF</div>

So, I've tried to use the attr() with no success, but I'm not sure I'm using the right contents (I've tried text, textContent, and innerText to no avail). Doesn't need to be cross-browser, but just a way to accomplish it.

Currently, there is no way to use CSS to access an element's text content.

Regarding this:

So, I've tried to use the attr() with no success, but I'm not sure I'm using the right contents (I've tried text, textContent, and innerText to no avail). Doesn't need to be cross-browser, but just a way to accomplish it.

attr() only looks at element attributes (foo="bar"). Since text content isn't an attribute of an HTML element (despite being a property of the corresponding DOM object), you can't query for it using that function.

There isn't a similar function for accessing an element's text content.

Reverse image archive : stacking images from bottom to top with CSS / Javascript?

7 votes

Wondering if anyone has a solution for this.
I would like to present an archive of thumbnail images oldest at the bottom and newest at the top. I would also like the flow itself to be reversed... something like this:

reverse archive

The page should be right aligned, with future images added to the top of the page. I am creating the page dynamically with PHP pulling image filenames from a MySQL DB. The catch here is I would love this layout to be fluid, meaning most PHP tricks for counting images and building the HTML accordingly go out the window.

Is there a way to do this with Javascript or even just CSS?

See: http://jsfiddle.net/thirtydot/pft6p/

This uses float: right to order the divs as required, then transform: scaleY(-1) flips the entire container, and lastly transform: scaleY(-1) again flips each individual image back.

It will work in IE9 and greater and all modern browsers.

CSS:

#container, #container > div {
    -webkit-transform: scaleY(-1);
       -moz-transform: scaleY(-1);
        -ms-transform: scaleY(-1);
         -o-transform: scaleY(-1);
            transform: scaleY(-1);
}

#container {
    background: #ccc;
    overflow: hidden;
}
#container > div {
    float: right;
    width: 100px;
    height: 150px;
    border: 1px solid red;
    margin: 15px;
    font-size: 48px;
    line-height: 150px;
    text-align: center;
    background: #fff;
}

HTML:

<div id="container">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    ..
</div>

Why the font size won't change with browser zoom in?

7 votes

In most of websites, while I change the zoom level of browsers, the font size will also increase and help user to see them. For some reasons, that just won't work on my new website. While I change the zoom level of the browser, everything changes but all font size keep the same. Is there a css or html property that I can use to control this behavior? Thanks

here is an example: http://ca.skywatcher.com/index.php

The problem is that you have set -webkit-text-size-adjust: none; for the body in layout.css. Changing it to -webkit-text-size-adjust: auto; allows the zooming of the fonts along with the page.

I guess this is just one weird speciality of Chrome (at least for me it was zooming correctly in Firefox).

Edit: Corrected the CSS. Should be auto not 0

Tool to parse and compare two CSS stylesheets

7 votes

Does anyone know of a good tool that can parse and compare two CSS stylesheets in order to find which selectors have different styles?

I cannot use a standard diff-like tool because the two CSS files have very different layout. I need a tool that can parse and understand the CSS, then look for selectors that actually have different styles in the two stylesheets.

The only tool I've found is the CSS Comparer from Alan Hart, however it gets confused when there are styles that apply to multiple selectors.

Here's what I ended up doing, in case someone else has the same problem:

  1. I used CSSTidy to "normalize" the two stylesheets I wanted to compare. Normalization in my case meant splitting multiple selectors and sorting selectors and properties. An online version of CSSTidy is available here.
  2. After this, I used the CSS Comparer tool from Alan Hart to find out differences between the two stylesheets.

This did the job for my specific requirements.

jquery - issue populating hidden div

3 votes

I have a div that I am populating with an ajax call to flickr. The goal is to fill the div with photos and then fadeIn the div. The problem is that I am using javascript to distribute the photos into 3 columns based on whichever column is shortest, but if the div is initially hidden there are no dimensions so the distribution script fails and puts all images in the first column.

Is there a way to hide the div but let it still have height? Using visibility: hidden doesn't work by the way.

As a hack, you can often fake invisibility by setting an element's margin to -3000px (or any other large number). The element will retain its width and height but be rendered outside of the screen's view.