My LESS mixin for all icon sizes from one sprite image file

This LESS mixin will resize a background-image, via the CSS3 background-size property, so this single PNG image sprite file can be resized and reused for all icons sizes that are lower or equal to the originals.

Why PNG images, why not SVG?

I love working with vectorial images. They offer so much advantages. But they are time consuming. Must of the designers at my job create their icons in Photoshop pixels. In some case, when I have free time, I lunch my FreeInk app and RE-design my icons as SVG image. But since it’s written front-end developer on my paychecks, not designer, it is hard to justify my time spent in a drawing software instead of a (code) text editor.

In real (sprint demo) life HTML website development, time is money. Using PNG (24) for background-image sprites is so much faster for HTML websites that there is no real choice.

CSS 3.0 background-size to the rescue!

The background-size property is a stable CSS 3.0 that is supported by all modern browsers, including IE9.

Compare real dimensions of close icon sizes within the sprite background-image; The original 50x50 VS the required 34x34 pixels in Photoshop viewport
The original 50×50 close button dimension VS the required 34×34 pixels in Photoshop viewport
Web inspector screenshot showing my HTML source code and CSS code generated with my LESS mixin in it's context
Web inspector screenshot showing my HTML source code and CSS code generated with my LESS mixin in it’s context.

My bgSpriteFix mixin

I broke the details in four parts for your conveninece:

  1. The variables
  2. The mixin itself
  3. The mixin in context
  4. The rendered CSS

The variables lexicon

LESS mixin’s variables CSS property Description
1. @bgColor background-color – –
2. @bgImg_url background-image – –
3. @spriteIco_pxSize_original – – The original size of the icons as they are designed within the original image-sprite.
4. @spriteIco_pxRequired_value width, height The required size for THIS icon. This variable should NOT higher the the original (@spriteIco_pxSize_original).
5. @imgFile_pxSize_w – – The outter width of the original image-sprite.
6. @imgFile_pxSize_h – – The outter height of the original image-sprite.
7. @bgImg_pxPosition_x background-position Icon’s horizontal position within the original image-sprite
8. @bgImg_pxPosition_y background-position Icon’s vertical position within the original image-sprite
9. @bgImg_pxPosition_y_hover background-position Icon’s vertical position on mouse hover state

My LESS mixin bgSpriteFit

/*
* BACKGROUND-IMAGE SPRITE FIT
*
* This mixin resize a background-image via the background-size property.
* Requirements:
* * icon ratio 1:1 (square shape),
* * the first & second var are strings, all the others are digits ONLY,
* * don't put the 'px', only value as digit!
*
* -----------------------------------------------------------------
* DATA EXAMPLE FOR REFERENCE
*
* 1) @bgColor:                     transparent; //default
* 2) @bgImg_url:                   '/img/sprite/btn-50x50-sprite.png';
*
* // icon sizes:
* 3) @spriteIco_pxSize_original:   50;
* 4) @spriteIco_pxRequired_value:  34;
*
* // image-sprite size:
* 5) @imgFile_pxSize_w:            300;
* 6) @imgFile_pxSize_h:            150;
*
* // icon position within the image-sprite:
* 7) @bgImg_pxPosition_x:          200;
* 8) @bgImg_pxPosition_y:          50;
* 9) @bgImg_pxPosition_y_hover:    100;
*
*/
.bgSpriteFit(@bgColor:transparent, @bgImg_url, @spriteIco_pxSize_original, @spriteIco_pxRequired_value, @imgFile_pxSize_w, @imgFile_pxSize_h, @bgImg_pxPosition_x:0, @bgImg_pxPosition_y:0, @bgImg_pxPosition_y_hover:0) when (isnumber(@spriteIco_pxSize_original)) and (isnumber(@spriteIco_pxRequired_value)) and (isstring(@bgImg_url)) and (isnumber(@imgFile_pxSize_w)) and (isnumber(@imgFile_pxSize_h)) and (isnumber(@bgImg_pxPosition_x)) and (isnumber(@bgImg_pxPosition_y)) and (isnumber(@bgImg_pxPosition_y_hover)) {

    // calculate ratio
    @spriteResize_ratio_value:          floor(((100/@spriteIco_pxSize_original)*(@spriteIco_pxRequired_value))); //calcul
    @spriteResize_ratio:                ((@spriteResize_ratio_value)/100); //pourcentage in decimals. ex: 75% = 0.75
    //turn it in a pourcentage string
    @spriteResize:                      ~'@{spriteResize_ratio_value}%'; //pourcentage string interpolation
    // calculate background-size height value
    @imgFile_pxResized_h_value:         floor(((@imgFile_pxSize_h)*(@spriteResize_ratio)));
    //turn it in a pixel string
    @imgFile_pxResized_h:               ~'@{imgFile_pxResized_h_value}px'; //pixel string interpolation
    //turn pxRequired in pixel string
    @spriteIco_pxResized :              ~'@{spriteIco_pxRequired_value}px'; //pixel string interpolation

    // re-calculate background-position after applying resized value
    @resized_bgImg_pxPosition_x_value:  floor(((@bgImg_pxPosition_x)*(@spriteResize_ratio))); //calcul (ex: 250px * 68% = 170)
    @resized_bgImg_pxPosition_y_value:  floor(((@bgImg_pxPosition_y)*(@spriteResize_ratio)));  //calcul (ex: 50px * 68% = 34)
    @resized_bgImg_pxPosition_y_hover_value: floor(((@bgImg_pxPosition_y_hover)*(@spriteResize_ratio)));  //calcul (ex: 100px * 68% = 68)
    //turn them in pixel strings
    @resized_bgImg_pxPosition_x:        ~'@{resized_bgImg_pxPosition_x_value}px'; //pixel string interpolation
    @resized_bgImg_pxPosition_y:        ~'@{resized_bgImg_pxPosition_y_value}px'; //pixel string interpolation
    @resized_bgImg_pxPosition_y_hover:  ~'@{resized_bgImg_pxPosition_y_hover_value}px'; //pixel string interpolation

    /*
     * render
     */
    width: @spriteIco_pxResized;
    height: @spriteIco_pxResized;
    background: @bgColor url(@bgImg_url) no-repeat ~'-@{resized_bgImg_pxPosition_x}' ~'-@{resized_bgImg_pxPosition_y}';
    background-size: auto (@imgFile_pxResized_h);
    // hover state
    &:hover {
        background-position: ~'-@{resized_bgImg_pxPosition_x}' ~'-@{resized_bgImg_pxPosition_y_hover}';
    }
}

The mixin script used within the context of the 34×34 modal close button

.modal-header {
    .close {
        position: absolute;
        opacity: 1;
        right: 40px;
        border: none;

        // my mixin
        .bgSpriteFit(transparent, '/img/sprite/btn-50x50-sprite.png', 50,34, 300,150, 250,50,100);
    }
}

The LESS rendered as CSS

.modal-header .close {
    position: absolute;
    opacity: 1;
    right: 40px;
    border: none;

    /* rendered mixin */
    width: 34px;
    height: 34px;
    background: transparent url('/img/sprite/btn-50x50-sprite.png') no-repeat -170px -34px;
    background-size: auto 102px;
}
.modal-header .close:hover {
    background-position: -170px -68px;
}

Bootstrap burger menu optimized as an icon

Burger menu icons are everywhere in today’s web sites and application interfaces. Good or bad for user experience, this debate is not the subject here.

Design request

I had a design request where desktop interface get a button with both a “Menu” label and a burger menu icon next to it and the mobile interface get a simplified burger menu icon on the far right of the header.

screenshot Ztele.com bootstrap grid desktop VS mobile interface

Bootstrap been very popular these days for building fast responsive HTML layouts it’s not surprising to get burger menu in it’s Glyphs library … D’oupssss! There is NO burger menu available in the Glyphicons Free Edition used by Bootstrap’s Components.

Burger menu from Bootstrap

In fact by default Bootstrap use burger menu only within the Navbar Component when responsive kicks in.

Even worst for designers, it is not a define object (image or graph), you can’t use it out of the Navbar context. It is a pure semantic hack that takes 3 HTML <span> tags wrapped within a <button>. OK there is the <span class="sr-only"> fix but that is really a minimum to pass accessibility QA.

 A web-inspector view of Bootstrap navbar <span.icon-bar>

 

So I have designed a custom burger menu based on Bootstrap’s “icon-bar” LESS code lines.

HTML source code


<button id="main-menu-dropdown" class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" title="Toggle navigation">
    <span class="string">Menu</span>
    <span class="ico ico-burger-menu" title="Menu">
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
    </span>
</button>

The get the burger wrapped within a border you just add the class “border” to <span class="ico ico-burger-menu border">

Layout “Bootstrap style” by default

  1. Default icon layout (whitout border)

    <span class="ico ico-burger-menu">

  2. Icon wrapped within border

    <span class="ico ico-burger-menu border">

Default burger menu layout within a <button>Burger menu layout wrapped within border

LESS code lines


// ico-burger-menu is generated with the glyphicon icon method from bootstrap
@burger-menu-color:                 lighten(@dropdown-caret-color, 50%);
// ico-burger-menu within bootstrap buttons
@burger-menu-default-color:         lighten(@btn-default-color, 20%);
@burger-menu-primary-color:         @btn-primary-color;
// ico-burger-menu hover
@burger-menu-hover-color:           darken(@burger-menu-color, 30%);

/*
 * -------------------
 * Burger Menu
 */
.ico {
    .glyphicon;
    &.ico-burger-menu {
        display: inline-block;
        min-width: 18px;
        max-width: 32px;
        min-height: 18px;
        text-align: center;
        vertical-align: middle;
        background-color: transparent;
        &.border {
            min-width: 20px;
            margin-top: -4px;
            padding: 1px 2px;
            border: 1px solid @burger-menu-color;
            border-radius: 2px;
            // within bootstrap buttons
            .btn-default & {
                border-color: @burger-menu-default-color;
            }
            .btn-primary & {
                border-color: @burger-menu-primary-color;
            }
        }
        // Bars (style from navbar.less)
        .icon-bar {
            display: block;
            min-height: 2px;
            margin: 2px auto;
            border-radius: @border-radius-small;
            background-color: @burger-menu-color;
            // within bootstrap buttons
            .btn-default & {
                background-color: @burger-menu-default-color;
            }
            .btn-primary & {
                background-color: @burger-menu-primary-color;
            }
            .dropdown.open .btn &,
            .btn:hover & {
                background-color: @burger-menu-hover-color;
            }
        }
        &:focus {
            outline: 0;
        }
        &:hover,
        &:focus,
        .btn:hover & {
            text-decoration: none;
        }
        .btn-primary & {
            text-decoration: none;
        }
    }
}

Custom drop-down select tag using only CSS

Graphic illustration of the alternative select drop-down
A 100% CSS method to customize the layout of HTML
 

The required HTML markup

<div class="select">
    <div class="altSelect">
        <select name="dropdownSelect" title="Select an option">
            <option value="-1" class="first">-</option>
            <option value="1">Option 1 </option>
            <option value="2">Option 2 minutes</option>
            <option value="3">Option 3 hours</option>
            <option value="4">Option 4 very long days</option>
            <option value="5">Option 5 weeks</option>
            <option value="6">Option 6 month</option>
            <option value="7">Option 7 years</option>
            <option value="8">Long option 8 lorem ipsum</option>
            <option value="9">Option 9 centiries</option>
        </select>
        <span class="arrow" title="&larr; edit"></span>
    </div>
</div>

The style

select {
	padding-top: .3em;
	padding-bottom: .3em;
}
select option {
	border-bottom: 1px dotted #CCC; /*-moz-*/
	background-color: white;
}
select option:focus {
	outline-width: thin; /*-webkit-*/
}
select option:before {
	content: "\2022\0020"; /*-moz- Adds a bullet before each line*/
}
/*The following style should only target an option where NO values are declared: <option value=""> or <option value="-1">*/
select option[value=""],
select option[value="-1"] {
	font-style: italic;
	opacity: .7;
	background-color: #EEE;
}
select option[value=""]:before,
select option[value="-1"]:before {
    content: "\2193\0020Please select one of these options"; /*-moz- only*/
	color: #EEE;
}
/* html5 requires to set a lang value on the <html> tag. Let's us it for my French Canadian translation example */
select option[value=""]:lang(fr-CA):before,
select option[value="-1"]:lang(fr-CA):before {
    content: "\2193\0020Veuillez choisir parmi ces options"; /*-moz- only*/
}

Support for Internet Explorer

Using this CSS hack is not what I would recommend, but it allowed me to isolate the display on the span ONLY to Microsoft’s browser without requiring the complex management of conditional comments in the customer’s CMS.

div.select .altSelect:hover {
	background-image: none\9; /*ie9Hack : hide the arrow in background*/
}
.select .altSelect span.arrow {
	display: block\9; /*ie9Hack : show the arrow in foreground, over the <select>*/
}
div.select .altSelect:hover span.arrow {
	background-position: right -349px\9; /*ie9Hack*/
}
div.select .altSelect:hover span.arrow:hover {
	background-position: right 1px\9; /*ie9Hack*/
}

Styled option tag layout in IE9

Enhance drop-down options layout for Firefox

Enhance the layout of your dropdown list based on the HTML <select> tag. The following CSS code will NOT affect the layout and usability of your forms in other browsers then Firefox since only Mozilla’s Gecko layout engine seems to support custom styling on the <option> tags.

<div class="select">
    <label for="thisField"><abbr class="required">*</abbr>Select field</label>
    <select id="thisField" name="thisField" required="required" title="Select an option">
        <option value=""></option>
        <option value="01">Option 01</option>
        <option value="02">Option 02 lorem ipsum dolor sit amet</option>
        <option value="03">Option 03</option>
    </select>
    </div><!-- /.altSelect -->
</div><!-- /.select -->

 

select {
	padding-top: .3em;
	padding-bottom: .3em;
}
select option {
	border-bottom: 1px dotted #CCC; /*-moz-*/
	background-color: white;
}
select option:focus {
	outline-width: thin; /*-webkit-*/
}
select option:before {
	content: "\2022\0020"; /*-moz- Adds a bullet before each line*/
}

The following style should only target an option where NO values are declared: <option value=""> or <option value="-1">

select option[value=""],
select option[value="-1"] {
	font-style: italic;
	opacity: .7;
	background-color: #EEE;
}
select option[value=""]:before,
select option[value="-1"]:before {
    content: "\2193\0020Please select one of these options"; /*-moz- only*/
	color: #EEE;
}

HTML5 requires to set a lang value on the <html> tag. Let’s use it for my French Canadian translation example.

select option[value=""]:lang(fr-CA):before,
select option[value="-1"]:lang(fr-CA):before {
    content: "\2193\0020Veuillez choisir parmi ces options"; /*-moz- only*/
}

End result examples

Here are screen capture images from 3 major browsers.

Mozilla Firefox

Styled option tag layout in Mozilla Firefox browser

Google Chrome

Styled option tag layout in Google Chrome browser

Microsoft Internet Explorer 9

Styled option tag layout in Microsoft IE9 browser

Styling from Quotation marks to Guillemets & Comillas

Today’s CMS (Content Management System) rely on web text editor APIs, like CKEditor or TinyMCE, to generate, edit and style their post’s contents based on HTML tags. But if those HTML tags are not style properly site editors can generate more bad than good by generating typos in their text.

Inline quotation marks from CKEditor

Here is my handy CSS method to style an HTML quote <q> tag that meets the 3 main North-American languages (culture).

This method is based on the HTML5 language declaration required on the <html> tag.

<!doctype html>
<html lang="fr-CA">
<head>
...

First the language by default; English

English quotation marks characters are double-quotes .

q {
	&:before {
		content: '\201c';
	}
	&:after {
		content: '\201d';
	}
}

Then cascading to the French and Spanish version

For both French and Spanish language, quotation marks characters are Guillemets, refered as Comillas in Spanish. Despite the different syntaxes both use the opening and closing guillemets « … » characters.

To simplify my code and since I never integrated an HTML page for a Spanish customer, I decided that both FR and EN version will benefit of the white space character (unicode \0020) within the <q> tag content.

q {
	// first english
	&:before {
		content: '\201c';
	}
	&:after {
		content: '\201d';
	}
	// then Spanish and French
	&:lang(es),
	&:lang(fr) {
		&:before {
			content: '\00ab\0020';
		}
		&:after {
			content: '\0020\00bb';
		}
	}
}

Why use Apostrophe, not Single Quote as left single quotation mark in text

While we are in the character subject, I encourage writers, editor and programmers to use the (real) curved apostrophe in text content instead of the strait single quote from your computer keyboard device. I know this practice is time consuming because the strait single quote key is the only character available on our 7-bit encoded (default) ASCII keyboards. But you get two benefits at once when you make the effort of copy & pasting the real curved apostrophe quotation mark in your document:

Curved quotation mark from serif typography layout used as apostrophe in traditional printed books
Curved quotation mark used in traditional printed books.
Strait quotation mark from non-serif typography layout from computer’s 7-bit ASCII keyboards
Strait quotation mark from computer’s keyboards
  1. Curved apostrophe typography IS the proper character used in written languages. If you open a book printed with a serif font type you usually see curved apostrophe not strait ones. The strait single quote is a mathematical sign to be used with numbers not letters.
  2. Curved apostrophe does NOT break a script when used within a string of JavaScript, PHP or any other programming language. So programmers, no need to pollute your code with all those not human readable escaping backslash in your strings.

Unicode references

You can find the complete list of unicode characters to use in your CSS go on Andrew Marcuse’s website FileFormat.info or on the American Standard Code for Information Interchange for ASCII encoded characters.

  • \201c = – ASCII code 34
  • \201d = – ASCII code 34
  • \00ab = « – ASCII code 174
  • \00bb = » – ASCII code 175
  • \0020 = space – ASCII code 32
  • \02bc = – ASCII code 39

Clean inner transparent border in CSS

Pure CSS 2.1, no image sprite in there

Quand j’ai reçu cette maquette du designer je croyais devoir utiliser une énorme image sprite qui contiendrait un contour rouge de 10 pixels, dont la couche (Photoshop layer) serait à 50% de transparence, pour chaque dimensions d’image utilisés dans le site.

Puis j’ai trouver la méthode CSS “:before” & “:after” proposée par Remy Sharp (VagrantRadio) en réponse à la question “Inner Border in CSS?“. Malgré que cette technique ne soit pas supportée par les anciens navigateurs de Internet Explorer (IE8 et moins), puisqu’il ne s’agit que d’un élément graphique, de savoir que c’est supporté et fonctionnel dans IE9, IE10, Google Chrome, Safari et Firefox me suffit amplement pour ce client.

The HTML source

<a class="picture" title="db_ARTICLE_TITLE" href="#">
 <span class="flag">Flag label</span>
 <img src="image/picture_182x102.jpg" alt="db_IMG_DESC" />
</a>

The CSS code

a.picture{
	position:relative;
	width:182px;
	height:102px;
}
.picture:before{
	content:'';
	position:absolute;
	left:0;
	top:0;
	width:162px;
	height:82px;
	border:10px solid transparent;
}
.picture:hover:before{
	border-color:rgba(215,32,23,.5);
}

Références: