This weekend I’ve had some spare time and I’ve used it to take a proper look at AngularJS. I’ve used Backbone a lot and find myself defaulting to it as soon as a JavaScript application gets complicated. I realised that I was ignoring everything else because I already know Backbone and that’s not a good place to be. Time to jump into something new.
When all you have is a hammer…
Initially I downloaded the Angular source and launched into trying to build something simple with it but I found this a really frustrating experience. I consider myself a pretty competent JS developer but nothing really worked and the concepts didn’t click. Making me feel stupid is a quick way to turn me off of something.
I took a step back and realised that I was trying so hard to shoehorn what I knew about MVC from Rails and Backbone into the app that I wasn’t letting myself see the bigger picture. I spent an hour watching and coding along with a tutorial video and by the end felt I really understood the basics. Just by investing a small amount of time into learning the fundamentals I’m now really productive with Angular. Making me feel smart is a great way to keep me interested in something!
In less than a day I’ve come to love the declarative nature of the code I’m writing. Everything is so terse and I’m spending zero time writing what I would now consider boilerplate DOM manipulation or event binding code. This is really exciting coming from a world of manual template rendering and zombie events and I love not having to think about that stuff.
Conventions
I listened to an interview with Chad Fowler this week. He spoke about how Rails is not necessarily the best web framework but it offers such a strong set of conventions and has such a strong community that it really allows you to forget about hooking an app together and just focus on the product you’re trying to build.
I feel like Angular offers the same level of convention and I’m really looking forward to getting stuck into a bigger project with it. I don’t want to spend my time writing glue code, clearing up old views, manually re-rendering templates on data change or writing form input handlers. I know there are libraries to handle these things in Backbone, but I also don’t want to be depending on 20 plugins just to get a functioning app.
Step back
These are just my initial thoughts after playing with the framework for a day and maybe I’ll change my mind after I’ve used it more extensively but right now I’m loving Angular and can’t see myself choosing Backbone the next time I start a big front end JS project.
If you’re looking to get started with Angular I’d recommend you check out the following resources:
Please enable JavaScript to view comments.
- Dan Whalin’s video tutorial really helped me to get the fundamentals of Angular.
- egghead.io is a great collection of screencasts covering some more specific cases.
- The AngularJS project homepage (although the docs are not that beginner friendly).
Hundreds of web businesses use Segment.io to simplify their analytics setup. Send data from Javascript, Ruby, Python, Java or PHP to Google Analytics, Mixpanel, KISSmetrics, Marketo, Pardot, and many others.
Parameter Type Description width string Controls the width style attribute of the Select2 container div. The following values are supported:
- off
- No width attribute will be set. Keep in mind that the container div copies classes from the source element so setting the width attribute may not always be necessary.
- element
- Uses javascript to calculate the width of the source element.
- copy
- Copies the value of the width style attribute set on the source element
- resolve
- First attempts to copy than falls back on element
- other values
- if the width attribute contains a function it will be avaluated, otherwise the value is used verbatim
minimumInputLength int Number of characters necessary to start a search maximumInputLength int Maximum number of characters that can be entered for an input minimumResultsForSearch int The minimum number of results that must be initially (after opening the dropdown for the first time) populated in order to keep the search field. This is useful for cases where local data is used with just a few results, in which case the search box is not very useful and wastes screen space.
Only applies to single-value select boxes
maximumSelectionSize int/function The maximum number of items that can be selected in a multi-select control. If this number is less than 1 selection is not limited.
Once the number of selected items reaches the maximum specified the contents of the dropdown will be populated by the formatSelectionTooBig function
placeholder string Initial value that is selected if no other selection is made.
The placeholder can also be specified as a data-placeholder attribute on the select or input element that Select2 is attached to.
Note that because browsers assume the first option element is selected in non-multi-value select boxes an empty first option element must be provided (<option></option>) for the placeholder to work.
separator string Separator character or string used to delimit ids in value attribute of the multi-valued selects. The default delimiter is the , character.
allowClear boolean Whether or not a clear button is displayed when the select box has a selection. The button, when clicked, resets the value of the select box back to the placeholder, thus this option is only available when the placeholder is specified.
This option only works when the placeholder is specified
When attached to a select an option with an empty value must be provided. This is the option that will be selected when the button is pressed since a select box requires at least one selection option.
Also, note that this option only works with non-multi-value based selects because multi-value selects always provide such a button for every selected option.
multiple boolean Whether or not Select2 allows selection of multiple values.
When Select2 is attached to a select element this value will be ignored and select's multiple attribute will be used instead.
closeOnSelect boolean If set to false the dropdown is not closed after a selection is made, allowing for rapid selection of multiple items. By default this option is set to true.
Only applies when configured in multi-select mode.
openOnEnter boolean If set to true the dropdown is opened when the user presses the enter key and Select2 is closed. By default this option is enabled.
id function Function used to get the id from the choice object or a string representing the key under which the id is stored. id(object)The default implementation expects the object to have a id property that is returned.
Parameter Type Description object object A choice object <returns> string the id of the object matcher function Used to determine whether or not the search term matches an option when a built-in query function is used. The built in query function is used when Select2 is attached to a select, or the local or tags helpers are used. matcher(term, text, option)The default implementation is case insensitive and matches anywhere in the term: function(term, text) { return text.toUpperCase().indexOf(term.toUpperCase())>=0; }
Parameter Type Description term string search term text string text of the option being matched option jquery object the option element we are trying to match. Only given when attached to select. Can be used to match against custom attributes on the option tag in addition to matching on the option's text. <returns> boolean true if search term matches the text, or false otherwise sortResults function Used to sort the results list for searching right before display. Useful for sorting matches by relevance to the user's search term. sortResults(results, container, query)Defaults to no sorting: function(results, container, query) { return results; }
object object One of the result objects returned from the query function container jQuery object jQuery wrapper of the node that should contain the representation of the result query object The query object used to request this set of results <returns> object A results object. formatSelection function Function used to render the current selection. formatSelection(object, container)
Parameter Type Description object object The selected result object returned from the query function container jQuery object jQuery wrapper of the node to which the selection should be appended <returns> string (optional) Html string, a DOM element, or a jQuery object that renders the selection The default implementation expects the object to have a text property that is returned.
The implementation may choose to append elements directly to the provided container object, or return a single value and have it automatically appended
When attached to a select the original <option> (or <optgroup>) element is accessible inside the specified function through the property item.element:
format(item) { var originalOption = item.element; return item.text }formatResult function Function used to render a result that the user can select. formatResult(object, container, query)
Parameter Type Description object object One of the result objects returned from the query function container jQuery object jQuery wrapper of the node that should contain the representation of the result query object The query object used to request this set of results escapeMarkup function Function used to escape markup in results. If you do not expect to render custom markup you should pass your text through this function to escape any markup that may have been accidentally returned. This function is configurable in options of select2. <returns> string (optional) Html string, a DOM element, or a jQuery object that represents the result The default implementation expects the object to have a text property that is returned.
The implementation may choose to append elements directly to the provided container object, or return a single value and have it automatically appended
When attached to a select the original <option> (or <optgroup>) element is accessible inside the specified function through the property item.element:
format(item) { var originalOption = item.element; return item.text }formatResultCssClass function Function used to add css classes to result elements formatResultCssClass(object)
Parameter Type Description object object One of the result objects returned from the query function <returns> string (optional) String containing css class names separated by a space By default when attached to a select css classes from options will be automatically copied
formatNoMatches function Function used to render the "No matches" message formatNoMatches(term)
Parameter Type Description term string Search string entered by user <returns> string Message html formatSearching function Function used to render the "Searching..." message that is displayed while search is in progress formatSearching()
Parameter Type Description <returns> string Message html or null/undefined to disable the message formatInputTooShort function Function used to render the "Search input too short" message formatInputTooShort(term, minLength)
Parameter Type Description term string Search string entered by user minLength int Minimum required term length <returns> string Message html formatSelectionTooBig function Function used to render the "You cannot select any more choices" message formatSelectionTooBig(maxSize)
Parameter Type Description maxSize string The maximum specified size of the selection <returns> string Message html createSearchChoice function Creates a new selectable choice from user's search term. Allows creation of choices not available via the query function. Useful when the user can create choices on the fly, eg for the 'tagging' usecase. createSearchChoice(term)If the function returns undefined or null no choice will be created. If a new choice is created it is displayed first in the selection list so that user may select it by simply pressing enter.
Parameter Type Description term string Search string entered by user <returns> object (optional) Object representing the new choice. Must at least contain an id attribute. When used in combination with input[type=hidden] tag care must be taken to sanitize the id attribute of the choice object, especially stripping , as it is used as a value separator
initSelection function Called when Select2 is created to allow the user to initialize the selection based on the value of the element select2 is attached to. Essentially this is an id->object mapping function.
initSelection(element, callback)
Parameter Type Description element jQuery array element Select2 is attached to callback function callback function that should be called with the data which is either an object in case of a single select or an array of objects in case of multi-select This function will only be called when there is initial input to be processed.
Here is an example implementation used for tags. Tags are the simplest form of data where the id is also the text:$("#tags").select2({ initSelection : function (element, callback) { var data = []; $(element.val().split(",")).each(function () { data.push({id: this, text: this}); }); callback(data); } }); // Or for single select elements: $("#select").select2({ initSelection : function (element, callback) { var data = {id: element.val(), text: element.val()}; callback(data); } });tokenizer function A tokenizer function can process the input typed into the search field after every keystroke and extract and select choices. This is useful, for example, in tagging scenarios where the user can create tags quickly by separating them with a comma or a space instead of pressing enter. Tokenizer only applies to multi-selects
tokenizer(input, selection, selectCallback, opts)The default tokenizer will only be used if the tokenSeparators and createSearchChoice options are specified. The default tokenizer will split the string using any separator in tokenSeparators and will create and select choice objects using createSearhChoice option. It will also ignore duplicates, silently swallowing those tokens.
Parameter Type Description input string The text entered into the search field so far selection array Array of objects representing the current selection. Useful if tokenizer needs to filter out duplicates. selectCallback function Callback that can be used to add objects to the selection opts object Options with which Select2 was initialized. Useful if tokenizer needs to access some properties in the options. <returns> string (optional) Returns the string to which the input of the search field should be set to. Usually this is the remainder, of any, of the string after the tokens have been stripped. If undefined or null is returned the input of the search field is unchanged. tokenSeparators array An array of strings that define token separators for the default tokenizer function. By default, this option is set to an empty array which means tokenization using the default tokenizer is disabled. Usually it is sensible to set this option to a value similar to [',', ' '] query function Function used to query results for the search term. query(options)
Parameter Type Description options.term string Search string entered by user options.page int 1-based page number tracked by Select2 for use with infinite scrolling of results options.context object An object that persists across the lifecycle of queries for the same search term (the query to retrieve the initial results, and subsequent queries to retrieve more result pages for the same search term). When this function is first called for a new search term this object will be null. The user may choose to set any object in the results.context field - this object will then be used as the context parameter for all calls to the query method that will load more search results for the initial search term. The object will be reset back to null when a new search term is queried. This feature is useful when a page number is not easily mapped against the server side paging mechanism. For example, some server side paging mechanism may return a "continuation token" that needs to be passed back to them in order to retrieve the next page of search results. options.callback function Callback function that should be called with the result object. The result object:
Parameter Type Description result.results [object] Array of result objects. The default renderers expect objects with id and text keys. The id attribute is required, even if custom renderers are used. The object may also contain a childrenkey if hierarchical data is displayed. result.more boolean trueif more results are available for the current search term results.context object A user-defined object that should be made available as the context parameter to the query function on subsequent queries to load more result pages for the same search term. See the description of options.context parameter. In order for this function to work Select2 should be attached to a input type='hidden' tag instead of a select.
Example Data
{ more: false, results: [ { id: "CA", text: "California" }, { id: "AL", text: "Alabama" } ] }
Example Hierarchical Data
{ more: false, results: [ { text: "Western", children: [ { id: "CA", text: "California" }, { id: "AZ", text: "Arizona" } ] }, { text: "Eastern", children: [ { id: "FL", text: "Florida" } ] } ] }ajax object Options for the built in ajax query function. This object acts as a shortcut for having to manually write a function that performs ajax requests. The built-in function supports more advanced features such as throttling and dropping out-of-order responses.
Parameter Type Description transport function Function that will be used to perform the ajax request. Must be parameter-compatible with $.ajax. Defaults to $.ajax if not specified. Allows the use of various ajax wrapper libraries such as: AjaxManager. url string/function String containing the ajax url or a function that returns such a string. dataType string Data type for the request. ajax, jsonp, other formats supported by jquery quietMillis int Number of milliseconds to wait for the user to stop typing before issuing the ajax request data function Function to generate query parameters for the ajax request. data(term, page)
Parameter Type Description term string Search term page int 1-based page number tracked by Select2 for use with infinite scrolling of results context object See options.context parameter to the query function above. <returns> object Object containing url paramters results function Function used to build the query results object from the ajax response results(data, page)
Parameter Type Description data object Retrieved data page int Page number that was passed into the data function above context object See options.context parameter to the query function above. <returns> object Results object. See "options.callback" in the "query" function for format. In order for this function to work Select2 should be attached to a input type='hidden' tag instead of a select.
data array/object Options for the built in query function that works with arrays. If this element contains an array, each element in the array must contain id and text keys
Alternatively, this element can be specified as an object in which results key must contain the data as an array and a text key can either be the name of the key in data items that contains text or a function that retrieves the text given a data element from the array
tags array/function Puts Select2 into 'tagging'mode where the user can add new choices and pre-existing tags are provided via this options attribute which is either an array or a function that returns an array of objects or strings. If strings are used instead of objects they will be converted into an object that has an id and text attribute equal to the value of the string. containerCss function/object Inline css that will be added to select2's container. Either an object containing css property/value key pairs or a function that returns such an object. containerCssClass function/string Css class that will be added to select2's container tag dropdownCss function/object Inline css that will be added to select2's dropdown container. Either an object containing css property/value key pairs or a function that returns such an object. dropdownCssClass function/string Css class that will be added to select2's dropdown container escapeMarkup function String escapeMarkup(String markup) Function used to post-process markup returned from formatter functions. By default this function escapes html entities to prevent javascript injection.
selectOnBlur boolean Set to true if you want Select2 to select the currently highlighted option when it is blurred
loadMorePadding integer Defines how many results need to be below the fold before the next page is loaded. The default value is 0 which means the result list needs to be scrolled all the way to the bottom for the next page of results to be loaded. This option can be used to trigger the load sooner, possibly resulting in a smoother user experience. Gets or sets the selection. If the value parameter is not specified, the id attribute of the currently selected element is returned. If the value parameter is specified it will become the current selection.
val method invoked on a single-select with an unset value will return "", while a val method invoked on an empty multi-select will return []
Notice that in order to use this method you must define the initSelection function in the options so Select2 knows how to transform the id of the object you pass in val() to the full object it needs to render selection. If you are attaching to a select element this function is already provided for you.
Gets or sets the selection. Analogous to val method, but works with objects instead of ids.
data method invoked on a single-select with an unset value will return null, while a data method invoked on an empty multi-select will return []
Reverts changes to DOM done by Select2. Any selection done via Select2 will be preserved.
Disables Select2. During this mode the user is not allowed to manipulate the selection.
Enables Select2.
Retrieves the main container element that wraps all of DOM added by Select2 Example: console.log($("#tags").select2("container"));
Notifies Select2 that a drag and drop sorting operation has started. Select2 will hide all non-selection list items such as the search container, etc. Example: $("#tags").select2("onSortStart");
Notifies Select2 that a drag and drop sorting operation has finished. Select2 will re-display any elements previously hidden and update the selection of the element it is attached to. Example: $("#tags").select2("onSortEnd");
Support The Changelog. Become a member!Special thanks to Paul Irish for the hat tip and sharing this tweet:
Sublime Web Inspector: massive JS integration between Sublime & Chrome DevTools sokolovstas.github.com/SublimeWebInsp… (skip to 3:25) Whoa /via @addyosmani
— Paul Irish (@paul_irish) March 17, 2013For those who haven’t yet gone the way of text mode with Vim, you likey hack with Sublime Text (especially if you’ve given up on TextMate like the rest of us).
Stanislav just released some pretty massive JavaScript integration between Sublime Text and Chrome DevTools with Sublime Web Inspector that lets you debug JavaScript inside the Sublime Text editor.
Follow Paul’s suggestion to watch the video and also check out the readme on GitHub for installation details.
JavaScript Database is a collection of the best clientside javascripts for modern web development
ClearLessA reuseable collection of carefully-considered Less mixins, or YALML (Yet Another Less Mixin Library).
The core tenets of this mixin library are to avoid output bloat wherever possible (via duplicated properties etc) and to provide flexibile, configurable solutions to the problems that are addressed by the library (i.e. by using Modernizr classes, browser hacks or not, etc). The aim is to give the author the benefits of reusable shortcuts without obliterating personal style and generating bloated stylesheets.
Before diving in it is strongly recommended that you peruse the notes on usage and best practices at the end of this document, which gives an overview of how you can take full advantage of ClearLess without compromising the generated CSS output.
Usage
Simply @import the mixins/all.less file into the top of your main Less file, and then (optionally) override any of the settings as described below.
The mixins/all.less file itself simply imports all the individual Less files into one place. The mixins and settings for these individual files are documented under in their various groupings below:
Global settings
ClearLess defines a few settings that affect the output of some of the mixins. These are just Less variables, and have their default values defined in mixins/settings.less.
To override the defaults, simply redefine them after importing the mixins:
@import "mixins/all"; @using-modernizr: true; @base-font-size: 14;The following global settings are defined:
SETTING: @using-modernizr
If using Modernizr, some of the mixins will swap to using the Modernizr-generated classes to determine support for various features and thus what CSS to generate (see the icon/sprites mixins for an example). Set this to true to enable this behaviour.
Modernizr feature tests currently used (if using a custom Modernizr build):
- Generated Content (.generatedcontent)
SETTING: @using-ieclasses
If using H5BP-style conditional comments to add IE-indentifying classes to the HTML element, some mixins will use them to patch IE support where there are known issues. If this is set to false then these mixins will fall back to hacks like the star hack to provide this support instead.
SETTING: @disable-filters
Whether or not certain mixins (like the gradient mixins) should generate IE fallbacks using the MS proprietary filter property or not. Disabled by default due to performance issues with filter props.
Other section-specific settings are documented alongside their mixins below.
Resets
Convinience mixins that should be used outside of element selectors as a quick way to generate popular reset stylesheet contents.
.reset;
Outputs styles from the 'Meyer Reset'.
.normalize;
Outputs styles from normalize.css.
Shortcuts & Helpers
These are the most basic mixins. Shortcuts typically provide a quick way to generate all the required vendor-prefixed versions of a property, and/or give a more manageable syntax for defining things like CSS gradients. Helpers are mixins that typically generate boilerplate code for common use cases, such as display: inline-block; statements with IE7 fixes, or image replacement code.
.border-radius()
Generates a box-radius property with the appropriate vendor prefixes.
.border-radius( <@radius> );
- @radius: (Optional) Radius to round all corners to. Defaults to 5px.
/* Usage: */ .example1 { .border-radius( 5px ); } .example2 { .border-radius( 5px 7px 5px 10px ); } /* Example output: */ .example1 { -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } .example2 { -webkit-border-radius: 5px 7px 5px 10px; -moz-border-radius: 5px 7px 5px 10px; border-radius: 5px 7px 5px 10px; }.box-sizing()
Generates a box-sizing property with the appropriate vendor prefixes.
.box-sizing( [<@type>] );
- @type: (Optional) box-sizing property value. Defaults to border-box.
/* Usage: */ .example { .box-sizing( border-box ); } /* Example output: */ .example { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; }.box-shadow()
Generates a box-shadow property with the appropriate vendor prefixes.
.box-shadow( [<@shadow>] );
- @shadow: (Optional) box-shadow property value. Defaults to 1px 1px 2px rgba(0,0,0,0.25).
/* Usage: */ .example { .box-shadow( 2px 2px 3px #999 ); } /* Example output: */ .example { -webkit-box-shadow: 2px 2px 3px #999; -moz-box-shadow: 2px 2px 3px #999; box-shadow: 2px 2px 3px #999; }.filter()
Generates a filter property with the appropriate vendor prefixes.
- @filter: (Optional) filter property value. Defaults to grayscale(100%).
/* Usage: */ .example { .filter( sepia(50%) ); } /* Example output: */ .example { -webkit-filter: sepia(50%); -moz-filter: sepia(50%); -ms-filter: sepia(50%); -o-filter: sepia(50%); filter: sepia(50%); }.transition()
Generates a transition property with the appropriate vendor prefixes.
.transition( <@transition> );
- @transition: transition property value.
/* Usage: */ .example { .transition( all .2s ease-in-out ); } /* Example output: */ .example { -webkit-transition: all .2s ease-in-out; -moz-transition: all .2s ease-in-out; transition: all .2s ease-in-out; }.rotate()
Generates a transform property with a rotation value and with the appropriate vendor prefixes.
- @rotation: rotation value.
/* Usage: */ .example { .rotate( 2.5deg ); } /* Example output: */ .example { -webkit-transform: rotate(2.5deg); -moz-transform: rotate(2.5deg); -o-transform: rotate(2.5deg); transform: rotate(2.5deg); }.placeholder()
Generates pseudo-selector rules to globally change the colour of placeholder text for inputs. Use outside of element selectors.
.placeholder( [<@color>] );
- @color: (Optional) colour value. Defaults to #DDD
/* Usage: */ .placeholder( #F00 ); /* Example output: */ :-moz-placeholder { color: #F00; } ::-webkit-input-placeholder { color: #F00; }#gradient > .vertical()
Uses CSS3 gradient values to generate vertical background gradients with appropriate vendor prefixed implementations. Output varies according to the value of the @disable-filters setting.
#gradient > .vertical( <@start-color>, <@end-color> );
- @start-color: Colour value for the upper start colour.
- @end-color: Colour value for the bottom end colour.
/* Usage: */ .example { #gradient > .vertical( #F00, #555); } /* Example output: */ .example { background-color: #555; background-repeat: repeat-x; background-image: -khtml-gradient(linear, left top, left bottom, from(#F00), to(#555)); background-image: -moz-linear-gradient(#F00, #555); background-image: -ms-linear-gradient(#F00, #555); background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #F00), color-stop(100%, #555)); background-image: -webkit-linear-gradient(#F00, #555); background-image: -o-linear-gradient(#F00, #555); background-image: -ms-linear-gradient(top, #F00 0%, #555 100%); }#gradient > .horizontal()
Uses CSS3 gradient values to generate horizontal background gradients with appropriate vendor prefixed implementations. Output varies according to the value of the @disable-filters setting.
#gradient > .horizontal( <@start-color>, <@end-color> );
- @start-color: Colour value for the left start colour.
- @end-color: Colour value for the right end colour.
/* Usage: */ .example { #gradient > .horizontal( #F00, #555); } /* Example output: */ .example { background-color: #555; background-repeat: repeat-x; background-image: -khtml-gradient(linear, left top, right top, from(#F00), to(#555)); background-image: -moz-linear-gradient(left, #F00, #555); background-image: -ms-linear-gradient(left, #F00, #555); background-image: -webkit-gradient(linear, left top, right top, color-stop(0%, #F00), color-stop(100%, #555)); background-image: -webkit-linear-gradient(left, #F00, #555); background-image: -o-linear-gradient(left, #F00, #555); background-image: -ms-linear-gradient(left, #F00 0%, #555 100%); background-image: linear-gradient(left, #F00, #555); }.clearfix()
Generates the appropriate properies to apply the micro-clearfix hack to the element. Output varies according to the value of the @using-ieclasses setting.
/* Usage: */ .example { .clearfix(); } /* Example output: */ .example:before, .example:after { content: ""; display: table; } .example:after { clear: both; } .ie6 .example, .ie7 .example { zoom: 1; }.inline-block()
Helper to generate the inline-block display property plus fixes for IE7. Output varies according to the value of the @using-ieclasses setting.
/* Usage: */ .example { .inline-block(); } /* Example output: */ .example { display: inline-block } .ie6 .example, .ie7 .example { display: inline; zoom: 1; }.ir()
Generates text-removing properties for use in image replacement. Does not specify the background image (or it's positioning) itself - this needs to be specified manually (or use one of the sprite mixins, if appropriate).
/* Usage: */ .example { .ir(); background-image: url('/text.png'); } /* Example output: */ .example { border: 0; font: 0/0 a; text-shadow: none; color: transparent; background-color: transparent; background-image: url('/text.png'); }.hidden()
Hides content from the page. Uses !important to override inline-styles added by JS.
/* Usage: */ .example { .hidden(); } /* Example output: */ .example { display: none !important; visibility: hidden; }.visually-hidden()
Hides content visually, but leaves is accessible to screenreaders. Also generates helper classes to allow the element to be focusable when navigated to via the keyboard.
/* Usage: */ .example { .visually-hidden(); } /* Example output: */ .example { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } .example.focusable:active, .example.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }.size()
Shortcut for generating width and height properties.
- @size: Value to use for the height and width properties.
.size( <@width>, <@height> );
- @width: Value to use for the width property
- @height: Value to use for the height property
/* Usage: */ .example1 { .size( 30px ); } .example2 { .size( 20px, 70px ); } /* Example output: */ .example1 { width: 30px; height: 30px; } .example2 { width: 20px; height: 70px; }Typography
SETTING: @base-font-size
@base-font-size: 16;
A variable to sets the base font-size (in pixels) that is used as the default in certain calculations (such as in the pixels to rems conversion helper). Units should be omited.
Note that this doesn't stop you doing your base body font size calculations/definitions any way you please - this should just be set to the result of that. For instance, if you set your base font size to 62.5% then just set the @base-font-size value to 10.
.font-size-ems()
Generates a font-size property with the pixel value converted to ems.
.font-size-ems( <@px-size> [, <@context-px-size>] );
- @px-size: Font size (in pixels) to convert to ems.
- @context-px-size: (Optional) The font size (in pixels) of the current context. Defaults to the value of @base-font-size if not specified.
/* Usage: */ p { .font-size-ems( 12 ); } /* Example output: */ p { font-size: 0.75em; }.font-size-rems()
Generates a font-size property with the pixel value converted to rems and provides a pixel based fallback for browsers that do not support rem units.
.font-size-rems( <@px-size> );
- @px-size: Font size (in pixels) to convert to rems.
/* Usage: */ p { .font-size-rems( 12 ); } /* Example output: */ p { font-size: 12px; font-size: 0.75rem; }.font-face()
Generates a font-face declaration block. Should be used outside of any element selectors. Note that this assumes that you have generated EOT, WOFF and TTF versions of the font, and that they all live in the same location, with the same filename (apart from the extension.
Future versions of this may include workarounds to make this more flexible.
.font-face( <@font-family>, <@font-path>, <@font-weight>, <@font-style>, <@include-svg> );
- @font-family: The name to give the font-family
- @font-path: The path/URL to the font, including the font name but with the file extension removed
- @font-weight: (Optional) Value for the font-weight property. Defaults to normal
- @font-style: (Optional) Value for the font-style property. Defaults to normal
- @include-svg: (Optional) Value for the font-weight property. Defaults to normal
/* Usage: */ .font-face( 'MyNiceFontBold', '/fonts/my_nice_font', bold ); /* Example output: */ @font-face { font-family: 'MyNiceFontBold'; src: url('/fonts/my_nice_font.eot'); src: url('/fonts/my_nice_font.eot?#iefix') format('embedded-opentype'), url('/fonts/my_nice_font.woff') format('woff'), url('/fonts/my_nice_font.ttf') format('truetype'); font-weight: bold; font-style: normal; }.word-wrap()
Implement word-wrapping for text within the element, with hyphenation where supported. See http://blog.kenneth.io/blog/2012/03/04/word-wrapping-hypernation-using-css/ for details.
/* Usage: */ .example { .word-wrap(); } /* Example output: */ .example { -ms-word-break: break-all; word-break: break-all; word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; }Sprites
The sprite mixins give you an easy way to use sprited background images. It assumes the use of a single sprite image with individual images placed on a regular grid. These are defined as settings variables, but can also be supplied on a per-mixin basis.
SETTING: @sprite-image
@sprite-image: '/images/example-sprite.png';The default image to use for the sprite mixins. Can be a Base64 encoded data-uri.
SETTING: @sprite-grid
The size of the grid (in pixels) that the individal images are placed on.
.sprite()
The most basic sprite mixin. Outputs all the required properties to generate your sprited image.
.sprite(<@x>, <@y>[, <@sprite-image>[, <@sprite-grid>]]);
- @x: The x coordinate of the desired image on the grid.
- @y: The y coordinate of the desired image on the grid.
- @sprite-image: (Optional) The sprite image to use. Defaults to the globally defined @sprite-image value.
- @sprite-grid: (Optional) The grid size used in the sprite. Defaults to the globally defined @sprite-grid value.
/* Usage: */ .example { .sprite( 2, 3 ); } /* Example output: */ .example { background-image: url('/images/example-sprite.png'); background-repeat: no-repeat; background-position: -100px -150px; }.sprite-sized()
The same as the .sprite() mixin above, but allows you to specify the height and width to constrain the element by.
.sprite(<@x>, <@y>, <@width>, <@height>[, <@sprite-image>[, <@sprite-grid>]]);
- @x: The x coordinate of the desired image on the grid.
- @y: The y coordinate of the desired image on the grid.
- @width: The width of the image.
- @height: The height of the image.
- @sprite-image: (Optional) The sprite image to use. Defaults to the globally defined @sprite-image value.
- @sprite-grid: (Optional) The grid size used in the sprite. Defaults to the globally defined @sprite-grid value.
.sprite(<@x>, <@y>, <@size>[, <@sprite-image>[, <@sprite-grid>]]);
- @x: The x coordinate of the desired image on the grid.
- @y: The y coordinate of the desired image on the grid.
- @size: The height and width of the image (for 'square' images).
- @sprite-image: (Optional) The sprite image to use. Defaults to the globally defined @sprite-image value.
- @sprite-grid: (Optional) The grid size used in the sprite. Defaults to the globally defined @sprite-grid value.
/* Usage: */ .example { .sprite-sized( 2, 3, 16px, 32px ); } .example2 { .sprite-sized( 2, 3, 16px ); } /* Example output: */ .example { background-image: url('/images/example-sprite.png'); background-repeat: no-repeat; background-position: -100px -150px; width: 16px; height: 32px; } .example2 { background-image: url('/images/example-sprite.png'); background-repeat: no-repeat; background-position: -100px -150px; width: 16px; height: 16px; }.sprite-ir()
Augments the .sprite-sized() mixin to include image replacement properties as defined in the .ir() mixin.
.sprite-ir(<@x>, <@y>, <@width>, <@height>[, <@sprite-image>[, <@sprite-grid>]]);
- @x: The x coordinate of the desired image on the grid.
- @y: The y coordinate of the desired image on the grid.
- @width: The width of the image.
- @height: The height of the image.
- @sprite-image: (Optional) The sprite image to use. Defaults to the globally defined @sprite-image value.
- @sprite-grid: (Optional) The grid size used in the sprite. Defaults to the globally defined @sprite-grid value.
.sprite-ir(<@x>, <@y>, <@size>[, <@sprite-image>[, <@sprite-grid>]]);
- @x: The x coordinate of the desired image on the grid.
- @y: The y coordinate of the desired image on the grid.
- @size: The height and width of the image (for 'square' images).
- @sprite-image: (Optional) The sprite image to use. Defaults to the globally defined @sprite-image value.
- @sprite-grid: (Optional) The grid size used in the sprite. Defaults to the globally defined @sprite-grid value.
/* Usage: */ .example { .sprite-ir( 2, 3, 16px, 32px ); } .example2 { .sprite-ir( 2, 3, 16px ); } /* Example output: */ .example { background-image: url('/images/example-sprite.png'); background-repeat: no-repeat; background-position: -100px -150px; width: 16px; height: 32px; border: 0; font: 0/0 a; text-shadow: none; color: transparent; background-color: transparent; } .example2 { background-image: url('/images/example-sprite.png'); background-repeat: no-repeat; background-position: -100px -150px; width: 16px; height: 16px; border: 0; font: 0/0 a; text-shadow: none; color: transparent; background-color: transparent; }.sprite-image()
A partial mixin. Just sets the background-image property to the @sprite-image. Useful in combination with the other sprite partial mixins below.
.sprite-image([<@sprite-image>]);
- @sprite-image: (Optional) The sprite image to use. Defaults to the globally defined @sprite-image value.
/* Usage: */ .example { .sprite-image(); } /* Example output: */ .example { background-image: url('/images/example-sprite.png'); background-repeat: no-repeat; }.sprite-pos()
A partial mixin. Generates the correct background-position property according to the position and grid. Useful in combination with the other sprite partial mixins.
- @x: The x coordinate of the desired image on the grid.
- @y: The y coordinate of the desired image on the grid.
/* Usage: */ .example { .sprite-pos(2,3); } /* Example output: */ .example { background-position: -100px -150px; }.sprite-pos-sized()
Similar to the .sprite-pos() partial mixin above, but includes the ability to set the size of the element.
.sprite-pos-sized(<@x>, <@y>, <@width>, <@height>);
- @x: The x coordinate of the desired image on the grid.
- @y: The y coordinate of the desired image on the grid.
- @width: The width of the image.
- @height: The height of the image.
.sprite-pos-sized(<@x>, <@y>, <@size>);
- @x: The x coordinate of the desired image on the grid.
- @y: The y coordinate of the desired image on the grid.
- @size: The width of the image.
/* Usage: */ .example { .sprite-pos-sized( 2, 3, 16px, 32px ); } .example2 { .sprite-pos-sized( 2, 3, 16px ); } /* Example output: */ .example { background-position: -100px -150px; width: 16px; height: 32px; } .example2 { background-position: -100px -150px; width: 16px; height: 16px; }Icons
The icons mixins let you easily place an icon before or after an element, using absolutely positioned :before and :after pseudo elements to display them. There are also sprited icon mixins build on the sprite mixins above.
The exact output of all the icon mixins depends on the value of the @using-modernizer setting.
.prepend-icon()
Prepends an icon to the element it's called on.
.prepend-icon( <@icon-image>, <@width>, <@height>[, <@nudge-left>[, <@nudge-top>[, <@pad>]]] );
- @icon-image: URL or data URI of an image to use for the prepended icon
- @width: Width of the image
- @height: Height of the image
- @nudge-left: (Optional) The value of the left property for the icon. Defaults to 0.
- @nudge-top: (Optional) The value of the top property for the icon. Defaults to 0.
- @pad: (Optional) Left-padding (in addition to the width of the icon) to apply to the element. Defaults to 10px
/* Usage: */ .example { .prepend-icon( 'img/icon.png', 16px, 32px ); } /* Example output: */ .example { position: relative; padding-left: 42px; } .example:before { position: absolute; display: block; content: ' '; background: url('img/icon.png') no-repeat 0 0; width: 16px; height: 32px; top: 0; left: 0; }.append-icon()
Appends an icon after the element it's called on.
.append-icon( <@icon-image>, <@width>, <@height>[, <@nudge-right>[, <@nudge-top>[, <@pad>]]] );
- @icon-image: URL or data URI of an image to use for the prepended icon
- @width: Width of the image
- @height: Height of the image
- @nudge-right: (Optional) The value of the right property for the icon. Defaults to 0.
- @nudge-top: (Optional) The value of the top property for the icon. Defaults to 0.
- @pad: (Optional) Right-padding (in addition to the width of the icon) to apply to the element. Defaults to 10px
/* Usage: */ .example { .append-icon( 'img/icon.png', 16px, 32px ); } /* Example output: */ .example { position: relative; padding-right: 42px; } .example:after { position: absolute; display: block; content: ' '; background: url('img/icon.png') no-repeat 0 0; width: 16px; height: 32px; top: 0; right: 0; }.prepend-sprite-icon()
Prepends an icon taken from the sprite to the element it's called on.
.prepend-sprite-icon( <@x>, <@y>, <@width>, <@height>[, <@nudge-left>[, <@nudge-top>[, <@pad>[, <@sprite-image>[, <@sprite-grid>]]]]] );
- @x: The x coordinate of the desired image on the grid.
- @y: The y coordinate of the desired image on the grid.
- @width: Width of the image
- @height: Height of the image
- @nudge-left: (Optional) The value of the left property for the icon. Defaults to 0.
- @nudge-top: (Optional) The value of the top property for the icon. Defaults to 0.
- @pad: (Optional) Left-padding (in addition to the width of the icon) to apply to the element. Defaults to 10px
- @sprite-image: (Optional) The sprite image to use. Defaults to the globally defined @sprite-image value.
- @sprite-grid: (Optional) The grid size used in the sprite. Defaults to the globally defined @sprite-grid value.
/* Usage: */ .example { .prepend-sprite-icon( 1, 2, 16px, 32px ); } /* Example output: */ .example { position: relative; padding-left: 42px; } .example:before { position: absolute; display: block; content: ' '; background-image: url('/images/example-sprite.png'); background-repeat: no-repeat; background-position: -50px -100px; width: 16px; height: 32px; top: 0; left: 0; }.append-sprite-icon()
Appends an icon taken from the sprite after the element it's called on.
.append-sprite-icon( <@x>, <@y>, <@width>, <@height>[, <@nudge-right>[, <@nudge-top>[, <@pad>[, <@sprite-image>[, <@sprite-grid>]]]]] );
- @x: The x coordinate of the desired image on the grid.
- @y: The y coordinate of the desired image on the grid.
- @width: Width of the image
- @height: Height of the image
- @nudge-right: (Optional) The value of the right property for the icon. Defaults to 0.
- @nudge-top: (Optional) The value of the top property for the icon. Defaults to 0.
- @pad: (Optional) Right-padding (in addition to the width of the icon) to apply to the element. Defaults to 10px
- @sprite-image: (Optional) The sprite image to use. Defaults to the globally defined @sprite-image value.
- @sprite-grid: (Optional) The grid size used in the sprite. Defaults to the globally defined @sprite-grid value.
/* Usage: */ .example { .append-sprite-icon( 1, 2, 16px, 32px ); } /* Example output: */ .example { position: relative; padding-right: 42px; } .example:after { position: absolute; display: block; content: ' '; background-image: url('/images/example-sprite.png'); background-repeat: no-repeat; background-position: -50px -100px; width: 16px; height: 32px; top: 0; right: 0; }.prepend-sprite-icon-pos()
Adjusts the positioning of a prepended sprite icon.
.prepend-sprite-icon-pos( <@x>, <@y>[, <@nudge-left>[, <@nudge-top>[, <@sprite-grid>]]] );
- @x: The x coordinate of the desired image on the grid.
- @y: The y coordinate of the desired image on the grid.
- @nudge-left: (Optional) The value of the left property for the icon. Defaults to 0.
- @nudge-top: (Optional) The value of the top property for the icon. Defaults to 0.
- @sprite-grid: (Optional) The grid size used in the sprite. Defaults to the globally defined @sprite-grid value.
/* Usage: */ .example { .prepend-sprite-icon-pos( 1, 2 ); } /* Example output: */ .example:before { background-position: -50px -100px; }.append-sprite-icon-pos()
Adjusts the positioning of a appended sprite icon.
.append-sprite-icon-pos( <@x>, <@y>[, <@nudge-right>[, <@nudge-top>[, <@sprite-grid>]]] );
- @x: The x coordinate of the desired image on the grid.
- @y: The y coordinate of the desired image on the grid.
- @nudge-right: (Optional) The value of the right property for the icon. Defaults to 0.
- @nudge-top: (Optional) The value of the top property for the icon. Defaults to 0.
- @sprite-grid: (Optional) The grid size used in the sprite. Defaults to the globally defined @sprite-grid value.
/* Usage: */ .example { .append-sprite-icon-pos( 1, 2 ); } /* Example output: */ .example:after { background-position: -50px -100px; }.prepend-icon-setup()
A partial mixin to generate common properties for prepended icon mixins.
.prepend-icon-setup( [<@width>[, <@height>[, <@nudge-left>[, <@nudge-top>[, <@pad>]]]]] );
- @width: (Optional) Width of the image. Defaults to not being set.
- @height: (Optional) Height of the image. Defaults to not being set.
- @nudge-left: (Optional) The value of the left property for the icon. Defaults to not being set.
- @nudge-top: (Optional) The value of the top property for the icon. Defaults to not being set.
- @pad: (Optional) Left-padding (in addition to the width of the icon) to apply to the element. Defaults to 10px
/* Usage: */ .example { .prepend-icon-setup( 32px, 15px ); } /* Example output: */ .example { position: relative; } .example:before { position: absolute; display: block; content: ' '; top: 0; left: 0; width: 32px; height: 15px; }.append-icon-setup()
A partial mixin to generate common properties for appended icon mixins.
.append-icon-setup( [<@width>[, <@height>[, <@nudge-right>[, <@nudge-top>[, <@pad>]]]]] );
- @width: (Optional) Width of the image. Defaults to not being set.
- @height: (Optional) Height of the image. Defaults to not being set.
- @nudge-right: (Optional) The value of the right property for the icon. Defaults to not being set.
- @nudge-top: (Optional) The value of the top property for the icon. Defaults to not being set.
- @pad: (Optional) Right-padding (in addition to the width of the icon) to apply to the element. Defaults to 10px
/* Usage: */ .example { .append-icon-setup( 32px, 15px ); } /* Example output: */ .example { position: relative; } .example:after { position: absolute; display: block; content: ' '; top: 0; right: 0; width: 32px; height: 15px; }.prepend-icon-image()
A partial mixin to generate image-specific properties for prepended icon mixins. Likely to be used in combination with the .prepend-icon-setup() mixin above.
.prepend-icon-image( <@icon-image>[, <@width>[, <@height>[, <@nudge-left>[, <@nudge-top>[, <@pad>]]]]] );
- @icon-image: URL or data URI of an image to use for the prepended icon
- @width: (Optional) Width of the image. Defaults to not being set.
- @height: (Optional) Height of the image. Defaults to not being set.
- @nudge-left: (Optional) The value of the left property for the icon. Defaults to not being set.
- @nudge-top: (Optional) The value of the top property for the icon. Defaults to not being set.
- @pad: (Optional) Left-padding (in addition to the width of the icon) to apply to the element. Defaults to 10px
/* Usage: */ .example { .prepend-icon-image( 'img/icon.png', 12px, 12px ); } /* Example output: */ .example { padding-left: 22px; } .example:before { background: url('img/icon.png') no-repeat 0 0; width: 12px; height: 12px; }.append-icon-image()
A partial mixin to generate image-specific properties for appended icon mixins. Likely to be used in combination with the .append-icon-setup() mixin above.
.append-icon-image( <@icon-image>[, <@width>[, <@height>[, <@nudge-right>[, <@nudge-top>[, <@pad>]]]]] );
- @icon-image: URL or data URI of an image to use for the prepended icon
- @width: (Optional) Width of the image. Defaults to not being set.
- @height: (Optional) Height of the image. Defaults to not being set.
- @nudge-right: (Optional) The value of the right property for the icon. Defaults to not being set.
- @nudge-top: (Optional) The value of the top property for the icon. Defaults to not being set.
- @pad: (Optional) Right-padding (in addition to the width of the icon) to apply to the element. Defaults to 10px
/* Usage: */ .example { .append-icon-image( 'img/icon.png', 12px, 12px ); } /* Example output: */ .example { padding-right: 22px; } .example:after { background: url('img/icon.png') no-repeat 0 0; width: 12px; height: 12px; }Arrows
The arrow mixins give the ability to create pure CSS 'arrows' for use in different contexts.
.arrow()
Turns an empty element into an arrow. This works best when applied to pseudo-elements so that you don't need to creating junk elements in the DOM.
.arrow( <@direction>, <@size>, <@bg-color> );
- @direction: Direction that the arrow should point in. Possible values: up, down, left, right.
- @size: Size (in pixels) of the arrow.
- @bg-color: The color of the arrow.
/* Usage: */ .example:before { .arrow(right, 10px, #F00); } /* Example output: */ .example:before { width: 0; height: 0; border: 10px solid transparent; border-left-color: #F00; }.arrowbox()
Adds an arrow pointer to a box, for use as a tooltip (or similar).
.arrowbox( <@direction>, <@size>, <@bg-color>[, <@offset>] );
- @direction: Direction that the arrow should point in. Possible values: up, down, left, right.
- @size: Size (in pixels) of the arrow.
- @bg-color: The background-color of the arrow and the box.
- @offset: (Optional) Position (in pixels) for where the arrow should be positioned along the side of the box. Defaults to the center.
.arrowbox( <@direction>, <@size>, <@bg-color>, <@border-width>, <@border-color>[, <@offset>] );
- @direction: Direction that the arrow should point in. Possible values: up, down, left, right.
- @size: Size (in pixels) of the arrow.
- @bg-color: The background-color of the arrow and the box.
- @border-width: The border width for the arrow and the box.
- @border-color: The border color for the arrow and the box.
- @offset: (Optional) Position (in pixels) for where the arrow should be positioned along the side of the box. Defaults to the center.
/* Usage: */ .example { .arrowbox(down, 10px, #000); } .example2 { .arrowbox(right, 10px, #000, 2px, #F00); } /* Example output: */ .example { width: 100px; height: 100px; position: relative; background: #000; margin-bottom: 20px; } .example:after, .example:before { top: 100%; border: solid transparent; content: " "; height: 0; width: 0; position: absolute; pointer-events: none; } .example:after { border-color: transparent; border-top-color: #000; border-width: 10px; left: 50%; margin-left: -10px; } .example2 { width: 100px; height: 100px; position: relative; background: #000; border: 2px solid #F00; margin-bottom: 20px; } .example2:after, .example2:before { left: 100%; border: solid transparent; content: " "; height: 0; width: 0; position: absolute; pointer-events: none; } .example2:after { border-color: transparent; border-left-color: #000; border-width: 8px; top: 50%; margin-top: -8px; } .example2:before { border-color: transparent; border-left-color: #F00; border-width: 11px; top: 50%; margin-top: -11px; }Grids
The ClearLess grid system is a straightforward, fluid grid system that supports either floated columns or columns created using display: inline-block;. It supports infinite levels of nested columns.
Gutters are applied using the margin-right property. The columns that represent the last in a row at any time need to have the .end-column() (for floated grids) or .inline-end-column() (for inline-block grids) applied to them to stop them dropping down (although there are also shortcuts for doing this in the column and inline-column mixins themselves). There are obviously other ways to address this 'last column gutter' issue - but we've opted for simplicity and to closest match how many people would code this when doing so in 'straight' css.
Groups of columns need to be wrapped in a parent element with the appropriate .column-wrapper() or .inline-column-wrapper() mixin applied to them.
SETTING: @total-columns
The total number of columns for the top-level grid.
SETTING: @column-width
The width of a column, in pixels. It should be noted that the pixel value is never actually used itself - instead it will be converted to a percentage value. If you have flat visuals you can take this value straight from your visual, whatever width they are fixed at.
SETTING: @gutter-width
The width of a gutter, in pixels. It should be noted that the pixel value is never actually used itself - instead it will be converted to a percentage value. If you have flat visuals you can take this value straight from your visual, whatever width they are fixed at.
.column-wrapper()
Apply to the parent element of the grid columns for floated grids. This (by design) does not apply any float clearing to the columns - you will likely want to use the .clearfix() mixin (or overflow:hidden; or whatever you're perferred float clearing methid is!) to account for this.
/* Usage: */ .example { .column-wrapper(); } /* Example output: */ .example { width: 100%; }.inline-column-wrapper()
Apply to the parent element of the grid columns for inline-block grids.
.inline-column-wrapper();/* Usage: */ .example { .column-wrapper(); } /* Example output: */ .example { letter-spacing: -0.31em; word-spacing: -0.43em; } .ie7 .example { letter-spacing: normal; }.column()
When supplied with no arguments, this mixin just sets up the necessary shared styles to make an element into a floated column. The .span() mixin should then be used to apply the correct width accordingly.
When supplied with a column count, this mixin effectively combines both of the above steps into one - simpler but may not result in the most optimised CSS, depending on the situation.
.column( <@span>[, <@parent-grid-units>[, <@end-column>]] );
- @span: Number of grid columns to span.
- @parent-grid-units: (Optional) For nested grids, the number of columns the parent element spans needs to be added here.
- @end-column: (Optional) Set to true if this column is the last one in a row.
.column( <@span>[, <@end-column>] );
- @span: (Optional) Number of grid columns to span.
- @end-column: (Optional) Set to true if this column is the last one in a row.
/* Usage: */ .example { .column(); } .example2 { .column(2); } .example3 { .column(2,true); } /* Example output: */ .example { float: left; margin-right: 1.5873015873015872%; } .example2 { float: left; width: 11.11111111111111%; margin-right: 1.5873015873015872%; } .example3 { float: left; width: 11.11111111111111%; }.inline-column()
When supplied with no arguments, this mixin just sets up the necessary shared styles to make an element into a inline-block column. The .span() mixin should then be used to apply widths and margins accordingly.
When supplied with a column count, this mixin effectively combines both of the above steps into one - simpler but may not result in the most optimised CSS, depending on the situation.
.inline-column( <@span>[, <@parent-grid-units>[, <@end-column>]] );
- @span: Number of grid columns to span.
- @parent-grid-units: (Optional) For nested grids, the number of columns the parent element spans needs to be added here.
- @end-column: (Optional) Set to true if this column is the last one in a row.
.inline-column( <@span>[, <@end-column>] );
- @span: (Optional) Number of grid columns to span.
- @end-column: (Optional) Set to true if this column is the last one in a row.
/* Usage: */ .example { .inline-column(); } .example2 { .inline-column(2); } .example3 { .inline-column(2,true); } /* Example output: */ .example { display: inline-block; vertical-align: top; letter-spacing: normal; word-spacing: normal; margin-right: 1.5873015873015872%; } .ie7 .example { display: inline; zoom: 1; } .example2 { display: inline-block; vertical-align: top; letter-spacing: normal; word-spacing: normal; width: 11.11111111111111%; margin-right: 1.5873015873015872%; } .ie7 .example2 { display: inline; zoom: 1; } .example3 { display: inline-block; vertical-align: top; letter-spacing: normal; word-spacing: normal; width: 11.11111111111111%; } .ie7 .example3 { display: inline; zoom: 1; }.end-column()
Should be applied to the last column in a row for floated columns. Typically this will equate to the :last-child column, but when dropping columns for RWD this is not always the case.
/* Usage: */ .example { .end-column(); } /* Example output: */ .example { margin-right: 0; float: right; }.inline-end-column()
Should be applied to the last column in a row for inline-block columns. Typically this will equate to the :last-child column, but when dropping columns for RWD this is not always the case.
/* Usage: */ .example { .inline-end-column(); } /* Example output: */ .example { margin-right: 0; }.span()
A partial mixin for generating the width (and sometimes margin-right) property for columns (both floated and inline-block).
.span( <@span>[, <@parent-grid-units>] );
- @span: Number of grid columns to span.
- @parent-grid-units: (Optional) For nested grids, the number of columns the parent element spans needs to be added here.
/* Usage: */ .example { .span(2); } /* Example output: */ .example { width: 11.11111111111111%; }.pre-pad()
Adds the specified number of columns' worth of padding to the the left of the element.
.pre-pad( <@span>[, <@parent-grid-units>] );
- @span: Number of grid columns' worth of padding-left to add.
- @parent-grid-units: (Optional) For nested grids, the number of columns the parent element spans needs to be added here.
/* Usage: */ .example { .pre-pad(2); } /* Example output: */ .example { padding-left: 12.698412698412698%; }.post-pad()
Adds the specified number of columns' worth of padding to the the right of the element.
.post-pad( <@span>[, <@parent-grid-units>] );
- @span: Number of grid columns' worth of padding-right to add.
- @parent-grid-units: (Optional) For nested grids, the number of columns the parent element spans needs to be added here.
/* Usage: */ .example { .post-pad(2); } /* Example output: */ .example { padding-right: 12.698412698412698%; }.pre-push()
Adds the specified number of columns' worth of margin to the the left of the element.
.pre-push( <@span>[, <@parent-grid-units>] );
- @span: Number of grid columns' worth of margin-left to add.
- @parent-grid-units: (Optional) For nested grids, the number of columns the parent element spans needs to be added here.
/* Usage: */ .example { .pre-push(2); } /* Example output: */ .example { margin-left: 12.698412698412698%; }.post-push()
Adds the specified number of columns' worth of margin to the the right of the element.
.post-push( <@span>[, <@parent-grid-units>] );
- @span: Number of grid columns' worth of margin-right to add.
- @parent-grid-units: (Optional) For nested grids, the number of columns the parent element spans needs to be added here.
/* Usage: */ .example { .post-push(2); } /* Example output: */ .example { margin-right: 14.285714285714285%; }.post-push-end()
Should be used instead of the .post-push() mixin above when applied to the last column in a row.
.post-push-end( <@span>[, <@parent-grid-units>] );
- @span: Number of grid columns' worth of margin-right to add.
- @parent-grid-units: (Optional) For nested grids, the number of columns the parent element spans needs to be added here.
/* Usage: */ .example { .post-push-end(2); } /* Example output: */ .example { margin-right: 12.698412698412698%; }Some notes on usage and best practices
Using a CSS preprocessor can result in pretty bloated generated CSS if you're not careful. Below are a few notes that outline some thoughts on how to avoid this and how ClearLess is structured to give you better tools to optimise your generated CSS.
On using (Clear)Less responsibly...
Just because there is a mixin for something doesn't mean you need to use it! If you have a individual case that would need to override half the the properties outputted by the mixin in order to be styled correctly, then is probably better to roll the solution by hand (or create a new mixin for this use case) rather than to use the mixin and then override it. Fight the bloat!
All of the examples below above sample output from the mixins. It's definitely recommended that you familiarise yourself with the output so you can judge whether or not to use the mixin in different situations.
Optimising output using 'partial' mixins
The library consists mostly of 'full' mixins, which stand alone and give you all the functionality you might expect. However there are also an number of so-called 'partial' mixins for things lke sprites, grids and icons. You may need more than one of these mixins to achieve the desired result - the idea is to split out certain bits of functionality so as to allow for optimisations in your generated CSS.
An example using the sprite mixins:
/* Using 'full' mixins - results in verbose generated CSS */ .social { a.twitter { .sprite-sized(0, 1, 16px, 16px); } a.facebook { .sprite-sized(0, 2, 16px, 16px); } a.youtube { .sprite-sized(0, 3, 16px, 16px); } } /* Output - poorly optimised, lots of repitition */ .social a.twitter { background-image: url('/images/example-sprite.png'); background-repeat: no-repeat; background-position: 0 -50px; width: 16px; height: 16px; } .social a.facebook { background-image: url('/images/example-sprite.png'); background-repeat: no-repeat; background-position: 0 -100px; width: 16px; height: 16px; } .social a.youtube { background-image: url('/images/example-sprite.png'); background-repeat: no-repeat; background-position: 0 -150px; width: 16px; height: 16px; } /* Using 'partial' mixins - results in more optimised generated CSS */ .social { a { .sprite-image(); .size(16px); } a.twitter { .sprite-pos(0, 1); } a.facebook { .sprite-pos(0, 2); } a.youtube { .sprite-pos(0, 3); } } /* Output - much better! */ .socal a { background-image: url('/images/example-sprite.png'); background-repeat: no-repeat; width: 16px; height: 16px; } .social a.twitter { background-position: 0 -50px; } .social a.facebook { background-position: 0 -100px; } .social a.youtube { background-position: 0 -150px; }As you can see the second example gives an output that is much less verbose and more like what you would write by hand. So use the mixins wisely - for one off styling a full mixin is often appropriate, for applying the same styling to multiple related elements some of the partial mixins are probably better to use.
Doesn't Gzipping make bloated output a non-issue?
Gzip compression works very well on duplicated strings, so yes - gzipping a file with a lot of duplicated properties will to a large extent offest the additional size/bloat issue.
However, It's still best to work to avoid all that duplication in the first place! And never forget that people may be view-sourcing on these files, and trying to learn from them. Regardless of whether you're gzip'ing, you should always strive to make sure your generated CSS is as representative of CSS you'd write by hand as possible/reasonable.
Mixins or classes?
If you find yourself applying a particular mixin to a lot of element selectors, it's probably worth considering if it would be better to take the 'regular CSS' route and create a separate classname (or classnames) to apply that mixin to. you can then use that class in your HTML instead of repeatedly using the mixin in your Less/CSS. It's generally good to do this in situations where you have an appropriate semantic class name that could encapsulate the mixin's output.
You can of course still use the mixin in other places as needed (where using the class would not be appropriate), but you'll get the advantage of a leaner CSS file (although with the possible disadvantage of more classes in your HTML).
Neither approach is right or wrong - but take the time to consider each particular use case and you'll end up with a better balance between your HTML, your Less and the generated CSS.
Credits
ClearLess is maintained and documented by Mark Perkins. For any queries, questions or bug reports you can ping him on twitter or open an issue in the Github issue tracker.
Many of the mixins, styles and other parts of this library were shamelessly poached from other open-source projects, including Mark Otto's Preboot and the HTML5 Boilerplate. Thanks for being awesome!
IcoMoon provides a package of vector icons, along with a free HTML5 app for making custom icon fonts. Browse among thousands of pixel perfect icons or import your own vectors.
Polar area charts
Polar area charts are similar to pie charts, but the variable isn't the circumference of the segment, but the radius of it.
Chart.js delivers animated polar area charts with custom coloured segments, along with customisable scales and animation.
OverAPI.com is a site collecting all the cheatsheets,all!
Improving performance is a constant process. First we ditched tables, spacer gifs, and inline markup such as the <font> element in favor of CSS, reducing page sizes, and separating style from layout. Then we became aware of all our DNS requests, caching, and the total number of files and started using CSS sprites, moving many small images out of the HTML and into a single background image.
Illustration: Share This:Now it’s time we embrace the third epoch in performance optimization: symbol fonts.
Embedding a symbol font lets us move some of those tiny icons into a single font file rather than a sprite. This has the same caching and file size benefits as a CSS sprite, as well as some additional benefits we’re only now realizing with high-resolution displays. In this article, I’ll walk you through some of the advantages and issues you’ll encounter when using a symbol font.
A smooth experience
As the number of fonts designed for use as icons, glyphs, and decorations increase, several high-traffic websites have replaced all the images on their site with a single symbol font. One of the best-known examples is GitHub, which has improved both its speed and its user experience by dropping all its tiny icon files in favor of Octicons, a single, custom symbol font file.
Symbol fonts trade blocky raster images for smooth vector images in your HTML. This is important because rasterized images are designed to work at a specific resolution, so at higher pixel densities, like those found in today’s high-resolution displays, the images must be scaled up to appear the same size. This results in something that looks more “blocky.” Vectors never have this problem, scaling endlessly up or down for any resolution.
Embedding vector graphics into HTML has had limitations in the past. PDF and SVG are possible, but create interoperability problems. Fonts are vectors and all web browsers, even IE6, have the ability to render embedded fonts in an HTML page. This convergence of technologies—font embedding, high-resolution displays, and browser support—has created a new opportunity to further optimize performance and user experience.
Accessibility
When it comes to accessibility, symbol fonts are in the conflicted situation of working poorly as images, yet quite well as text.
Many of the early symbol font services mapped the graphic to a letter in the ASCII range. Typing a “w” would produce a picture of a globe, typing an “m,” an envelope. This made it easy to see the character-to-symbol conversion simply by typing. Problems would occur when the font embedding failed, ending up with strange letters in random places that didn’t make sense. For instance, if your markup was meant to display an arrow, then the text “Next,” the HTML might look like:
<div><span class="icon">L</span> Next</div>
But if the CSS, JavaScript, or font loading were to fail, you would see the character “L” rather than the symbol for a left arrow. You could put all the fallbacks in place, inject the code with JavaScript or CSS :before or :after, but at the end of the day, search engine spiders might still index that text as “L Next.”There is a better way.
We’ve matured, learned more about these issues, and solved the problem by using the private-use area in Unicode. The glyphs in this area are not connected to the semantics of any letters of the alphabet. If the font isn’t available or doesn’t load, then an empty box will appear instead of a letter.
But wait—we can improve even more!
Fonts also have special characters called ligatures—subtle, often hardly noticeable, tweaks to the letterforms that are used to aid reading. Take, for instance, two consecutive “f” characters. A good font will convert that “ff” into a single ligature where the fs connect smoothly. There are several standard ligatures, including ff, fl, and fi. But there is no reason you can’t also define your own. In a font file, it is a simple substitution; all the ligature is looking for is the right sequence of letters. When they’re typed, they are replaced with another glyph. This means you can have a string like “A List Apart” and convert it into a single symbol icon of the logo.
Browsers that don’t support font embedding—namely, search engine spiders—will index the raw un-ligatured text, but devices capable of rendering the font and ligature will show you the nice vector symbol instead. It’s the best of both worlds, baked in at a much higher level than HTML and CSS.
Once you understand how ligatures work, a world of new possibilities opens up! All those mystery-meat icons used in navigation could be symbols in a font, but beyond that they could be ligatures. So your HTML markup might look like:
<ul> <li>Home</li> <li>Contact</li> <li>About</li> <li>Cart</li> </ul>But the resulting rendered ligatures might look like:
Symbolset has been experimenting with ligatures and symbol fonts for a while, and now sells packs of symbol fonts with commonly used icons. It also has great ligature support, and a demo where you can simply type keywords and watch them snap to symbols immediately. Don’t be surprised if this makes your mind race with ideas.
Using ligatures as glyph substitutes has practical applications. For example, the BBC News website formerly featured a ticking clock in the corner of the homepage. The clock could have used Flash, but that would have been ill-advised given its lack of support and the existence of alternatives. Another option would have been to use CSS to rotate images of the hands with a little JavaScript timing. Instead, the BBC chose HTML5, using Canvas plus JavaScript to continually redraw the clock face.
But both these non-Flash solutions use rasterized images that wouldn’t look as nice on high-resolution displays. There are JavaScript libraries, like Raphaeljs, which can create SVG or VML objects that would be nice and vectorized, but since they are loaded and created in JavaScript, they would be invisible to search engine spiders or other non-JavaScript browsers.
Using a symbol font instead would give you the best of both worlds: accessibility and vectors. Typing 12:00 would call up a ligature, which would convert to a clock with both hands at 12. Typing 12:01 would be a different ligature for the corresponding clock face. While there would be a lot of ligatures to create, the resulting clock would be a beautifully designed vector graphic that would work across platforms.
Think about all a web page’s little details that could be symbol fonts. Open your mind to the possibilities. Everything from bullets and arrows to feed and social media icons could be bundled into a single, tiny font file that can be cached and rendered at various sizes without needing multiple images or colors.
Creating your own symbol font
Web developers and designers cut their teeth on applications like Photoshop, Fireworks and others. For us, moving to CSS sprites or background images wasn’t a big leap because the tools didn’t change. With symbol fonts, a new program enters into the mix: the font editor. This is a new beast we need to learn, but it’s not that difficult.
Even better, plenty of tools are being released to aid in symbol font creation. For example, Icomoon lets you upload your SVG files, map them to unicode characters, and export a font for use online.
What if you want to get more specific and tweak the design beyond its default displays? There are several tools out there to create your own fonts. A few are paid, professional apps, but the most common free tool is FontForge. It’s a bit unwieldy, but there are many tutorials out there to help you use it.
Issues with fonts
As any good designer will tell you, an icon or logo will have subtly different designs at different sizes, such as changing its line thicknesses or even dropping some of its detail at small sizes. With a symbol font, however, you can’t have alternative designs for different font sizes. Your design at 20 point must be the same as at 120 point or 6 point.
If you want different designs at different font sizes, then you need to duplicate the icon in the font file and select the appropriate glyph depending on the usage. This too is problematic, because you have no idea how the end user will actually view your design. Increasing the font size in their browser natively won’t switch your symbol design. For most of us, this isn’t a problem, as many of the utility icons we use today for feeds and social networking scale relatively well.
The other major issue with using a symbol font is that you only get one color. You can work some magic with background colors and font gradients to emulate a two-color logo, but if your icons are multicolored, then the current symbol font setup won’t work for you.
To remedy this, Apple is proposing multicolor fonts, which would let you create and embed pure vector graphics into any web page. Its first foray into this field is the Apple Color Emoji font, which you might already have if your machine runs OSX Lion. The downside of introducing a new font format is the lack of browser support and font creation tools needed to come up to speed, which means it might be a while before this becomes a reality.
Welcome to the next epoch
Symbol fonts are the next step forward in website design and optimization, and you need to understand them to work on the web today. With practice, you can create your own custom symbol fonts with logos, icons, and branding to embed into your websites. Not only will these little extras impress your audience, but they will simultaneously optimize your website’s performance. It’s time we all start using symbol fonts—and help improve the tools, standards, and techniques to make them.
TweetMar 4 2013 by Leo Widrich | Stumble Bookmark
Over the last two years of working at Buffer, I’ve come to learn that there are a few preconceived notions, stereotypes, clichés, and commonsense knowledge about startups that simply aren’t true.
I’d like to share some myths that I’ve discovered while working at a tech startup.
Myth 1: "You Need to Have Deadlines"
It’s hard to find companies, new or old, that don’t have deadlines. It’s in the business culture to set deadlines. And deadlines, on the surface, seem even more important in a newly launched Internet startup as a gauge of rapid progression.
And, honestly, in the beginning, we got sucked into thinking that deadlines were important to our success.
Here’s what we’d do: We’d set a deadline, work like crazy as the date arrives, and then, once the task is finally finished, we could relax.
As most of you probably already know, that never works when you’re trying to do something innovative and new; when you don’t have a manual to refer to on how to perform your tasks. And having deadlines didn’t make us happy either.
So, instead, we decided to apply the idea of pace. We help everyone on the team perform their work at a fast pace. We never try to build up to a big launch anymore.
At Balsamiq, we don’t have deadlines. Ever."
- Giacomo "Peldi" Guilizzoni, founder and CEO of Balsamiq Studios
Myth 2: "You Need Everybody in the Same Room"
This is may be the most obvious — and surprisingly still prevalent — myths about working at a company.
I have to admit that I was very skeptical about working in a remote team. My thinking went like this: "Yes, you can probably have a good team working remotely, but what about a great one?"
The truth is that you can build better remote teams than ever before, and most likely an even better one than having everyone in one place because you remove the geographical factor when you hire team members.
The people on the Buffer team live in Australia, U.S. and Europe.
I believe that embracing remote teams is one of the most important elements going forward.
"The technology to successfully run and manage remote teams has never been better."
- David Heinemeier Hansson, creator of Ruby on Rails and partner at 37signals
"WooThemes will always stay true to our remote roots."
- Adii Piernaar, co-founder of WooThemes
Myth 3: "You Don’t Need a Company Culture at the Start"
So, you’re a team of 4 or 6 or 10. The intuitive thinking in this situation is that company culture is a huge waste of time.
You’re small. You’re just starting out. What you need right now is users, marketing strategies, and beautiful code.
Who cares (or has time to think) about company culture?
Building a company culture from Day 1 was one of the most important elements in Buffer’s growth.
I remember that when I first got on board, Joel (the company’s founder) and I wrote a short document called "The personality of Buffer." This simple document helped us in staying aligned with our vision whenever new ideas or challenges came in.
Culture, I believe, should be solidly in place before any feature update, marketing campaign, significant code-writing, and so forth. It doesn’t have to be elaborate; it could be a short document like ours that guides you in the proper direction.
"If I could do it all over again, I would roll out our core values from Day 1."
- Tony Hsieh, chief executive of Zappos.com
Myth 4: "You Have to Work A Lot, Never Sleep and Feel Miserable"
One of the most common beliefs about the tech startup life is that it’s a miserable one.
You are spending day and night in the office, fueled by energy drinks and pizza, without anything else in your life going on.
We’ve found that discouraging crazy work hours and instead building up an incredibly solid daily routine is much more powerful.
What we do is in fact quite counterintuitive to the prevalent notion that work hours at a startup has to be long — we even ask people to go home even if they’re in a good flow!
You can’t sacrifice today for tomorrow.
"Happiness is not something you postpone for the future; it is something you design for the present."
- Jim Rohn, American entrepreneur, author and motivational speaker
Myth 5: "You Can’t Make Money Until You Become Big"
Making money in the early stages of a startup is often equated to "You’re doing it wrong."
The thinking goes: If you’re focusing on monetization at the start, then you’re not putting all of your attention on growth, which is the most important thing for a startup.
On the contrary, there’s nothing better for a startup than making money early. And it’s not just for the obvious reasons.
"Charging for something is the best way to truly validate your idea," is a line from Joel, Buffer’s founder.
"Making money > Raising money."
- Hiten Shah, co-founder of Crazy Egg and KISSmetrics
Myth 6: "You Need to Hurry!"
This misconception about startup companies is similar to the one about needing deadlines.
The idea is often this: You’re a small startup, you need to outrun the competition and everything needs to happen quickly and in a hurry.
That’s a recipe for burning out and for making huge mistakes.
At our company, we try many things to create a balance between being fast-paced and not rushing our work.
One of the best ways to accomplish this, I’ve found, is with deliberate reflection. Recently we introduced "Daily Pair Calls" where two members of the team have a daily call to reflect and discuss their previous days. It’s a great way to slow down in order to speed up.
"Breaking things in right requires a certain amount of patience. You don’t want to push a new engine too hard. You certainly can’t sit still. And the last thing you need is to stall on the interstate."
- Todd Razor, founder of Three Razor
Myth 7: "You Need to Focus on Hiring the Best People"
Here is another myth that definitely needs some explanation first.
We see that new CEO, VP or SVP being hired away from Google to Amazon, from Twitter to Facebook, and so on. And slowly a myth develops.
You can call it the "rockstar" myth.
The "rockstar" myth is the idea that the best engineers, marketers, designers, etc. are 10x better than us regular folks, and that these are the only people you need to be working with in a startup in order to ensure success.
But, at a startup, is it practical to focus your time and resources searching for that perfect "10x" programmer?
Wouldn’t you be missing out on working with many amazing people if you limited your options to that elusive "10x" designer that probably already works for someone else paying them much more than you can afford?
Instead, at our company, we evaluate candidates based on:
- Do they fit our company’s culture?
- Do we have a real need for the person’s talent and skills right now?
However, if we find someone who is an exceptional fit to our company’s culture, we will still hire the person, even if the position isn’t immediately obvious.
"Your goal shouldn’t be to buy players, your goal should be to buy wins."
- From the movie, Moneyball
Myth 8: "Be Miserable Now, So You Can Enjoy Your Life Later"
Another key misconception about working in a startup is that it involves sacrificing a few years of your life so you’re able to sell your company for a good profit and then live happily ever after.
You don’t need to sacrifice your health and happiness when you work at a startup.
A lot of our values and work at Buffer evolve around happiness. Everyone on the team has a daily call with another team member to discuss his or her daily improvement towards increased happiness, which I believe is important in maintaining a high level of productivity in our company.
"Instead of wondering when your next vacation is, you ought to set up a life you don’t need to escape from."
- Seth Godin, American entrepreneur, author and public speaker
Myth 9: "You Launch Lean, And Then You Can Build Things the Old Way"
So, you’ve read and understood Lean Startup. You decide you’re launching lean with your MVP until you find product market fit, doing all the customer development you can. And then you stop and revert to the "traditional" way of running a company when you’ve gotten a bit of a foothold in the industry.
That’s what we did near the beginning of our startup journey.
Instead, I think being lean should be a continual process, even well after you outgrow the title of "startup" and become a mega-huge company.
The most impressive case study of this is Eric Ries’s (the pioneer of Lean Startup) own company, IMVU. The company’s clear focus on lean throughout all processes is something we try to see as an amazing example to follow at our startup.
Myth 10: "You Can’t Share Numbers or Sensitive Details"
Another myth that we strongly aim to work against is that, as a startup, you have to keep your numbers under the hood.
After all, you’re a small company and if you share your innermost secrets, the competition will crush you!
We found the opposite to be true. We openly shared how we met each of our investors, how much revenue we are generating and have plans of turning into a full-fledged Open company over the next few months.
I believe that being transparent and sharing our progress has helped us gain goodwill with our users and also within the industry.
Your Turn
I’m sure that you could come up with lots more myths and misconceptions about startups.
Share your thoughts and experiences on the subject.
Related Content
About the Author
Leo Widrich is co-founder of Buffer, a better way to post to Twitter, Facebook and LinkedIn. He also blogs about insights on lifehacks, business and productivity on the Buffer blog. You can say “hello” to him on Twitter @leowid (he is a super nice guy).
Published on March 4th, 2013by Jean-Baptiste Jung. - HTML5 is the newest revision, and by far the most interesting, of the Hyper Text Markup Language. is In this article I have compiled awesome HTML5 code snippets to take your website to the next level.Url and email input types
HTML5 introduced new input types url and email are one of those. They allow you to write a more semantically correct code and make the form completion easier on mobile devices, by displaying special buttons (like the @ or .com buttons) depending on the input type.
Here is the url attribute in action:
<input type="url" value="">And the email attribute as well. Please also pay attention to the pattern attribute as I will explain it below.
<input type="email" pattern="[^ @]*@[^ @]*" value="">Source: http://davidwalsh.name/html5-email
Regexp patterns for form validation
Before HTML5, when you used a form on your website, you had to use JavaScript to create a front-side validation. Now with HTML5 and the pattern attribute, you can define a regular expression pattern to validate the data.
The following snippet is for validating email addresses:
<input type="text" title="email" required pattern="[^@]+@[^@]+\.[a-zA-Z]{2,6}" />This one is for strong passwords:
<input title="at least eight symbols containing at least one number, one lower, and one upper letter" type="text" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" required />And this one is for validating phone numbers:
<input type="text" required pattern="(\+?\d[- .]*){7,13}" title="international, national or local phone number"/>Source: http://blog.staffannoteberg.com/2012/03/01/html5-form-validation-with-regex/
Context menus with HTML5
HTML5 context menus allows you to add elements to the contextual menu which appears when the user right click somewhere on your page.
At the time of writing this article, the contextmenu element is only compatible with Firefox, so let’s hope other browsers will implement it very soon.<section contextmenu="mymenu"> <p>Yes, this section right here</p> </section> <menu type="context" id="mymenu"> <menuitem label="Please do not steal our images" icon="img/forbidden.png"></menuitem> <menu label="Social Networks"> <menuitem label="Share on Facebook" onclick="window.location.href = 'http://facebook.com/sharer/sharer.php?u=' + window.location.href;"> </menuitem> </menu> </menu>Source/Demo: http://speckyboy.com/2013/02/13/quick-tip-the-html5…
HTML5 video, with Flash fallback
One of the greatest new possibilities of HTML5 is definitely its ability to play video files without requesting the use of Flash. Though, as older browsers are not compatible with HTML5 videos, you should implement a Flash fallback. The following example show how to embed mp4 and ogv videos in HTML5, with a Flash fallback for older browsers.
<video width="640" height="360" controls> <source src="__VIDEO__.MP4" type="video/mp4" /> <source src="__VIDEO__.OGV" type="video/ogg" /> <object width="640" height="360" type="application/x-shockwave-flash" data="__FLASH__.SWF"> <param name="movie" value="__FLASH__.SWF" /> <param name="flashvars" value="controlbar=over&image=__POSTER__.JPG&file=__VIDEO__.MP4" /> <img src="__VIDEO__.JPG" width="640" height="360" alt="__TITLE__" title="No video playback capabilities, please download the video below" /> </object> </video>Source: http://camendesign.com/code/video_for_everybody
Autocompletion with HTML5 datalists
Using the datalist element, HTML5 allows you to create a list of data to autocomplete an input field. Super useful!
<input name="frameworks" list="frameworks" /> <datalist id="frameworks"> <option value="MooTools"> <option value="Moobile"> <option value="Dojo Toolkit"> <option value="jQuery"> <option value="YUI"> </datalist>Source/Demo: http://davidwalsh.name/datalist
Hidden elements using HTML5
HTML5 introduce the hidden attribute, which allow you to hide a specific element, as you would do it in CSS using display:none.
<p hidden>You can't see this text</p>Source: http://html5demos.com/hidden
element with autofocus
The autofocus attribute allow you to force the focus on a specific element. Useful for search pages such as google.com homepage.
<input autofocus="autofocus" />Source: http://davidwalsh.name/autofocus
HTML5 prefetching
Some time ago I wrote a detailed article about HTML5 prefetching. Basically, prefetching is a simple technique to prefetch and load a resource which is not included in the current page.
The example below shows the prefetching of an image:
<link rel="prefetch" href="http://www.catswhocode.com/wp-content/uploads/my_image.png">Source: http://www.catswhocode.com/blog/mastering-html5-prefetching
Playing audio files with HTML5
HTML5 can play videos as I shown you before, and of course it can also play audio files such as the popular mp3 format. As an example, here is a minimalist but functional audio player.
<audio id="player" src="sound.mp3"></audio> <div> <button onclick="document.getElementById('player').play()">Play</button> <button onclick="document.getElementById('player').pause()">Pause</button> <button onclick="document.getElementById('player').volume+=0.1">Volume Up</button> <button onclick="document.getElementById('player').volume-=0.1">Volume Down</button> </div>Source: http://www.catswhocode.com/blog/mastering-the-html5-audio-property
More posts about HTML5 Share this article
We web designers get excited about the littlest things. Our friends in the print world must get a kick out of watching us talk about finally being able to achieve layouts on the web that they’ve taken for granted for years. Let’s face it: it’s easier these days to embed a video on the web than it is to set type consistently or align elements to a universal grid.
Illustration: Share This:But we’re scrappy folks, web designers. We don’t give up easy. In the long slow battle with browser support and platform inconsistencies, we’ve been able to bring more and more sophisticated print techniques onto the web—sometimes kicking and screaming.
We have the technology
Over the last year or so, there’s been a lot of talk about grid systems and using column grids for website layouts. Mark gave us a lesson plan, Khoi gave us a case study and Cameron gave us a toolkit. The message is clear: we have the browser support, the know-how, and the tools we need to create consistent multi-column grid layouts on the web.
We can apply the same principles of proportion and balance to the type within those columns by borrowing another technique from our print brethren: the baseline grid.
The main principle of the baseline grid is that the bottom of every line of text (the baseline) falls on a vertical grid set in even increments all the way down the page. Imagine those old Big Chief ruled writing pads they gave you in grade school to practice penmanship and you’ve got the basic idea. The magical end result is that all the text on your page lines up across all the columns, creating a harmonious vertical rhythm.
In print, it’s not that hard. Just enable the baseline grid in Quark or InDesign and set the increment based on the line-height you want. On the web of course, it’s another story. It’s hard enough to align things vertically with CSS because it’s tough to predict where every element will fall, and it only gets worse when we’re dealing with type, which is hard enough to size consistently on its own. But with a little math and a slightly obsessive attention to detail, we can make it work.
Firing up the grid
Note: I’ve used pixel units for sizing text in the examples for this article. Recognizing that this may be a surprising recommendation for an article in this publication, I’ve addressed some of my reasons for doing so—as well as some alternate techniques that use relative units—further down.
The first thing we have to do is set a line-height for our grid. I’ve chosen a pretty standard base font size of 12 pixels, and set the line-height at 18 pixels, which gives us a nice open leading of about 150%. It’s important to think about your line-heights up front. You want a ratio of font size to line-height that’s a good balance for readability and that’s easily divisible into smaller units (more on this later).
I’ve also borrowed a trick from Khoi and created a tiling background image that I can use on the page while I’m working to make sure everything lines up where I want it to. You can see the end result with the grid turned on in this example.
You’ll notice in the previous example that the text doesn’t fall directly on the grid lines. Because of the way CSS renders line-height (by adding space above and below the letters) it’s a lot easier to line the text up within the grid lines rather than directly on them. It’s possible to adjust your background image to take this into account, or tweak the padding on certain elements so the text starts in a different place, but there’s no point making this more complicated than it needs to be.
Paragraphs and headers
I’ll start by resetting the margin and padding on everything to zero so we don’t have to worry about default browser styles. In practice, you’ll probably want to use something a little more precise, but for the purposes of this example, a good old star selector will do just fine.
* { margin: 0; padding: 0; }We want space between paragraphs, but the default top and bottom margins of 1em (which works out in this case to 12 pixels) won’t work with our 18 pixel grid, so we’ll set the bottom margin on paragraphs to 18 pixels.
p { margin-bottom: 18px; }As we set the font size for headers, we also need to set appropriate line-heights in multiples of 18, as well as adding the 18 pixel bottom margin.
h1 { font-size: 24px; line-height: 36px; margin-bottom: 18px; } h2 { font-size: 18px; line-height: 18px; margin-bottom: 18px; } h3 { font-size: 12px; line-height: 18px; }The pattern is pretty simple. Any time you add vertical space with a margin or padding, you need to add it in units of 18 pixels to maintain the baseline grid. You don’t always have to add it in one place, but you need to add it in pairs that add up to 18 pixels. For instance, you could set a top margin of 12 pixels and a bottom margin of 6 pixels.
Lists
Lists are a little bit tougher. We’re used to adding a little padding between each list item and before or after a nested list. Depending on your grid size, you may have to choose between adding a lot of extra space (adding a full grid line) or adding none at all and letting list items fall on the regular grid lines.
Since the 18-pixel line-height we started with is pretty generous, the “none at all” option works pretty well here. I’ll just add the bottom margin of 18 pixels.
ul, ol { margin-bottom: 18px; }As for nested lists, it’s possible to add half of your line-height (in this case, 9 pixels) of margin above and below nested lists. Adding half a line to the top and another half to the bottom means the contents of the list will be “off the grid,” but the grid will get back on track once the list ends. It’s a compromise, but sometimes worth it for designs in which you need to accommodate especially long or complicated nested lists.
Floats and sidebars
Here’s where a little discipline comes in. Images and other elements floated within your text need to be sized vertically in multiples of your grid increment: in this case, multiples of 18. If they’re sized correctly, you can add margins around them that add up vertically to a multiple of 18, and the text will always break in the right place, directly under your image.
.left { float: left; margin: 0 18px 18px 0; } .right { float: right; margin: 0 0 18px 18px; }Other floated elements like callout boxes are a little bit more complicated, since it’s harder to predict their height based on the content inside. As long as all text and images inside the float follow the 18-pixel rules, and you always add vertical padding and margins in groups that add up to 18, everything should line up no matter what you put inside.
.callout { border: 1px solid #ddd; padding: 8px 10px; margin-bottom: 18px; }Notice that I added 8 pixels of padding to the top and bottom of the floated element, since the border width already accounted for 2 pixels of added height (8 + 8 + 1 + 1 = 18).
I’m also going to suck out the bottom margin on the last element in the callout so we don’t end up with too much extra space inside. This isn’t a critical layout feature (the grid is still intact without it), so I’ll go ahead and use the :last-child pseudo class since it doesn’t require me to add any extra markup. IE6 won’t get it, but it won’t break the layout.
.callout :last-child { margin-bottom: 0; }The important thing to remember with callouts and sidebars is to keep the line-height the same even if you make the text smaller. You might be tempted to tighten it up, but even for 11- or 10-pixel font sizes, 18 pixels is still a very readable line-height.
All your baseline are belong to us
You can see it all put together in this example. If you don’t believe me, put your rulers away and check it out with the background grid visible.
You can start to see why baseline grids aren’t used very often on the web. It’s pretty tough to keep up with it—especially as your layouts get more complicated—and we’ve only touched the surface of some of the relatively manageable challenges. Just as in print, baseline grids are not always the right choice for every layout, and sometimes you need to make exceptions or exclude certain elements from the grid to make a layout work.
But it’s definitely possible, and something that’s worth experimenting with, especially in combination with a horizontal or column grid. A nice balanced baseline grid—even just within the main content area—can add polish and readability as we move typesetting on the web to the next generation with CSS3 and beyond.
Don’t fear the pixel
One final note on font sizing: I’m using pixels instead of ems in this example for one reason: it makes everything simpler. With pixels, I can set one base line-height for the entire document and I don’t have to recalculate it whenever I use a smaller font size. When designing a practical system like this, it’s important that it’s relatively easy (for yourself and others) to use and maintain.
You can use relative sizes, but it quickly becomes a lot more difficult to maintain as the math becomes more complicated. It’s easy to get 12 out of 18 (just set the line-height to 1.5em), but when you want to adjust the text size but keep the same line-height, the fractions start to get messy, and predicting how browsers are going to round your values makes it hard to be exact. It’s certainly possible however, and if you’re interested in trying something similar with relative text sizes, I’d recommend checking out Richard Rutter’s excellent 24 ways article, Compose to a Vertical Rhythm.
In the end, it’s a tradeoff. Most browsers will scale pixel-based line-heights proportionally along with the text. Of course, the margins don’t scale, and neither do the images. But is it worth making the system more complicated just to make the margins scale if the images don’t? It depends on the situation. In the end, it’s up to you.
At some point as designers we have to strike a balance between creating pixel-perfect layouts and infinitely flexible ones. When you get down to it, resizable text is primarily an accessibility feature, not a design feature. Ideally it’s something that should be provided by the browser, no matter how the page is built, and in modern browsers it is. As long as all your content is readable and accessible at all sizes, it’s not necessarily true that the design must maintain integrity as you scale.
The hover effects on Amazon’s big ‘ole “Shop by Department” mega dropdown are super fast. Look’it how quick each submenu fills in as your mouse moves down the list:
It’s instant. I got nerd sniped by this. Most dropdown menus have to include a bit of a delay when activating submenus. Here’s an old Khan Academy dropdown as an example:
See the delay? You need that, because otherwise when you try to move your mouse from the main menu to the submenu, the submenu will disappear out from under you like some sort of sick, unwinnable game of whack-a-mole. Enjoy this example from bootstrap’s dropdown menus:
I love bootstrap, don’t get it twisted. Just a good example of submenu frustration.
How did Amazon get away without using a delay?It’s easy to move the cursor from Amazon’s main dropdown to its submenus. You won’t run into the bootstrap bug. They get away with this by detecting the direction of the cursor’s path.
If the cursor moves into the blue triangle the currently displayed submenu will stay open for just a bit longer.At every position of the cursor you can picture a triangle between the current mouse position and the upper and lower right corners of the dropdown menu. If the next mouse position is within that triangle, the user is probably moving their cursor into the currently displayed submenu. Amazon uses this for a nice effect. As long as the cursor stays within that blue triangle the current submenu will stay open. It doesn’t matter if the cursor hovers over “Appstore for Android” momentarily — the user is probably heading toward “Learn more about Cloud Drive.”
And if the cursor goes outside of the blue triangle, they instantly switch the submenu, giving it a really responsive feel.
So if you’re as geeky as me and think something this trivial is cool, I made a jQuery plugin that fires events when detecting this sort of directional menu aiming: jQuery-menu-aim. We’re using it in the new Khan Academy “Learn” menu:
I think it feels snappy. I’m not ashamed to copy Amazon. I’m sure this problem was solved years and years ago, forgotten, rediscovered, solved again, forgotten, rediscovered, solved again.
If anyone else on the planet ends up finding a use for jQuery-menu-aim, I’d be grateful to know what you think.
Thanks go to Ben Alpert for helping me understand the linear algebra / cross-product magic Amazon uses to detect movement inside the “blue triangle.” I ended up going w/ a cruder slope-based approach, mostly b/c I’ve lost all intuitive understanding of linear algebra. Sad. Need to watch more KA videos.
If you’ve spent much time with preprocessors like LESS, SASS/SCSS or Stylus you’ve probably discovered their one rather crippling flaw: debugging. With thousands of lines of LESS code suddenly turning into even more thousands of lines of CSS it can become nearly impossible to tell where a particular style comes from. Inspecting CSS used to be the domain of the Chrome Developer Tools and Firebug but now that our CSS is machine generated there’s no longer a link between the style at line 2137 and the LESS file that generated it. Thankfully the Chrome team is addressing this problem but their current focus is on SASS. Today I’ll teach you how to rework your LESS processor so it plays nice with Chrome and reunites you with your old friend, the CSS inspector.
Just to whet your appetite here’s a teaser shot of what we’re going to accomplish.
You’ll notice over on the right instead of your typical style.css: 7 it says modules.less: 7. That’s right, the developer tools are looking at the generated CSS and source mapping it back to the LESS files.
Clicking on the line number will actual dive into the LESS file where we can see the nesting, variables and mixins.
“Awesome!” you say, but how do we do it?
Well SASS has a debugging feature which will output media-queries above each style. It looks like this:
1 2 3 4 @media -sass-debug-info{filename{font-family:file\:\/\/\/Users\/Rob\/Desktop\/less-debug\/less\/base\.less}line{font-family:\000035}} h1 { color: #999999; }This is known as a source map and it basically tells a debugging tool how to find it’s way from the generated output back to the correct source file. The latest version of Chrome Canary has specific support for SASS style source maps, so Felix Gnass cleverly reasoned that if LESS could work like SASS in this respect then the developer tools would pick up on that as well. LESS already has a similar source map feature but the media-queries didn’t quite use the same syntax. In LESS 1.3.3 this should all be fixed so we can now debug our LESS files using the Chrome Dev Tools!
Let’s go ahead and setup Chrome Canary which is required because these are still experimental features.
Important: If you use less.js to compile your LESS in the browser the techniques we’ll be covering will not work for you. Unfortunately less.js generates all its output in a big style block at the top of the page and that seems to confuse the dev tools. I wanted to point that out before you spend too much time setting things up.
Chrome Canary
You can grab the latest version of Chrome Canary here. At the time of this writing (Jan. 09, 2013) the standard Chrome browser does not yet have this feature so Canary is a must.
Once you’ve downloaded Canary type chrome://flags/ into the address bar and hit enter. You should be transported to a magical place.
Here we’ll search for “Enable Developer Tools experiments”. When you find it click “Enable”. Then restart Canary. Once it’s open again fire up the developer tools and click the gear in the bottom right.
In the left hand sidebar click General. Scroll down to where it says Sources and click “Enable source maps”. Again in the sidebar click Experiments, scroll down and enable “Support for Sass”.
Now if you’re just working with SASS then all you have to do is make sure your SASS files generate the proper source maps and you’re done. Here’s a great article to walk you through the last couple of steps. But if you’re like me and your codebase is in LESS there is more work to be done. Onward!
Processors
There are a quite a few ways to convert your LESS into properly source mapped CSS code. You can use the lessc command line tool, a GUI such as CodeKit or have the server do it with something like less-middleware for connect/express. As I mentioned previously, you can also compile less on the client-side using less.js but unfortunately our debugging technique does not seem to work with that approach so you’ll need to use an alternative.
Depending on your processor and the version of LESS it uses you might have to locate the tree.js file inside its copy of LESS and change some of the debugging output. I know that the current version of CodeKit (1.4.1) still uses LESS 1.3.1 so we’ll detail how to patch it.
lessc
If you’ve installed LESS using npm check that you’ve got the latest version.
1 2 $ lessc --version lessc 1.3.3 (LESS Compiler) [JavaScript]If your version is not 1.3.3 or greater you should run npm install -g less to update to the latest version.
To compile your less with baked in source maps pass the --line-numbers flag a value of mediaquery. For example:
1 lessc --line-numbers=mediaquery theme.less theme.cssYour generated LESS should now be inspectable in Chrome Canary. Yay!
CodeKit
We’ll have to patch CodeKit 1.4.1 because it’s still using an oudated version of LESS. Navigate to your Applications folder and right-click on CodeKit.app. Choose “Show Package Contents.” Navigate to Contents/Resources/engines/less/lib/less/ and open tree.js.
Inside of tree.js we’re looking for a block of code like this:
tree.js1 2 3 tree.debugInfo.asMediaQuery = function(ctx) { return '@media -sass-debug-info{filename{font-family:"' + ctx.debugInfo.fileName + '";}line{font-family:"' + ctx.debugInfo.lineNumber + '";}}\n'; };we’re just going to replace that function with this one:
tree.js1 2 3 4 5 tree.debugInfo.asMediaQuery = function(ctx) { return '@media -sass-debug-info{filename{font-family:' + ('file://' + ctx.debugInfo.fileName).replace(/[\/:.]/g, '\\$&') + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; };and that’s it really!
Now when you go back to CodeKit use the “Debug Info in CSS” dropdown and set it to “Media Query at Top of CSS File”.
After that you should be good to go :)
less-middleware
If you’re using the less-middleware extension for Express you’ll want to check its package.json and make sure it’s on version 0.1.9. You should notice in its dependencies that it requires LESS 1.3.3.
1 2 3 4 "dependencies": { "less": ">= 1.3.3", "mkdirp": ">= 0.3.1" },You might need to update your version of the middleware and run npm install again to update everything to the very latest.
In your app you’ll need to add the dumpLineNumbers options to the middleware’s config.
app.js1 2 3 4 5 app.use(lessMiddleware({ src: __dirname + 'path/to/src', dest: __dirname + 'path/to/dest', dumpLineNumbers: 'mediaquery' }));After that you should be all set.
Warnings
Be careful about hacking your own tree.js file if you can’t update LESS for whatever reason. For instance if you’re using CodeKit a future update might wipe out your patch but not necessarily bring LESS to the current version so you may have to re-apply it.
One more thing, make sure before you send your code into production that you remember to turn off debugging otherwise you’ll be needlessly bloating your CSS files by quite a lot.
Conclusion
Personally I’ve found this trick extremely useful when working with large LESS codebases. I’ve seen some chatter that Stylus might also support this trick so if you have first-hand experience debugging Stylus with Chrome please drop me a comment. Otherwise I might do a follow up showing how to achieve similar results in that language.
Any questions or comments hit me up in the discussion area below.
– Rob
You should follow me on Twitter here.
Text Box
Lato is free web-font designed by Lukasz Dziedzic from Warsaw.
Here you can feel the color, size, line height and margins between paragraphs. Don’t forget to underline your links, they are important visual marker for user.
Also, to attract attention you can mark some important words using bold weights.
JekyllBy Tom Preston-Werner, Nick Quaranto, and many awesome contributors!
Jekyll is a simple, blog aware, static site generator. It takes a template directory (representing the raw form of a website), runs it through Textile or Markdown and Liquid converters, and spits out a complete, static website suitable for serving with Apache or your favorite web server. This is also the engine behind GitHub Pages, which you can use to host your project’s page or blog right here from GitHub.
Getting Started
Diving In
Runtime Dependencies
- Classifier: Generating related posts (Ruby)
- Directory Watcher: Auto-regeneration of sites (Ruby)
- Kramdown: Markdown-superset converter (Ruby)
- Liquid: Templating system (Ruby)
- Maruku: Default markdown engine (Ruby)
- Pygments: Syntax highlighting (Python)
Developer Dependencies
- RDiscount: Discount Markdown Processor (Ruby)
- RedCloth: Textile support (Ruby)
- RedGreen: Nicer test output (Ruby)
- RR: Mocking (Ruby)
- Shoulda: Test framework (Ruby)
License
See LICENSE.
At this time of year (Christmas) there’s a lot of tip-like articles that emerge, so I wanted to share what I felt like was the single greatest technical win I have come across in the last few months: using Chrome DevTools for full web dev workflow – so I recorded a quick 4 minute screencast (and even wrote up a few extra bits – because I felt generous this Christmas!).
Actually, truth be told, it’s not the entire workflow (I can’t create new files for instance) – but where I’m up to is: navigating my entire project, making changes and seeing the live impact of that change, testing new ideas and most importantly – actually saving those changes to disk without leaving DevTools.
Although I’m using Canary in the screencast, this functionality is available today in Chrome stable.
Saving
For a long while now, you could edit the “sources” to the web page, and hitting save cmd-s and it would update the current state of the JavaScript engine – which is powerful as hell alone.
But in a recent release to DevTools, a feature that previous required an extension, when you save, DevTools will ask you where you want to save the file to. In my case, I’m working on client side apps – which means just a static directory of JavaScript files. That means I can overwrite the existing file (js or css), and when I continue hitting save, it now overwrites that file on disk.
For me, this seemingly simple addition, means I can do a large amount of coding, testing and debugging directly inside the browser – which reduces the workflow loops.
It’s also worth adding that, whilst you haven’t refreshed, you can also get a complete list of all the modifications – right click on the source: local modifications. From there you can see the time of edits but also see diffs of those changes and revert them (though I believe you should be able to revert individual changes – i.e. just the first change through a patch, I didn’t have any success with this and suspect it’s just a bug in Chrome that I came across).
Code with live state
Another big win for me (which I didn’t include in the video) is that whilst I’m working inside the sources panel, and experiementing I can quickly and easily inspect the state of variables.
I’ll add a breakpoint, or a conditional breakpoint (right click on the line) – the code pauses, and hit esc to bring up a console and test code and check variable state or check entire lines of code to see if the result is what I’m expecting.
Space and stretching your legs
Finally, a couple of extra bits that make my workflow more comfortable for me. I always bump the font up on the DevTools (simple cmd-+) – maybe because I don’t like to strain my eyes, maybe because I’m getting old!
I dock DevTools to the right (in most cases) – which used to be under settings (the bottom right cog) but in Canary has moved to click-hold the bottom left “popout” icon.
Then lastly I tend to hide the source navigator (the list of files) and the debugger (the right hand side) using the little collapse icon.
What I’d like to see next
No doubt there’s someone I can direct these to, but equally I wanted to share my thoughts here because either maybe you know they’re coming, or there’s other features you’d like to see too:
- Ability to edit the “program” file, including the HTML, CSS & JavaScript #167289
- A comment toggle keyboard shortcut (I keep hitting what I think it is, and instead pausing code execution) #167284
- Much clearer feedback when saving wasn’t linked to a file on the hard disk (sometimes I’ve hit save and it’ll save in V8′s engine, but not actually to disk, because I hadn’t linked it up yet) #167285
- Autocomplete whilst editing source (perhaps looking up from the autocomplete in the console) #167290
- Toggle word wrap on sources #167287
I’m sure there’s more I’d like to see the more my workflow moves inside of DevTools. I certainly hope this is as useful to you as it was to me when I discovered “save as”!
You should follow me on Twitter here I'll tweet about JavaScript, HTML 5 and other such gems (amongst usual tweet-splurges)
Hot swapping is the process of replacing code while the application is running. It allows a developer to see changes immediately - no recompiling, no waiting on page reloads, and no clicking to get to the application state where the code was changed. Just save the file and you’ll see the changes.
I would say hot swapping is a must for making applications with an always active update loop (games) and this guy would probably agree.
The Chrome editor
As you can see from the picture above, the Chrome editor has everything you need.
There is a built in tree list view of all scripts used by the application. The editor supports tabs which are remembered when you close the browser window. You have access to the debugger and all the tools that come with it and the all powerful console is right where you need it.
You can even have the editor side by side with the web page:
Most importantly it supports hot swapping out of the box. When you press control+s Chrome will start using the updated file immediately. The need for refreshing the page will greatly decrease.
Saving files locally
By default changes made will be lost when you refresh the page. But with right clicking the source file you can choose the Save As... option. Now just point the dialogue box to your local version of the site and now all the changes you make will get written to you hard drive. Awesome!
The only problem is that you will need to go through the Save As... step for every file in your application. It would be nice to just specify your localhost directory and then let Chrome figure out what goes where. Maybe in the next update?
Not just Javascript
All of the awesome things I mentioned work for editing css files as well. Designers rejoice!
Now we just need a better interface for saving files locally, an easy way of running unit tests, a vim mode and we will have the perfect editor!
Please enable JavaScript to view the comments powered by Disqus. blog comments powered byYou have reached the bottom of the page, well done! Would you consider following me on twitter? Follow @Smotko
Overview
Flight is a lightweight, component-based JavaScript framework that maps behavior to DOM nodes. Twitter uses it for their web applications. By way of example, we've included a simple email client demo (browse the source code) built over the Flight framework.
Flight uses ES5-shim and jQuery. Additionally you will need to include an AMD implementation such as require.js or loadrunner. Please read the Flight documentation for installation instructions.
TweetWhy Flight?
Flight is distinct from existing frameworks in that it doesn't prescribe or provide any particular approach to rendering or providing data to a web application. It's agnostic to how requests are routed, which templating language you use or even if you render your HTML on the client or the server. While some web frameworks encourage developers to arrange their code around a prescribed model layer, Flight is organized around the existing DOM model with functionality mapped directly to DOM nodes.
Not only does this obviate the need for additional data structures that will inevitably influence the broader architecture, but by mapping our functionality directly onto the native web we get to take advantage of native features. For example, we get custom event propagation for free by piggy-backing off DOM event bubbling, and our event handling infrastructure works equally well with both native and custom events.
How does it work?
Flight enforces strict separation of concerns. When you create a component you don't get a handle to it. Consequently, components cannot be referenced by other components and cannot become properties of the global object tree. This is by design. Components do not engage each other directly; instead, they broadcast their actions as events which are subscribed to by other components.
Why events?
Events are open ended. When a component triggers an event it has no knowledge of how its request will be satisfied or by whom. This enforced decoupling of functionality allows the engineer to consider each component in isolation rather than having to reason about the growing complexity of the application as a whole.
By making DOM node events proxies for component events, we let the web work for us:
- we get event propagation for free
- a component can subscribe to a given event type at the document level or it can choose to listen only those events originating from within a specified DOM Node
- subscribing components do not distinguish between custom events from other components (e.g. dataMailItemsServed) and native DOM node events (e.g. click), and process both types of event in an identical fashion
Mobility and Testing
Each component is a module, which aside from a minimal set of standard dependencies (relevant Flight utilities and mixins), has no reference to the outside world. Thus a given component will respond to a given event in the same way, regardless of environment. This makes testing both simple and reliable — events are essentially the only variable and a production event is easy to replicate in testing. You can even debug a component by triggering events in the console.
Mixins
A mixin defines a set of functionality that is useful to more than one object. Flight comes with built-in support for functional mixins, including protection against unintentional overrides and duplicate mixins. While classical JavaScript patterns support only single inheritance, a component (or other object) can have multiple mixins applied to it. Moreover mixins requires a fraction of the boilerplate required to form traditional classical hierarchies out of constructor-prototypes hybrids, and don't suffer the leaky abstractions of the latter ('super', 'static', 'const' etc.)
Documentation and Demo
Our GitHub page includes full documentation as well as a sample app in the form of an email client:
Future Work
Flight is an ongoing project. We’re planning to add a full testing framework as well as making available more of the utilities that we use for the Twitter website frontend. We also look forward to your contributions and comments. We know we haven’t thought of everything and with your help we can continue to improve Flight for the benefit of everyone.
Acknowledgements
Flight was a group effort.
The following folks contributed to the project: Angus Croll (@angustweets), Dan Webb (@danwrong), Kenneth Kufluk (@kpk) and the members of the Twitter web team.Thanks also to Tom Hamshere (@tbrd) for his work on the README.md and Nicolas Gallagher (@necolas) for general contributions to this site.
On behalf of the Web Core team,
—Angus Croll, Engineer (@angustweets)
Usage
1. Link to the JavaScript dependencies.
<script src="jquery.js"></script> <script src="jquery.cookie.js"></script> <script src="bootstrap.tooltip.js"></script> <script src="bootstrap.popover.js"></script> <script src="bootstrap-tour.js"></script>2. Initialize the tour
var tour = new Tour();3. Add steps
tour.addStep({ element: "", /* html element next to which the step popover should be shown */ title: "", /* title of the popover */ content: "" /* content of the popover */ });You can add as many steps as you want, but not too much or your users will fell asleep!
4. Start the tour
tour.start();Options
Useful Methods
Bootstrap Tour saves the current step and will not display the tour again to users who have already completed it.
If, for some reasons, you want to force the tour to be displayed, pass true to the start() method.
tour.start(true);Sometimes you want to end the tour prematurely:
tour.end();Or skip to the next step:
tour.next();Or go back to the previous step:
tour.prev();Or skip to a specific step:
tour.showStep(i); // i is the position of the step in the tour, starting from 0 for the first stepOr restart the tour after it ended:
tour.restart();Or verify if the tour ended:
tour.ended();Initialization Options
Default options:
var tour = new Tour({ name: "tour", keyboard: true, useLocalStorage: false, afterGetState: function (key, value) {}, afterSetState: function (key, value) {}, onStart: function (tour) {}, onEnd: function (tour) {}, onShow: function (tour) {}, onHide: function (tour) {} });name
This option is used to build the name of the cookie or localStorage item where the tour state is stored. You can initialize several tours with different names in the same page and application.
keyboard
This option set the left/right arrow navigation. The default is true.
useLocalStorage
You can choose to save the tour state with localStorage instead of cookie. If you decide, you can safely remove the jquery.cookie plugin from the dependencies
afterGetState and afterSetState
You may want to do something right after Bootstrap Tour read or write the state. Just pass functions to afterGetState or afterSetState.
Your functions can have two parameters:
- key
- Contains the name of the state being saved. It can be current_step (for the state where the latest step the visitor viewed is saved) or end (for the state which is saved when the user complete the tour). Note that Bootstrap Tour prepends the key with tour_ when saving the state.
- value
- The value of the state been saved. Can be the index of the current step if the key is current_step, or yes if the key is end.
A simple example if to send a post request to your server each time there is a change:
var tour = new Tour({ afterSetState: function (key, value) { jQuery.post("/some/path", value); } });onStart
Function to execute when the tour starts.
onEnd
Function to execute when the tour ends.
onShow
Function to execute right before each step is shown.
onHide
Function to execute right before each step is hidden.
Step Options
Default options:
tour.addStep({ path: "", // string element: "", // (required) jQuery selector placement: "right", // string|function title: "", // string|function content: "", // string|function next: 0, // number prev: 0, // number animation: true, // boolean onShow: function (tour) {}, // function onHide: function (tour) {} // function });
- path
- Path to the page on which the step should be shown. this allows you to build tours that span several pages!
- element
- HTML element on which the step popover should be shown.
- placement
- How to position the popover - top | bottom | left | right.
- title
- Step title
- content
- Step content
- next
- Index of the step to show after this one, starting from 0 for the first step of the tour. -1 to not show the link to next step. By default, the next step (in the order you added them) will be shown.
This option should be used in conjunction with "prev".- prev
- Index of the step to show before this one, starting from 0 for the first step of the tour. -1 to not show the link to previous step. By default, the previous step (in the order you added them) will be shown.
This option should be used in conjunction with "next".- animation
- Apply a css fade transition to the tooltip.
- onShow
- Function to execute right before the step is shown. It overrides the global onShow option.
- onHide
- Function to execute right before the step is hidden. It overrides the global onHide option.
- options
- (Object) Extend the options for one step.
- reflex
- (Bool) Enable the reflex mode : you can click on the element for continue the tour.
Contributing
Bug reports and pull requests are much needed!
License
Code licensed under the Apache License v2.0. Documentation licensed under CC BY 3.0. Well, the same licenses as Bootstrap. We are lazy! ;)
The new JavaScript Web Speech API makes it easy to add speech recognition to your web pages. This API allows fine control and flexibility over the speech recognition capabilities in Chrome version 25 and later. Here's an example with the recognized text appearing almost immediately while speaking.
DEMO / SOURCELet’s take a look under the hood. First we check to see if the browser supports the Web Speech API by checking if the webkitSpeechRecognition object exists. If not, we suggest the user upgrades his browser. (Since the API is still experimental, it's currently vendor prefixed.) Lastly, we create the webkitSpeechRecognition object which provides the speech interface, and set some of its attributes and event handlers.
if (!('webkitSpeechRecognition' in window)) { upgrade(); } else { var recognition = new webkitSpeechRecognition(); recognition.continuous = true; recognition.interimResults = true; recognition.onstart = function() { ... } recognition.onresult = function(event) { ... } recognition.onerror = function(event) { ... } recognition.onend = function() { ... } ...The default value for continuous is false, meaning that when the user stops talking, speech recognition will end. This mode is great for simple text like short input fields. In this demo, we set it to true, so that recognition will continue even if the user pauses while speaking.
The default value for interimResults is false, meaning that the only results returned by the recognizer are final and will not change. The demo sets it to true so we get early, interim results that may change. Watch the demo carefully, the grey text is the text that is interim and does sometimes change, whereas the black text are responses from the recognizer that are marked final and will not change.
To get started, the user clicks on the microphone button, which triggers this code:
function startButton(event) { ... final_transcript = ''; recognition.lang = select_dialect.value; recognition.start();We set the spoken language for the speech recognizer "lang" to the BCP-47 value that the user has selected via the selection drop-down list, for example “en-US” for English-United States. If this is not set, it defaults to the lang of the HTML document root element and hierarchy. Chrome speech recognition supports numerous languages (see the “langs” table in the demo source), as well as some right-to-left languages that are not included in this demo, such as he-IL and ar-EG.
After setting the language, we call recognition.start() to activate the speech recognizer. Once it begins capturing audio, it calls the onstart event handler, and then for each new set of results, it calls the onresult event handler.
recognition.onresult = function(event) { var interim_transcript = ''; for (var i = event.resultIndex; i < event.results.length; ++i) { if (event.results[i].isFinal) { final_transcript += event.results[i][0].transcript; } else { interim_transcript += event.results[i][0].transcript; } } final_transcript = capitalize(final_transcript); final_span.innerHTML = linebreak(final_transcript); interim_span.innerHTML = linebreak(interim_transcript); }; }This handler concatenates all the results received so far into two strings: final_transcript and interim_transcript. The resulting strings may include "\n", such as when the user speaks “new paragraph”, so we use the linebreak function to convert these to HTML tags <br> or <p>. Finally it sets these strings as the innerHTML of their corresponding <span> elements: final_span which is styled with black text, and interim_span which is styled with gray text.
interim_transcript is a local variable, and is completely rebuilt each time this event is called because it’s possible that all interim results have changed since the last onresult event. We could do the same for final_transcript simply by starting the for loop at 0. However, because final text never changes, we’ve made the code here a bit more efficient by making final_transcript a global, so that this event can start the for loop at event.resultIndex and only append any new final text.
That’s it! The rest of the code is there just to make everything look pretty. It maintains state, shows the user some informative messages, and swaps the GIF image on the microphone button between the static microphone, the mic-slash image, and mic-animate with the pulsating red dot.
The mic-slash image is shown when recognition.start() is called, and then replaced with mic-animate when onstart fires. Typically this happens so quickly that the slash is not noticeable, but the first time speech recognition is used, Chrome needs to ask the user for permission to use the microphone, in which case onstart only fires when and if the user allows permission. Pages hosted on HTTPS do not need to ask repeatedly for permission, whereas HTTP hosted pages do.
So make your web pages come alive by enabling them to listen to your users!
We’d love to hear your feedback...
HTML5 Drag and Drop Avatar Changer with Resizing and CroppingPublished January 14, 2013 by Chris Coyier
In any app that has user avatars, users should be able to change those avatars. Anything to make that easier is desirable. Many apps start with a user's Twitter avatar, Facebook avatar, or Gravatar. That's a smart move. Avatars give users a sense of ownership over a virtual space so any way to get them to have their desired avatar is good for engagement.
Let's create a page where a user can update their avatar with as little friction as possible: they just drop an image anywhere on the page and it's done.
The Workhorse of Drag and Drop
Perhaps the most important bit we'll deal with is the drop event. This is where we get access to the file and can do what we need to do with it. We'll be using jQuery to help us with events and whatnot.
// Required for drag and drop file access jQuery.event.props.push('dataTransfer'); $("body").on('drop', function(event) { // Or else the browser will open the file event.preventDefault(); // Do something with the file(s) var files = event.dataTransfer.files; }Interestingly enough, as written, the above won't work. One more bit is required, and that is to prevent the default of the dragover event as well. That's fine, as we will be using that event to make some kind of UI change to emphasize "dropability."
$("body").on("dragover", function(event) { // Do something to UI to make page look droppable // Required for drop to work return false; });And of course remove that UI change if the user doesn't perform the drop:
$("body").on("dragleave", function(event) { // Remove UI change });Handling the Dropped File
Drag and drop can do multiple files. We're only dealing with one file here, so let's just use the first one.
$("body").on('drop', function(event) { event.preventDefault(); var file = event.dataTransfer.files[0]; if (file.type.match('image.*')) { // Deal with file } else { // However you want to handle error that dropped file wasn't an image } }Perhaps if you were really nice, you'd loop over all the files and find the first image rather than rejecting based on the first file.
Resizing the Avatar
There are server side ways to resize images, but that requires a round trip (slow) and the transfer of potentially enormous files (slow). We can resize the avatar to the size we want for our app right on the client side. This is wicked fast.
You can do this by creating a <canvas>, drawing the image to the canvas, then exporting the canvas as a Data URI. Andrea Giammarchi has an excellent script for this. You would just include this script before all this custom code we're writing.
Squaring Avatars
In our example, all our avatars are squares. Squaring is a little tricky. Do you allow rectangles and just center them? Do you apply whitespace around edges so rectangles are really squares? Do you crop the image so it's a square? If you do crop, from what original point do you do the cropping? Do you crop before or after the resizing?
- Let's go with cropping.
- Let's not bother the user about it at all. There are ways to build UI cropping tool for users to pick their own crop, but let's not make an extra step for them and just do it automatically
- Let's crop from the top/left.
All this canvas stuff was a bit over my head. Fortunately Ralph Holzmann was able to jump in an help me alter Andrea's original script to handle cropping.
Crop / Resize In Action
With those parts ready to go, we can crop and resize by calling our new script that does both:
var fileTracker = new FileReader; fileTracker.onload = function() { Resample( this.result, 256, 256, placeNewAvatar ); } fileTracker.readAsDataURL(file);placeNewAvatar is a custom callback function that we'll provide that receives the newly resized data URI we can place on the page.
function placeNewAvatar(data) { $("#profile-avatar").attr("src", data); }Uploading and Saving Avatar
You'll probably want to save your resized avatar, not the original. You know, keep things fast and storage low.
It would be silly to trigger a page load to upload the file, since we're already using fancy drag and drop. So we're looking at Ajaxing the file to the server. Perhaps you're server is totally fine accepting and saving that Data URI. In that case, just send 'er up however. Maybe like
$.post({ url: "/your/app/save/image/whatever", data: data });But if you're using some kind of asset host, they will probably want a real file, not a data URI. And they'll want you to POST them multipart/form-data not just a string. So you'll need to change that data URI into a file (or "Blob").
function dataURItoBlob(dataURI) { var binary = atob(dataURI.split(',')[1]); var array = []; for (var i = 0; i < binary.length; i++) { array.push(binary.charCodeAt(i)); } return new Blob([new Uint8Array(array)], {type: 'image/jpeg'}); }You also can't use jQuery to Ajax the file anymore, because it's Ajax methods won't let you pass FormData() in my experience. So you'll have to do it manually, which is fine since drag and drop more new-fangled than Ajax anyway.
var xhr = new XMLHttpRequest(); var fd = new FormData(); fd.append('file', resampledFile); xhr.open('POST', "/your/app/save/image/whatever", true); xhr.send(fd);Relevant CSS Bits
If you're going to watch for the drop event on the body, you should make sure the body is at least as tall as the page. Otherwise there might be some space toward the bottom that won't take the event.
html, body { height: 100%; }Also, the drag event isn't only fired by files that you drag in from outside the browser window, it can be fired by dragging an image already placed on the page. To prevent this, I wrap the image in a div and apply a pseudo element over the entire div. This prevents the dragging of that image.
.profile-avatar-wrap { position: relative; } .profile-avatar-wrap:after { /* Drag Prevention */ content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; }This works with the file input as well
As a fallback, you could include a file input as well. How exactly you want to handle that is up to you. For example, inject it on a feature detection fail, or just supply both on the page.
<input type="file" id="uploader">Everything would be pretty much the same, only access to the file would happen on:
$("#uploader").on('change', function(event) { var file = event.target.files[0]; });This is particularly relevant for mobile where drag and drop is rather irrelevant.
Not Quite Done
Here's the demo:
I'm not even quite sure the browser support. Here's CanIUse for drag and drop and canvas.
I'm sure I haven't handled everything quite perfectly here. For one thing, it doesn't seem to work in Opera. The drag and drop stuff seems to work (it asks you if you want to upload the file) but never quite processes.
It does work in Chrome/Safari/Firefox.
For another thing, I handled the "Drop File Anywhere" thing by adding a pseudo element to the body. Sometimes it gets a little "flashy". It's an improvement for when I tried doing it with a div, but not great. I also tried only doing and UI action when the dragleave event originated on the body itself.
$("body").on("dragleave", function(event) { if (event.currentTarget == $("body")[0]) { $("body").removeClassClass("droppable"); } // Required for drop to work return false; });But no dice.
And finally, the code shown in this article isn't organized. In real life, you would organize all this. Here is the organized code. If you can fix stuff or make it better, I tossed it on GitHub so feel free to submit a pull request (how).
Responsive PatternsA collection of patterns and modules for responsive designs.
Mostly Fluid Column Drop Layout Shifter Tiny Tweaks Main column with sidebar 3 column 3 column v2 2 equal-width columns 3 equal-width columns 4 equal-width columns 5 equal-width columns 6 equal-width columns Top Left Right Left and Right Bottom Table Cell Flexbox AppendAround List with Thumbnails List with Thumbnails 2 List with Thumbnails and Summary 4-up Grid Block Double-Wide v1 Double-Wide v2 Double-Wide v3 Double-Wide v4 With Title Sections Equal Height Rows Irregular Grid Blocks Responsive Table Definition List to Table Pie Chart to Table Priority Columns Link to Full-Table Horizontal Overflow Header Orientation FlipToggle Footer Anchor Select Menu Left Nav Flyout Left Nav Flyout w/ 'off-nav closing' Priority+ Top Links Stacked Top Links Horizontal Overflow Overlay Multi-Toggle Multi-Toggle v2 Multi-Toggle v3 Multi-Toggle with Active Parent Links Multi-Toggle with Active Parent Links - Pure CSS The Ol' Right-to-Left The Skip the Subnav The Carousel+ Across the Top Breadcrumbs Dropdown Last-One OnlyBasic Fluid Image Picturefill Server-side Image GridFluid Video Fluid Map Maintaining Aspect Ratio Adaptive MapsForm with Left Labels Fluid Search Form Login Form3-up Carousel 3-up Touch Carousel Fluid Carousel Fluid Accordion to Full Accordion To Tab Vertical to Horizontal Slide-Down Notification Bar Overlay Conditional Lightbox
The ultimate checklist for all serious web developers building modern websites. Web Developer