Best css questions in June 2012

Is it possible to make a div 50px less than 100% in CSS3?

132 votes

Is it possible to make a div 50px less than 100% in pure CSS? I want the <div> to be only 50px less than 100%. I don't want any JavaScript.

Yes you can. Without using the IE's expression(), you can do that in CSS3 by using calc().

div {
    width: 100%;
    width: -webkit-calc(100% - 50px);
    width: -moz-calc(100% - 50px);
    width: calc(100% - 50px);
}

Demo: http://jsfiddle.net/thirtydot/Nw3yd/66/

This will make your life so much easier. It is currently supported in the 3 main browsers: Firefox, Google Chrome (WebKit), and IE9: http://caniuse.com/calc

MDN: https://developer.mozilla.org/en/CSS/-moz-calc

HTML/CSS: "See Through Background" Text?

11 votes

Ok, is this possible.

I have a background image. On top of that, I have a transparent grey box for content. I'd like to have title at the top in text, that is basically the letters exposing the background. So, the text removes the grey box and lets the background show through.

The only hacky way I can see is create an image with the letters transparent on a background the same grey color, and then try to somehow align that with the grey box.

Is there another - better - way?

One way is to use -webkit-background-clip: text;: demo here (webkit only obviously).

Using position, we can sync both backgrounds:

#container, #container h1 {
    background: url(bg.png)
}

#container {
    position: relative;
}

#container #gray {
    background: rgba(0,0,0,.8);
    padding-top: 8em;
}

#container h1 {
    font-size: 8em;
    padding-top: /* padding + border of div */;
    position: absolute;
    -webkit-text-fill-color: transparent;
    -webkit-background-clip: text;
}​

Or you could use the same approach and apply a svg mask, that will work in all modern browsers.

Rendering box shadow around unconventional shapes with HTML/CSS

11 votes

I'm currently working on a little project in which I'm trying to create a venn diagram representing additive colors. I've started with three circles (border-radius: 50%;) and used a combination of statically-position elements with hidden overflow to create some of the more complex shapes where the circles overlap. You can see what I currently have here:

http://jsfiddle.net/GjvEE/

One feature I'd like to add is the addition of a colored box-shadow around the shape currently being moused-over. The unique challenge I'm facing is presented by the nesting of the elements with hidden overflow, and the need to create 'faux-edges' along which to render the box shadow for each section of the diagram. I've considered the option of simply scrapping this approach and creating the shapes via SVG, but I'm interested to see if any of you have any clever ideas for building this sort of interaction into more complex shapes using traditional HTML and CSS3 alone.

Thanks in advance!

How about using CSS's :after to generate new circles behind the others and use a radial gradient background that fades to transparent?

I've done quick, basic implementations for Webkit on the red and blue circles here. Note the :hover:after style definitions. http://jsfiddle.net/stevelove/2hpwp/

Can I override inline !important?

10 votes

If you have

<div style="display: none !important;"></div>

Is there a way to override that in the stylesheet to make it displayed:

div { display: block !important; }

?

You can not override inline CSS having !important, because it has higher precedence, but using Javasctip/Jquery tweaks you may achieve what you want.

Can you have a javascript hook trigger after a DOM element's style object changes?

9 votes

An element has a javascript style object which contains the different names and values of css styles. I'd like to trigger a function every time this object changes without use of polling. Is there any way to do this in a way that is cross-browser compatible and would work reliably with third party code (because let's say you're providing a drop-in script)? Binding a javascript event like DOMAttrModified or DOMSubtreeModified won't suffice because they don't work in Chrome.

Edit 2:

  1. Fix for propertName in IE7 & IE8

Edit 1:

  1. Handle multiple elements
  2. Ordered the conditions as MutationObserver, DOMAttrModified and onpropertychange for better implementation.
  3. Added modified Attribute Name to the callback.

Thanks to @benvie for his feedback.

DEMO: http://jsfiddle.net/zFVyv/10/ (Tested in FF 12, Chrome 19 and IE 7.)

$(function() {
    (function($) {
        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

        function isDOMAttrModifiedSupported() {
            var p = document.createElement('p');
            var flag = false;

            if (p.addEventListener) p.addEventListener('DOMAttrModified', function() {
                flag = true
            }, false);
            else if (p.attachEvent) p.attachEvent('onDOMAttrModified', function() {
                flag = true
            });
            else return false;

            p.setAttribute('id', 'target');

            return flag;
        }

        $.fn.attrchange = function(callback) {
            if (MutationObserver) {
                var options = {
                    subtree: false,
                    attributes: true
                };

                var observer = new MutationObserver(function(mutations) {
                    mutations.forEach(function(e) {
                        callback.call(e.target, e.attributeName);
                    });
                });

                return this.each(function() {
                    observer.observe(this, options);
                });

            } else if (isDOMAttrModifiedSupported()) {
                return this.on('DOMAttrModified', function(e) {
                    callback.call(this, e.attrName);
                });
            } else if ('onpropertychange' in document.body) {
                return this.on('propertychange', function(e) {
                    callback.call(this, window.event.propertyName);
                });
            }
        }
    })(jQuery);

    $('.test').attrchange(function(attrName) {
        alert('Attribute: ' + attrName + ' modified ');
    }).css('height', 100);

});

Ref:

  1. Detect if DOMAttrModified supported
  2. DOMAttrModified for chrome
  3. Mutation Observer
  4. Why should we avoid using Mutation events?
  5. onPropertyChange IE

Mutation Observers is the proposed replacement for mutation events in DOM4. They are expected to be included in Firefox 14 and Chrome 18

Browser Support:

onpropertychange - is supported in IE (tested in IE 7)

DOMAttrModified - is supported in IE 9, FF and Opera

MutationObservers - is very new and it worked fine in Chrome 18. Not sure how far it is supported and yet to be tested in Safari.

Thanks @benvie on adding info about WebkitMutationObserver

Applying a background to <html> and/or <body>

8 votes

http://jsfiddle.net/julien_c/GmAL4/

I found that if you apply a CSS background to body, it takes up the whole page (no matter what the actual height of body is).

However, if you apply a CSS background to both html and body, the background for body does not take up the whole page.

Is this discrepancy expected behavior?

How would I go about superimposing two fullscreen backgrounds (say, a background color and a semi-transparent image?)

This is correct behavior.1 Unlike html, body doesn't immediately take up the entire height of the viewport, even though it appears so when you only apply a background to the latter. In fact, the html element will take on the background of body if you don't give it its own background:

For documents whose root element is an HTML HTML element or an XHTML html element: if the computed value of ‘background-image’ on the root element is ‘none’ and its ‘background-color’ is ‘transparent’, user agents must instead propagate the computed values of the background properties from that element's first HTML BODY or XHTML body child element. The used values of that BODY element's background properties are their initial values, and the propagated values are treated as if they were specified on the root element. It is recommended that authors of HTML documents specify the canvas background for the BODY element rather than the HTML element.

To that end, you can easily set a background color to html, and set a background image to body which you wish to superimpose over the background color. To ensure the background image on body takes up the full viewport height, you need to apply height and min-height respectively as well:

html {
    height: 100%;
    background-color: #ddd;
}

body {
    min-height: 100%;
    background: transparent url(background.png) center top no-repeat;
}

My comments under this other answer explain, with an accompanying fiddle, how body is actually offset from html by default margins even though it looks like it's being padded out instead, again owing to this seemingly strange phenomenon.


1 This may have its roots in setting the HTML background and bgcolor attributes of body causing the background attribute to apply to the entire viewport.

<html> width is less than its background

8 votes

I've set a style on <html>:

html {
    background: #ECECEC;
    border: 1px solid #FFFFFF;
}

If the contents of the page are wider than the page, why does the border stop, but the background keep going?

html is a proper block-level element, just like body, p, div, etc — it therefore observes all the same overflow rules as other block elements do.

However, the reason why the background of html bleeds past its border when content overflows its width (or when its width is less than 100% of the browser window, or viewport), is because the background color is propagated to the viewport, which is the canvas containing html and all its contents that are rendered. The border remains part of the html element, however, so the element doesn't expand when the content overflows. This behavior is very similar to how applying a background to body, but not html, causes the body background to propagate to the root element anyway, as described in this answer which cites this section of the spec.

As Alohci notes in a comment under the answer, the same applies to html with respect to the viewport:

Note that html behaves with respect to the viewport in much the same way as body behaves with respect to html, with the background escaping beyond the confines of the html element. See http://jsfiddle.net/GmAL4/4/ to see what I mean.

What is the cleanest way to disable css transition effects temporarily?

8 votes

I have a DOM element with some/all of the following effects applied:

#elem {
  -webkit-transition: height 0.4s ease;
  -moz-transition: height 0.4s ease;
  -o-transition: height 0.4s ease;
  -ms-transition: height 0.4s ease;
  transition: height 0.4s ease;
}

I am writing a jQuery plugin that is resizing this element, I need to disable these effects temporarily so I can resize it smoothly.

What is the most elegant way of disabling these effects temporarily (and then re-enabling them), given they may be applied from parents or may not be applied at all.

Add an additional CSS class that blocks the transition, and then remove it to return to the previous state. This make both CSS and JQuery code short, simple and well understandable.

CSS:

.notransition {
  -webkit-transition: none !important;
  -moz-transition: none !important;
  -o-transition: none !important;
  -ms-transition: none !important;
  transition: none !important;
}

!important was added to be sure that this rule will have more "weight", because ID is normally more specific than class.

JQuery:

$('#elem').addClass('notransition'); // to remove transition
$('#elem').removeClass('notransition'); // to return to previouse transition

Using :after CSS selector to fill a space?

7 votes

On this page I wish to have the entire space to the right of the navigation filled in white.

So, I achieved 5px wide white block using the :after CSS selector, and am hoping there is a way to make it fit the available width, although I am open to other suggestions!:

#menu-main-menu:after {
    content:"";
    display:block;
    background:#fff;
    width:5px;
    height:30px;
    float:right;
    }

Here is the simplified HTML:

<div class="menu"><ul id="menu-main-menu">
<li><a href="#">Home</a></li>
<li><a href="#">About us</a></li>
<li><a href="#">Courses &#038; prices</a></li>
<li><a href="#">Activities in Rio</a></li>
<li><a href="#">Accommodation</a></li>
<li><a href="#">News</a></li>
<li><a href="#">FAQs</a></li>
<li><a href="#">Contact</a></li>
</ul>
</div>

And all the relevant CSS:

#primary-menu ul {
    overflow:hidden;
}
#primary-menu li {
    list-style:none;
    float:left;
}
#primary-menu a {
    color:#333;
    background: #fff;
    display:block;
}
#primary-menu .current-menu-item a, #primary-menu .current-page-parent a {
    color:#fff;
    background:none;
}
#menu-main-menu:before {
content:"";
display:block;
background:#fff;
width:20px;
height:30px;
float:left;
} 
#menu-main-menu:after {
content:"";
display:block;
background:#fff;
width:5px;
height:30px;
float:right;
}

Thanks for taking the time to check out my question!

Caroline

You could add the ::after pseudo selector to the li.current-menu-item instead of #menu-main-menu and add white background from that element onwards.

.current-menu-item:after {
    background: none repeat scroll 0 0 #fff;
    content: "";
    height: 30px;
    position: absolute;
    right: -1000px;   /* these numbers are the same */
    top: 0;
    width: 1000px;    /* and need to be at least the width of the menu */
}

#primary-menu li {
    position: relative;  /* position the ::after element relative to the li */
}

#primary-menu ul {
    ....
    overflow: hidden;  /* you already have this to clear your floats */
    ....               /* but I thought I should emphasise that you need it */
}

How can I style a part of a single character with overlays using a dynamic width?

7 votes

Question

Can I style just a part of a single character?

Meaning

CSS attributes cannot be assigned to parts of characters. But if you want to style only a certain section of a character, there is no standardized way to do that.

Example

Is it possible to style an "X" which is half-way red and then black?

Expected result

Not working code

<div class="content"> 
    X
</div>
.content {
    position: relative;
    font-size: 50px;
    color: black;
}

.content:after {
    content: 'X';
    color: red;
    width: 50%;
    position: absolute;
    overflow: hidden;
}

Demo on jsFiddle

Purpose

My intention is styling the Font Awesome icon-star symbol. If I have an overlay with dynamic width, shouldn't it be possible to create an exact visualization of scores?

While playing around with a demo fiddle, i figured it out myself and wanted to share my solution. It's quite simple.

First things first: The DEMO

To partly style a single character, you need extra markup for your content. Basically, you need to duplicate it:

<​div class="content"> 
    <span class="overlay">X</span>
    X
</div>

Using pseudo-elements like :after or :before would be nicer, but i didn't found a way to do that.

The overlay needs to be positioned absolutely to the content element:

​.content {
    display: inline-block;
    position: relative;
    color: black;
}

​.overlay {
    width: 50%;
    position: absolute;
    color: red;
    overflow: hidden;
}​

Do not forget overflow: hidden; in order to cut off the remaing part of the "X".

You can use any width instead of 50% which makes this approach very flexible. You can even use a custom height, other CSS attributes or a combination of multiple attributes.

Extended DEMO

Why is the source code for some web pages all in one line?

7 votes

When viewing lots of webpages' source code (like JS,CSS,HTML), I find them in one line. How did they make this? Do they use some tools to make it? Can we restructure it?

Thanks.

Using Minify technique

Some free tools also available

http://developer.yahoo.com/yui/compressor/

http://www.minifycss.com/minify-tools/minify-css-tools.php

http://jscompress.com/

http://www.minifycss.com/css-compressor/

http://code.google.com/p/htmlcompressor/

It combines multiple CSS or Javascript files, removes unnecessary whitespace and comments, and serves them with gzip encoding and optimal client-side cache headers.

Why is <INPUT> wider than i told it to be?

7 votes

Given a <select> and an <input> element, both specified to be 200px wide:

<!doctype html>
<body>
<select style="width: 200px"></select><br/>
<input  style="width: 200px" type="text">
</body>
<html>

One ends up wider1,2,3, 4 than the other:

enter image description here

What is the reason for this?

If someone can give the reason, perhaps the solution would be obvious, and not a hack&pray.

Layout

The applied layout is perfectly reasonable:

enter image description here


Update 1: While i was writing this question Chrome updated itself from 17 to 19.

Update 2: Changing padding in the <input> from 1 to zero:

<!doctype html>
<body>
<select style="width: 200px"></select><br/>
<input style="width: 200px; padding: 0" type="text">
</body>
<html>

doesn't make the <input> 200px wide (i.e. doesn't fix it).

Update 3: Applying a CSS reset:

<!doctype html>
<head>
<style type="text/css">
   * {
       padding: 0;
       margin: 0;
   }
</style>
<body>
<select style="width: 200px"></select><br/>
<input style="width: 200px; padding: 0" type="text">
</body>
<html>

Does not solve the problem:

enter image description here

Also, i am less interested in a solution than an explanation.

Footnotes

  • 1,2,3 Chrome 1719, Firefox, Internet Explorer 9
  • 4 on Windows 7 64-bit

Bonus Reading

Your <input> isn't too wide; your <select> is too narrow!

The real issue is that the <select> element doesn't behave like most elements do. It uses a border-box model, where width is the width of the element after padding and borders are applied.

This runs counter to every other element when in "standards" mode; behaving as though it alone were in "quirks" mode.

The input element behaves like most elements do, using a content-box model, where the width is the width of the element before padding and borders are applied.

There are default padding and borders set by your browser, so it is larger than you might want and/or expect. I always use a "CSS reset" at the top of my stylesheets, like so:

* {
    padding: 0;
    margin: 0;
}

That will ensure there are no default padding or margins on any element.

The select element is a different case though, where is behaves more like an element with box-sizing: border-box enabled, where it takes into account borders and padding into its width specification.

If you add box-sizing: border-box to your input element, it will behave exactly as you expect/want.

EDIT: Bolded the part that may be relevant to you. An alternate solution is reducing the specified width of the input element by a few pixels, so that it matches the width of the select box.

Fiddle demonstrating both solutions: http://jsfiddle.net/n4yT2/2/