{"rowid": 169, "title": "Incite A Riot", "contents": "Given its relatively limited scope, HTML can be remarkably expressive. With a bit of lateral thinking, we can mark up content such as tag clouds and progress meters, even when we don\u2019t have explicit HTML elements for those patterns.\n\nSuppose we want to mark up a short conversation:\n\n \n Alice: I think Eve is watching. \n\n Bob: This isn\u2019t a cryptography tutorial \u2026we\u2019re in the wrong example!\n \n\n\nA note in the the HTML 4.01 spec says it\u2019s okay to use a definition list:\n\n\n\tAnother application of DL, for example, is for marking up dialogues, with each DT naming a speaker, and each DD containing his or her words.\n\n\nThat would give us:\n\n
\n\t
Alice
:
I think Eve is watching.
\n\t
Bob
:
This isn't a cryptography tutorial ...we're in the wrong example!
\n
\n\nThis usage of a definition list is proof that writing W3C specifications and smoking crack are not mutually exclusive activities. \u201cI think Eve is watching\u201d is not a definition of \u201cAlice.\u201d If you (ab)use a definition list in this way, Norm will hunt you down.\n\nThe conversation problem was revisited in HTML5. What if dt and dd didn\u2019t always mean \u201cdefinition title\u201d and \u201cdefinition description\u201d? A new element was forged: dialog. Now the the \u201cd\u201d in dt and dd doesn\u2019t stand for \u201cdefinition\u201d, it stands for \u201cdialog\u201d (or \u201cdialogue\u201d if you can spell):\n\n\n\t
Alice
:
I think Eve is watching.
\n\t
Bob
:
This isn't a cryptography tutorial ...we're in the wrong example!
\n
\n\nProblem solved \u2026except that dialog is no longer in the HTML5 spec. Hixie further expanded the meaning of dt and dd so that they could be used inside details (which makes sense\u2014it starts with a \u201cd\u201d) and figure (\u2026um). At the same time as the content model of details and figure were being updated, the completely-unrelated dialog element was dropped.\n\nBack to the drawing board, or in this case, the HTML 4.01 specification. The spec defines the cite element thusly:\n\n\n\tContains a citation or a reference to other sources.\n\n\nPerfect! There\u2019s even an example showing how this can applied when attributing quotes to people:\n\nAs Harry S. Truman said,\nThe buck stops here.\n\nFor longer quotes, the blockquote element might be more appropriate. In a conversation, where the order matters, I think an ordered list would make a good containing element for this pattern:\n\n
    \n\t
  1. Alice: I think Eve is watching.
  2. \n\t
  3. Bob: This isn't a cryptography tutorial ...we're in the wrong example!
  4. \n
\n\nProblem solved \u2026except that the cite element has been redefined in the HTML5 spec:\n\n\n\tThe cite element represents the title of a work \u2026 A person\u2019s name is not the title of a work \u2026 and the element must therefore not be used to mark up people\u2019s names.\n\n\nHTML5 is supposed to be backwards compatible with previous versions of HTML, yet here we have a semantic pattern already defined in HTML 4.01 that is now non-conforming in HTML5. The entire justification for the change boils down to this line of reasoning:\n\n\n\tGiven that: titles of works are often italicised and\n\tgiven that: people\u2019s names are not often italicised and\n\tgiven that: most browsers italicise the contents of the cite element,\n\ttherefore: the cite element should not be used to mark up people\u2019s names.\n\n\nIn other words, the default browser styling is now dictating semantic meaning. The tail is wagging the dog.\n\nNot to worry, the HTML5 spec tells us how we can mark up names in conversations without using the cite element:\n\n\n\tIn some cases, the b element might be appropriate for names\n\n\nI believe the colloquial response to this is a combination of the letters W, T and F, followed by a question mark.\n\nThe non-normative note continues:\n\n\n\tIn other cases, if an element is really needed, the span element can be used.\n\n\nThis is not a joke. We are seriously being told to use semantically meaningless elements to mark up content that is semantically meaningful.\n\nWe don\u2019t have to take it.\n\nFirstly, any conformance checker\u2014that\u2019s the new politically correct term for \u201cvalidator\u201d\u2014cannot possibly check every instance of the cite element to see if it\u2019s really the title of a work and not the name of a person. So we can disobey the specification without fear of invalidating our documents.\n\nSecondly, Hixie has repeatedly stated that browser makers have a powerful voice in deciding what goes into the HTML5 spec; if a browser maker refuses to implement a feature, then that feature should come out of the spec because otherwise, the spec is fiction. Well, one of the design principles of HTML5 is the Priority of Constituencies:\n\n\n\tIn case of conflict, consider users over authors over implementors over specifiers over theoretical purity.\n\n\nThat places us\u2014authors\u2014above browser makers. If we resolutely refuse to implement part of the HTML5 spec, then the spec becomes fiction.\n\nJoin me in a campaign of civil disobedience against the unnecessarily restrictive, backwards-incompatible change to the cite element. Start using HTML5 but start using it sensibly. Let\u2019s ensure that bad advice remains fictitious.\n\nTantek has set up a page on the WHATWG wiki to document usage of the cite element for conversations. Please contribute to it.", "year": "2009", "author": "Jeremy Keith", "author_slug": "jeremykeith", "published": "2009-12-11T00:00:00+00:00", "url": "https://24ways.org/2009/incite-a-riot/", "topic": "code"} {"rowid": 171, "title": "Rock Solid HTML Emails", "contents": "At some stage in your career, it\u2019s likely you\u2019ll be asked by a client to design a HTML email. Before you rush to explain that all the cool kids are using social media, keep in mind that when done correctly, email is still one of the best ways to promote you and your clients online. In fact, a recent survey showed that every dollar spent on email marketing this year generated more than $40 in return. That\u2019s more than any other marketing channel, including the cool ones.\n\nThere are a whole host of ingredients that contribute to a good email marketing campaign. Permission, relevance, timeliness and engaging content are all important. Even so, the biggest challenge for designers still remains building an email that renders well across all the popular email clients.\n\nSame same, but different\n\nBefore getting into the details, there are some uncomfortable facts that those new to HTML email should be aware of. Building an email is not like building for the web. While web browsers continue their onward march towards standards, many email clients have stubbornly stayed put. Some have even gone backwards. In 2007, Microsoft switched the Outlook rendering engine from Internet Explorer to Word. Yes, as in the word processor. Add to this the quirks of the major web-based email clients like Gmail and Hotmail, sprinkle in a little Lotus Notes and you\u2019ll soon realize how different the email game is.\n\nWhile it\u2019s not without its challenges, rest assured it can be done. In my experience the key is to focus on three things. First, you should keep it simple. The more complex your email design, the more likely is it to choke on one of the popular clients with poor standards support. Second, you need to take your coding skills back a good decade. That often means nesting tables, bringing CSS inline and following the coding guidelines I\u2019ll outline below. Finally, you need to test your designs regularly. Just because a template looks nice in Hotmail now, doesn\u2019t mean it will next week.\n\nSetting your lowest common denominator\n\nTo maintain your sanity, it\u2019s a good idea to decide exactly which email clients you plan on supporting when building a HTML email. While general research is helpful, the email clients your subscribers are using can vary significantly from list to list. If you have the time there are a number of tools that can tell you specifically which email clients your subscribers are using. Trust me, if the testing shows almost none of them are using a client like Lotus Notes, save yourself some frustration and ignore it altogether. \n\nKnowing which email clients you\u2019re targeting not only makes the building process easier, it can save you lots of time in the testing phase too. For the purpose of this article, I\u2019ll be sharing techniques that give the best results across all of the popular clients, including the notorious ones like Gmail, Lotus Notes 6 and Outlook 2007. Just remember that pixel perfection in all email clients is a pipe dream.\n\nLet\u2019s get started.\n\nUse tables for layout\n\nBecause clients like Gmail and Outlook 2007 have poor support for float, margin and padding, you\u2019ll need to use tables as the framework of your email. While nested tables are widely supported, consistent treatment of width, margin and padding within table cells is not. For the best results, keep the following in mind when coding your table structure.\n\nSet the width in each cell, not the table\n\nWhen you combine table widths, td widths, td padding and CSS padding into an email, the final result is different in almost every email client. The most reliable way to set the width of your table is to set a width for each cell, not for the table itself.\n\n\n\t\n\t\t\n\t\t\n\t\n
\n\nNever assume that if you don\u2019t specify a cell width the email client will figure it out. It won\u2019t. Also avoid using percentage based widths. Clients like Outlook 2007 don\u2019t respect them, especially for nested tables. Stick to pixels. If you want to add padding to each cell, use either the cellpadding attribute of the table or CSS padding for each cell, but never combine the two.\n\nErr toward nesting\n\nTable nesting is far more reliable than setting left and right margins or padding for table cells. If you can achieve the same effect by table nesting, that will always give you the best result across the buggier email clients.\n\nUse a container table for body background colors\n\nMany email clients ignore background colors specified in your CSS or the tag. To work around this, wrap your entire email with a 100% width table and give that a background color.\n\n\n\t\n\t\t\n\t\n
\n\t\t\tYour email code goes here.\n\t\t
\n\nYou can use the same approach for background images too. Just remember that some email clients don\u2019t support them, so always provide a fallback color.\n\nAvoid unnecessary whitespace in table cells\n\nWhere possible, avoid whitespace between your tags. Some email clients (ahem, Yahoo! and Hotmail) can add additional padding above or below the cell contents in some scenarios, breaking your design for no apparent reason.\n\nCSS and general font formatting\n\nWhile some email designers do their best to avoid CSS altogether and rely on the dreaded tag, the truth is many CSS properties are well supported by most email clients. See this comprehensive list of CSS support across the major clients for a good idea of the safe properties and those that should be avoided. \n\nAlways move your CSS inline\n\nGmail is the culprit for this one. By stripping the CSS from the and of any email, we\u2019re left with no choice but to move all CSS inline. The good news is this is something you can almost completely automate. Free services like Premailer will move all CSS inline with the click of a button. I recommend leaving this step to the end of your build process so you can utilize all the benefits of CSS.\n\nAvoid shorthand for fonts and hex notation\n\nA number of email clients reject CSS shorthand for the font property. For example, never set your font styles like this.\n\np {\n\tfont:bold 1em/1.2em georgia,times,serif;\n}\n\nInstead, declare the properties individually like this.\n\np {\n\tfont-weight: bold;\n\tfont-size: 1em;\n\tline-height: 1.2em;\n\tfont-family: georgia,times,serif;\n}\n\nWhile we\u2019re on the topic of fonts, I recently tested every conceivable variation of @font-face across the major email clients. The results were dismal, so unfortunately it\u2019s web-safe fonts in email for the foreseeable future.\n\nWhen declaring the color property in your CSS, some email clients don\u2019t support shorthand hexadecimal colors like color:#f60; instead of color:#ff6600;. Stick to the longhand approach for the best results.\n\nParagraphs\n\nJust like table cell spacing, paragraph spacing can be tricky to get a consistent result across the board. I\u2019ve seen many designers revert to using double
or DIVs with inline CSS margins to work around these shortfalls, but recent testing showed that paragraph support is now reliable enough to use in most cases (there was a time when Yahoo! didn\u2019t support the paragraph tag at all).\n\nThe best approach is to set the margin inline via CSS for every paragraph in your email, like so:\n\np {\n\tmargin: 0 0 1.6em 0;\n}\n\nAgain, do this via CSS in the head when building your email, then use Premailer to bring it inline for each paragraph later.\n\nIf part of your design is height-sensitive and calls for pixel perfection, I recommend avoiding paragraphs altogether and setting the text formatting inline in the table cell. You might need to use table nesting or cellpadding / CSS to get the desired result. Here\u2019s an example:\n\nyour height sensitive text\n\nLinks\n\nSome email clients will overwrite your link colors with their defaults, and you can avoid this by taking two steps. First, set a default color for each link inline like so:\n\nthis is a link\n\nNext, add a redundant span inside the a tag.\n\nthis is a link\n\nTo some this may be overkill, but if link color is important to your design then a superfluous span is the best way to achieve consistency.\n\nImages in HTML emails\n\nThe most important thing to remember about images in email is that they won\u2019t be visible by default for many subscribers. If you start your design with that assumption, it forces you to keep things simple and ensure no important content is suppressed by image blocking.\n\nWith this in mind, here are the essentials to remember when using images in HTML email:\n\nAvoid spacer images\n\nWhile the combination of spacer images and nested tables was popular on the web ten years ago, image blocking in many email clients has ruled it out as a reliable technique today. Most clients replace images with an empty placeholder in the same dimensions, others strip the image altogether. Given image blocking is on by default in most email clients, this can lead to a poor first impression for many of your subscribers. Stick to fixed cell widths to keep your formatting in place with or without images.\n\nAlways include the dimensions of your image\n\nIf you forget to set the dimensions for each image, a number of clients will invent their own sizes when images are blocked and break your layout. Also, ensure that any images are correctly sized before adding them to your email. Some email clients will ignore the dimensions specified in code and rely on the true dimensions of your image. \n\nAvoid PNGs\n\nLotus Notes 6 and 7 don\u2019t support 8-bit or 24-bit PNG images, so stick with the GIF or JPG formats for all images, even if it means some additional file size.\n\nProvide fallback colors for background images\n\nOutlook 2007 has no support for background images (aside from this hack to get full page background images working). If you want to use a background image in your design, always provide a background color the email client can fall back on. This solves both the image blocking and Outlook 2007 problem simultaneously.\n\nDon\u2019t forget alt text\n\nLack of standards support means email clients have long destroyed the chances of a semantic and accessible HTML email. Even still, providing alt text is important from an image blocking perspective. Even with images suppressed by default, many email clients will display the provided alt text instead. Just remember that some email clients like Outlook 2007, Hotmail and Apple Mail don\u2019t support alt text at all when images are blocked.\n\nUse the display hack for Hotmail\n\nFor some inexplicable reason, Windows Live Hotmail adds a few pixels of additional padding below images. A workaround is to set the display property like so.\n\nimg {display:block;}\n\nThis removes the padding in Hotmail and still gives you the predicable result in other email clients.\n\nDon\u2019t use floats\n\nBoth Outlook 2007 and earlier versions of Notes offer no support for the float property. Instead, use the align attribute of the img tag to float images in your email.\n\n\n\nIf you\u2019re seeing strange image behavior in Yahoo! Mail, adding align=\u201ctop\u201d to your images can often solve this problem.\n\nVideo in email\n\nWith no support for JavaScript or the object tag, video in email (if you can call it that) has long been limited to animated gifs. However, some recent research I did into the HTML5 video tag in email showed some promising results.\n\nTurns out HTML5 video does work in many email clients right now, including Apple Mail, Entourage 2008, MobileMe and the iPhone. The real benefit of this approach is that if the video isn\u2019t supported, you can provide reliable fallback content such as an animated GIF or a clickable image linking to the video in the browser.\n\nOf course, the question of whether you should add video to email is another issue altogether. If you lean toward the \u201cyes\u201d side check out the technique with code samples.\n\nWhat about mobile email?\n\nThe mobile email landscape was a huge mess until recently. With the advent of the iPhone, Android and big improvements from Palm and RIM, it\u2019s becoming less important to think of mobile as a different email platform altogether.\n\nThat said, there are a few key pointers to keep in mind when coding your emails to get a decent result for your more mobile subscribers.\n\nKeep the width less than 600 pixels\n\nBecause of email client preview panes, this rule was important long before mobile email clients came of age. In truth, the iPhone and Pre have a viewport of 320 pixels, the Droid 480 pixels and the Blackberry models hover around 360 pixels. Sticking to a maximum of 600 pixels wide ensures your design should still be readable when scaled down for each device. This width also gives good results in desktop and web-based preview panes.\n\nBe aware of automatic text resizing\n\nIn what is almost always a good feature, email clients using webkit (such as the iPhone, Pre and Android) can automatically adjust font sizes to increase readability. If testing shows this feature is doing more harm than good to your design, you can always disable it with the following CSS rule:\n\n-webkit-text-size-adjust: none;\n\nDon\u2019t forget to test\n\nWhile standards support in email clients hasn\u2019t made much progress in the last few years, there has been continual change (for better or worse) in some email clients. Web-based providers like Yahoo!, Hotmail and Gmail are notorious for this. On countless occasions I\u2019ve seen a proven design suddenly stop working without explanation.\n\nFor this reason alone it\u2019s important to retest your email designs on a regular basis. I find a quick test every month or so does the trick, especially in the web-based clients. The good news is that after designing and testing a few HTML email campaigns, you will find that order will emerge from the chaos. Many of these pitfalls will become quite predictable and your inbox-friendly designs will take shape with them in mind.\n\nLooking ahead\n\nDesigning HTML email can be a tough pill for new designers and standardistas to swallow, especially given the fickle and retrospective nature of email clients today. With HTML5 just around the corner we are entering a new, uncertain phase. Will email client developers take the opportunity to repent on past mistakes and bring email clients into the present? The aim of groups such as the Email Standards Project is to make much of the above advice as redundant as the long-forgotten and tags, however, only time will tell if this is to become a reality.\n\nAlthough not the most compliant (or fashionable) medium, the results speak for themselves \u2013 email is, and will continue to be one of the most successful and targeted marketing channels available to you. As a designer with HTML email design skills in your arsenal, you have the opportunity to not only broaden your service offering, but gain a unique appreciation of how vital standards are.\n\nNext steps\n\nReady to get started? There are a number of HTML email design galleries to provide ideas and inspiration for your own designs. \n\n\n\thttp://www.campaignmonitor.com/gallery/\n\thttp://htmlemailgallery.com/\n\thttp://inboxaward.com/\n\n\nEnjoy!", "year": "2009", "author": "David Greiner", "author_slug": "davidgreiner", "published": "2009-12-13T00:00:00+00:00", "url": "https://24ways.org/2009/rock-solid-html-emails/", "topic": "code"} {"rowid": 175, "title": "Front-End Code Reusability with CSS and JavaScript", "contents": "Most web standards-based developers are more than familiar with creating their sites with semantic HTML with lots and lots of CSS. With each new page in a design, the CSS tends to grow and grow and more elements and styles are added. But CSS can be used to better effect.\n\nThe idea of object-oriented CSS isn\u2019t new. Nicole Sullivan has written a presentation on the subject and outlines two main concepts: separate structure and visual design; and separate container and content. Jeff Croft talks about Applying OOP Concepts to CSS:\n\n\n\tI can make a class of .box that defines some basic layout structure, and another class of .rounded that provides rounded corners, and classes of .wide and .narrow that define some widths, and then easily create boxes of varying widths and styles by assigning multiple classes to an element, without having to duplicate code in my CSS.\n\n\nThis concept helps reduce CSS file size, allows for great flexibility, rapid building of similar content areas and means greater consistency throughout the entire design. You can also take this concept one step further and apply it to site behaviour with JavaScript.\n\nBuild a versatile slideshow\n\nI will show you how to build multiple slideshows using jQuery, allowing varying levels of functionality which you may find on one site design. The code will be flexible enough to allow you to add previous/next links, image pagination and the ability to change the animation type. More importantly, it will allow you to apply any combination of these features.\n\nImage galleries are simply a list of images, so the obvious choice of marking the content up is to use a
    . Many designs, however, do not cater to non-JavaScript versions of the website, and thus don\u2019t take in to account large multiple images. You could also simply hide all the other images in the list, apart from the first image. This method can waste bandwidth because the other images might be downloaded when they are never going to be seen.\n\nTaking this second concept \u2014 only showing one image \u2014 the only code you need to start your slideshow is an tag. The other images can be loaded dynamically via either a per-page JavaScript array or via AJAX.\n\nThe slideshow concept is built upon the very versatile Cycle jQuery Plugin and is structured in to another reusable jQuery plugin. Below is the HTML and JavaScript snippet needed to run every different type of slideshow I have mentioned above.\n\n\"About\n\n\nSlideshow plugin\n\nIf you\u2019re not familiar with jQuery or how to write and author your own plugin there are plenty of articles to help you out.\n\njQuery has a chainable interface and this is something your plugin must implement. This is easy to achieve, so your plugin simply returns the collection it is using:\n\nreturn this.each(\n\tfunction () {}\n};\n\nLocal Variables\n\nTo keep the JavaScript clean and avoid any conflicts, you must set up any variables which are local to the plugin and should be used on each collection item. Defining all your variables at the top under one statement makes adding more and finding which variables are used easier. For other tips, conventions and improvements check out JSLint, the \u201cJavaScript Code Quality Tool\u201d.\n\nvar $$, $div, $images, $arrows, $pager,\n\tid, selector, path, o, options,\n\theight, width,\n\tlist = [], li = 0,\n\tparts = [], pi = 0,\n\tarrows = ['Previous', 'Next'];\n\nCache jQuery Objects\n\nIt is good practice to cache any calls made to jQuery. This reduces wasted DOM calls, can improve the speed of your JavaScript code and makes code more reusable.\n\nThe following code snippet caches the current selected DOM element as a jQuery object using the variable name $$. Secondly, the plugin makes its settings available to the Metadata plugin\u2021 which is best practice within jQuery plugins.\n\nFor each slideshow the plugin generates a
    with a class of slideshow and a unique id. This is used to wrap the slideshow images, pagination and controls.\n\nThe base path which is used for all the images in the slideshow is calculated based on the existing image which appears on the page. For example, if the path to the image on the page was /img/flowers/1.jpg the plugin would use the path /img/flowers/ to load the other images.\n\n$$ = $(this);\no = $.metadata ? $.extend({}, settings, $$.metadata()) : settings;\nid = 'slideshow-' + (i++ + 1);\n$div = $('
    ').addClass('slideshow').attr('id', id);\nselector = '#' + id + ' ';\npath = $$.attr('src').replace(/[0-9]\\.jpg/g, '');\noptions = {};\nheight = $$.height();\nwidth = $$.width();\n\nNote: the plugin uses conventions such as folder structure and numeric filenames. These conventions help with the reusable aspect of plugins and best practices.\n\nBuild the Images\n\nThe cycle plugin uses a list of images to create the slideshow. Because we chose to start with one image we must now build the list programmatically. This is a case of looping through the images which were added via the plugin options, building the appropriate HTML and appending the resulting
      to the DOM.\n\n$.each(o.images, function () {\n\tlist[li++] = '
    • ';\n\tlist[li++] = '';\n\tlist[li++] = '
    • ';\n});\n$images = $('
        ').addClass('cycle-images');\n$images.append(list.join('')).appendTo($div);\n\nAlthough jQuery provides the append method it is much faster to create one really long string and append it to the DOM at the end.\n\nUpdate the Options\n\nHere are some of the options we\u2019re making available by simply adding classes to the . You can change the slideshow effect from the default fade to the sliding effect. By adding the class of stopped the slideshow will not auto-play and must be controlled via pagination or previous and next links.\n\n// different effect\nif ($$.is('.slide')) {\n\toptions.fx = 'scrollHorz';\n}\n// don't move by default\nif ($$.is('.stopped')) {\n\toptions.timeout = 0;\n}\n\nIf you are using the same set of images throughout a website you may wish to start on a different image on each page or section. This can be easily achieved by simply adding the appropriate starting class to the .\n\n// based on the class name on the image\nif ($$.is('[class*=start-]')) {\n\toptions.startingSlide = parseInt($$.attr('class').replace(/.*start-([0-9]+).*/g, \"$1\"), 10) - 1;\n}\n\nFor example:\n\n\"About\n\nBy default, and without JavaScript, the third image in this slideshow is shown. When the JavaScript is applied to the page the slideshow must know to start from the correct place, this is why the start class is required.\n\nYou could capture the default image name and parse it to get the position, but only the default image needs to be numeric to work with this plugin (and could easily be changed in future). Therefore, this extra specifically defined option means the plugin is more tolerant.\n\nPrevious/Next Links\n\nA common feature of slideshows is previous and next links enabling the user to manually progress the images. The Cycle plugin supports this functionality, but you must generate the markup yourself. Most people add these directly in the HTML but normally only support their behaviour when JavaScript is enabled. This goes against progressive enhancement. To keep with the best practice progress enhancement method the previous/next links should be generated with JavaScript.\n\nThe follow snippet checks whether the slideshow requires the previous/next links, via the arrows class. It restricts the Cycle plugin to the specific slideshow using the selector we created at the top of the plugin. This means multiple slideshows can run on one page without conflicting each other.\n\nThe code creates a
          using the arrows array we defined at the top of the plugin. It also adds a class to the slideshow container, meaning you can style different combinations of options in your CSS.\n\n// create the arrows\nif ($$.is('.arrows') && list.length > 1) {\n\toptions.next = selector + '.next';\n\toptions.prev = selector + '.previous';\n\t$arrows = $('
            ').addClass('cycle-arrows');\n\t$.each(arrows, function (i, val) {\n\t\tparts[pi++] = '
          • ';\n\t\tparts[pi++] = '';\n\t\tparts[pi++] = '' + val + '';\n\t\tparts[pi++] = '';\n\t\tparts[pi++] = '
          • ';\n\t});\n\t$arrows.append(parts.join('')).appendTo($div);\n\t$div.addClass('has-cycle-arrows');\n}\n\nThe arrow array could be placed inside the plugin settings to allow for localisation.\n\nPagination\n\nThe Cycle plugin creates its own HTML for the pagination of the slideshow. All our plugin needs to do is create the list and selector to use. This snippet creates the pagination container and appends it to our specific slideshow container. It sets the Cycle plugin pager option, restricting it to the specific slideshow using the selector we created at the top of the plugin. Like the previous/next links, a class is added to the slideshow container allowing you to style the slideshow itself differently.\n\n// create the clickable pagination\nif ($$.is('.pagination') && list.length > 1) {\n\toptions.pager = selector + '.cycle-pagination';\n\t$pager = $('
              ').addClass('cycle-pagination');\n\t$pager.appendTo($div);\n\t$div.addClass('has-cycle-pagination');\n}\n\nNote: the Cycle plugin creates a
                with anchors listed directly inside without the surrounding
              • . Unfortunately this is invalid markup but the code still works.\n\nDemos\n\nWell, that describes all the ins-and-outs of the plugin, but demos make it easier to understand! Viewing the source on the demo page shows some of the combinations you can create with a simple , a few classes and some thought-out JavaScript.\n\nView the demos \u2192\n\nDecide on defaults\n\nThe slideshow plugin uses the exact same settings as the Cycle plugin, but some are explicitly set within the slideshow plugin when using the classes you have set.\n\nWhen deciding on what functionality is going to be controlled via this class method, be careful to choose your defaults wisely. If all slideshows should auto-play, don\u2019t make this an option \u2014 make the option to stop the auto-play. Similarly, if every slideshow should have previous/next functionality make this the default and expose the ability to remove them with a class such as \u201cno-pagination\u201d.\n\nIn the examples presented on this article I have used a class on each . You can easily change this to anything you want and simply apply the plugin based on the jQuery selector required.\n\nGrab your images\n\nIf you are using AJAX to load in your images, you can speed up development by deciding on and keeping to a folder structure and naming convention. There are two methods: basing the image path based on the current URL; or based on the src of the image. The first allows a different slideshow on each page, but in many instances a site will have a couple of sets of images and therefore the second method is probably preferred.\n\nMetadata \u2021\n\nA method which allows you to directly modify settings in certain plugins, which also uses the classes from your HTML already exists. This is a jQuery plugin called Metadata. This method allows for finer control over the plugin settings themselves. Some people, however, may dislike the syntax and prefer using normal classes, like above which when sprinkled with a bit more JavaScript allows you to control what you need to control.\n\nThe takeaway\n\nHopefully you have understood not only what goes in to a basic jQuery plugin but also learnt a new and powerful idea which you can apply to other areas of your website.\n\nThe idea can also be applied to other common interfaces such as lightboxes or mapping services such as Google Maps \u2014 for example creating markers based on a list of places, each with different pin icons based the anchor class.", "year": "2009", "author": "Trevor Morris", "author_slug": "trevormorris", "published": "2009-12-06T00:00:00+00:00", "url": "https://24ways.org/2009/front-end-code-reusability-with-css-and-javascript/", "topic": "code"} {"rowid": 177, "title": "HTML5: Tool of Satan, or Yule of Santa?", "contents": "It would lead to unseasonal arguments to discuss the title of this piece here, and the arguments are as indigestible as the fourth turkey curry of the season, so we\u2019ll restrict our article to the practical rather than the philosophical: what HTML5 can you reasonably expect to be able to use reliably cross-browser in the early months of 2010?\n\nThe answer is that you can use more than you might think, due to the seasonal tinsel of feature-detection and using the sparkly pixie-dust of IE-only VML (but used in a way that won\u2019t damage your Elf).\n\nCanvas\n\ncanvas is a 2D drawing API that defines a blank area of the screen of arbitrary size, and allows you to draw on it using JavaScript. The pictures can be animated, such as in this canvas mashup of Wolfenstein 3D and Flickr. (The difference between canvas and SVG is that SVG uses vector graphics, so is infinitely scalable. It also keeps a DOM, whereas canvas is just pixels so you have to do all your own book-keeping yourself in JavaScript if you want to know where aliens are on screen, or do collision detection.)\n\nPreviously, you needed to do this using Adobe Flash or Java applets, requiring plugins and potentially compromising keyboard accessibility. Canvas drawing is supported now in Opera, Safari, Chrome and Firefox. The reindeer in the corner is, of course, Internet Explorer, which currently has zero support for canvas (or SVG, come to that).\n\nNow, don\u2019t pull a face like all you\u2019ve found in your Yuletide stocking is a mouldy satsuma and a couple of nuts\u2014that\u2019s not the end of the story. Canvas was originally an Apple proprietary technology, and Internet Explorer had a similar one called Vector Markup Language which was submitted to the W3C for standardisation in 1998 but which, unlike canvas, was not blessed with retrospective standardisation.\n\nWhat you need, then, is some way for Internet Explorer to translate canvas to VML on-the-fly, while leaving the other, more standards-compliant browsers to use the HTML5. And such a way exists\u2014it\u2019s a JavaScript library called excanvas. It\u2019s downloadable from http://code.google.com/p/explorercanvas/ and it\u2019s simple to include it via a conditional comment in the head for IE:\n\n\n\nSimply include this, and your canvas will be natively supported in the modern browsers (and the library won\u2019t even be downloaded) whereas IE will suddenly render your canvas using its own VML engine. Be sure, however, to check it carefully, as the IE JavaScript engine isn\u2019t so fast and you\u2019ll need to be sure that performance isn\u2019t too degraded to use.\n\nForms\n\nSince the beginning of the Web, developers have been coding forms, and then writing JavaScript to check whether an input is a correctly formed email address, URL, credit card number or conforms to some other pattern. The cumulative labour of the world\u2019s developers over the last 15 years makes whizzing round in a sleigh and delivering presents seem like popping to the corner shop in comparison.\n\nWith HTML5, that\u2019s all about to change. As Yaili began to explore on Day 3, a host of new attributes to the input element provide built-in validation for email address formats (input type=email), URLs (input type=url), any pattern that can be expressed with a JavaScript-syntax regex (pattern=\"[0-9][A-Z]{3}\") and the like. New attributes such as required, autofocus, input type=number min=3 max=50 remove much of the tedious JavaScript from form validation.\n\nOther, really exciting input types are available (see all input types). The datalist is reminiscent of a select box, but allows the user to enter their own text if they don\u2019t want to choose one of the pre-defined options. input type=range is rendered as a slider, while input type=date pops up a date picker, all natively in the browser with no JavaScript required at all.\n\nCurrently, support is most complete in an experimental implementation in Opera and a number of the new attributes in Webkit-based browsers. But don\u2019t let that stop you! The clever thing about the specification of the new Web Forms is that all the new input types are attributes (rather than elements). input defaults to input type=text, so if a browser doesn\u2019t understand a new HTML5 type, it gracefully degrades to a plain text input.\n\nSo where does that leave validation in those browsers that don\u2019t support Web Forms? The answer is that you don\u2019t retire your pre-existing JavaScript validation just yet, but you leave it as a fallback after doing some feature detection. To detect whether (say) input type=email is supported, you make a new input type=email with JavaScript but don\u2019t add it to the page. Then, you interrogate your new element to find out what its type attribute is. If it\u2019s reported back as \u201cemail\u201d, then the browser supports the new feature, so let it do its work and don\u2019t bring in any JavaScript validation. If it\u2019s reported back as \u201ctext\u201d, it\u2019s fallen back to the default, indicating that it\u2019s not supported, so your code should branch to your old validation routines. Alternatively, use the small (7K) Modernizr library which will do this work for you and give you JavaScript booleans like Modernizr.inputtypes[email] set to true or false.\n\nSo what does this buy you? Well, first and foremost, you\u2019re future-proofing your code for that time when all browsers support these hugely useful additions to forms. Secondly, you buy a usability and accessibility win. Although it\u2019s tempting to style the stuffing out of your form fields (which can, incidentally, lead to madness), whatever your branding people say, it\u2019s better to leave forms as close to the browser defaults as possible. A browser\u2019s slider and date pickers will be the same across different sites, making it much more comprehensible to users. And, by using native controls rather than faking sliders and date pickers with JavaScript, your forms are much more likely to be accessible to users of assistive technology.\n\nHTML5 DOCTYPE\n\nYou can use the new DOCTYPE !doctype html now and \u2013 hey presto \u2013 you\u2019re writing HTML5, as it\u2019s pretty much a superset of HTML4. There are some useful advantages to doing this. The first is that the HTML5 validator (I use http://html5.validator.nu) also validates ARIA information, whereas the HTML4 validator doesn\u2019t, as ARIA is a new spec developed after HTML4. (Actually, it\u2019s more accurate to say that it doesn\u2019t validate your ARIA attributes, but it doesn\u2019t automatically report them as an error.)\n\nAnother advantage is that HTML5 allows tabindex as a global attribute (that is, on any element). Although originally designed as an accessibility bolt-on, I ordinarily advise you don\u2019t use it; a well-structured page should provide a logical tab order through links and form fields already.\n\nHowever, tabindex=\"-1\" is a legal value in HTML5 as it allows for the element to be programmatically focussable by JavaScript. It\u2019s also very useful for correcting a bug in Internet Explorer when used with a keyboard; in-page links go nowhere if the destination doesn\u2019t have a proprietary property called hasLayout set or a tabindex of -1.\n\nSo, whether it is the tool of Satan or yule of Santa, HTML5 is just around the corner. Some you can use now, and by the end of 2010 I predict you\u2019ll be able to use a whole lot more as new browser versions are released.", "year": "2009", "author": "Bruce Lawson", "author_slug": "brucelawson", "published": "2009-12-05T00:00:00+00:00", "url": "https://24ways.org/2009/html5-tool-of-satan-or-yule-of-santa/", "topic": "code"} {"rowid": 179, "title": "Have a Field Day with HTML5 Forms", "contents": "Forms are usually seen as that obnoxious thing we have to markup and style. I respectfully disagree: forms (on a par with tables) are the most exciting thing we have to work with.\n\nHere we\u2019re going to take a look at how to style a beautiful HTML5 form using some advanced CSS and latest CSS3 techniques. I promise you will want to style your own forms after you\u2019ve read this article.\n\nHere\u2019s what we\u2019ll be creating:\n\n The form. (Icons from Chalkwork Payments)\n\nMeaningful markup\n\nWe\u2019re going to style a simple payment form. There are three main sections on this form:\n\n\n\tThe person\u2019s details\n\tThe address details\n\tThe credit card details\n\n\nWe are also going to use some of HTML5\u2019s new input types and attributes to create more meaningful fields and use less unnecessary classes and ids:\n\n\n\temail, for the email field\n\ttel, for the telephone field\n\tnumber, for the credit card number and security code\n\trequired, for required fields\n\tplaceholder, for the hints within some of the fields\n\tautofocus, to put focus on the first input field when the page loads\n\n\nThere are a million more new input types and form attributes on HTML5, and you should definitely take a look at what\u2019s new on the W3C website. Hopefully this will give you a good idea of how much more fun form markup can be.\n\nA good foundation\n\nEach section of the form will be contained within its own fieldset. In the case of the radio buttons for choosing the card type, we will enclose those options in another nested fieldset.\n\nWe will also be using an ordered list to group each label / input pair. This will provide us with a (kind of) semantic styling hook and it will also make the form easier to read when viewing with no CSS applied:\n\n The unstyled form\n\nSo here\u2019s the markup we are going to be working with:\n\n
                \n\t
                \n\t\tYour details\n\t\t
                  \n\t\t\t
                1. \n\t\t\t\t\n\t\t\t\t\n\t\t\t
                2. \n\t\t\t
                3. \n\t\t\t\t\n\t\t\t\t\n\t\t\t
                4. \n\t\t\t
                5. \n\t\t\t\t\n\t\t\t\t\n\t\t\t
                6. \n\t\t
                \n\t
                \n\t
                \n\t\tDelivery address\n\t\t
                  \n\t\t\t
                1. \n\t\t\t\t\n\t\t\t\t\n\t\t\t
                2. \n\t\t\t
                3. \n\t\t\t\t\n\t\t\t\t\n\t\t\t
                4. \n\t\t\t
                5. \n\t\t\t\t\n\t\t\t\t\n\t\t\t
                6. \n\t\t
                \n\t
                \n\t
                \n\t\tCard details\n\t\t
                  \t\t\n\t\t\t
                1. \n\t\t\t\t
                  \n\t\t\t\t\tCard type\n\t\t\t\t\t
                    \n\t\t\t\t\t\t
                  1. \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
                  2. \n\t\t\t\t\t\t
                  3. \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
                  4. \n\t\t\t\t\t\t
                  5. \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
                  6. \n\t\t\t\t\t
                  \n\t\t\t\t
                  \n\t\t\t
                2. \n\t\t\t
                3. \n\t\t\t\t\n\t\t\t\t\n\t\t\t
                4. \n\t\t\t
                5. \n\t\t\t\t\n\t\t\t\t\n\t\t\t
                6. \n\t\t\t
                7. \n\t\t\t\t\n\t\t\t\t\n\t\t\t
                8. \n\t\t
                \n\t
                \n\t
                \n\t\t\n\t
                \n
                \n\nMaking things look nice\n\nFirst things first, so let\u2019s start by adding some defaults to our form by resetting the margins and paddings of the elements and adding a default font to the page:\n\nhtml, body, h1, form, fieldset, legend, ol, li {\n\tmargin: 0;\n\tpadding: 0;\n}\nbody {\n\tbackground: #ffffff;\n\tcolor: #111111;\n\tfont-family: Georgia, \"Times New Roman\", Times, serif;\n\tpadding: 20px;\n}\n\nNext we are going to style the form element that is wrapping our fields:\n\nform#payment {\n\tbackground: #9cbc2c;\n\t-moz-border-radius: 5px;\n\t-webkit-border-radius: 5px;\n\tborder-radius: 5px;\n\tpadding: 20px;\n\twidth: 400px;\n}\n\nWe will also remove the border from the fieldset and apply some bottom margin to it. Using the :last-of-type pseudo-class, we remove the bottom margin of the last fieldset \u2014 there is no need for it:\n\nform#payment fieldset {\n\tborder: none;\n\tmargin-bottom: 10px;\n}\nform#payment fieldset:last-of-type {\n\tmargin-bottom: 0;\n}\n\nNext we\u2019ll make the legends big and bold, and we will also apply a light-green text-shadow, to add that little extra special detail:\n\nform#payment legend {\n\tcolor: #384313;\n\tfont-size: 16px;\n\tfont-weight: bold;\n\tpadding-bottom: 10px;\n\ttext-shadow: 0 1px 1px #c0d576;\n}\n\nOur legends are looking great, but how about adding a clear indication of how many steps our form has? Instead of adding that manually to every legend, we can use automatically generated counters.\n\nTo add a counter to an element, we have to use either the :before or :after pseudo-elements to add content via CSS. We will follow these steps:\n\n\n\tcreate a counter using the counter-reset property on the form element\n\tcall the counter with the content property (using the same name we\u2019ve created before)\n\twith the counter-incremet property, indicate that for each element that matches our selector, that counter will be increased by 1\n\n\nform#payment > fieldset > legend:before {\n\tcontent: \"Step \" counter(fieldsets) \": \";\n\tcounter-increment: fieldsets;\n}\n\nFinally, we need to change the style of the legend that is part of the radio buttons group, to make it look like a label:\n\nform#payment fieldset fieldset legend {\n\tcolor: #111111;\n\tfont-size: 13px;\n\tfont-weight: normal;\n\tpadding-bottom: 0;\n}\n\nStyling the lists\n\nFor our list elements, we\u2019ll just add some nice rounded corners and semi-transparent border and background. Because we are using RGBa colors, we should provide a fallback for browsers that don\u2019t support them (that comes before the RBGa color). For the nested lists, we will remove these properties because they would be overlapping:\n\nform#payment ol li {\n\tbackground: #b9cf6a;\n\tbackground: rgba(255,255,255,.3);\n\tborder-color: #e3ebc3;\n\tborder-color: rgba(255,255,255,.6);\n\tborder-style: solid;\n\tborder-width: 2px;\n\t-moz-border-radius: 5px;\n\t-webkit-border-radius: 5px;\n\tborder-radius: 5px;\n\tline-height: 30px;\n\tlist-style: none;\n\tpadding: 5px 10px;\n\tmargin-bottom: 2px;\n}\nform#payment ol ol li {\n\tbackground: none;\n\tborder: none;\n\tfloat: left;\n}\n\nForm controls\n\nNow we only need to style our labels, inputs and the button element.\n\nAll our labels will look the same, with the exception of the one for the radio elements. We will float them to the left and give them a width.\n\nFor the credit card type labels, we will add an icon as the background, and override some of the properties that aren\u2019t necessary. We will be using the attribute selector to specify the background image for each label \u2014 in this case, we use the for attribute of each label.\n\nTo add an extra user-friendly detail, we\u2019ll add a cursor: pointer to the radio button labels on the :hover state, so the user knows that he can simply click them to select that option.\n\nform#payment label {\n\tfloat: left;\n\tfont-size: 13px;\n\twidth: 110px;\n}\nform#payment fieldset fieldset label {\n\tbackground:none no-repeat left 50%;\n\tline-height: 20px;\n\tpadding: 0 0 0 30px;\n\twidth: auto;\n}\nform#payment label[for=visa] {\n\tbackground-image: url(visa.gif);\n}\nform#payment label[for=amex] {\n\tbackground-image: url(amex.gif);\n}\nform#payment label[for=mastercard] {\n\tbackground-image: url(mastercard.gif);\n}\nform#payment fieldset fieldset label:hover {\n\tcursor: pointer;\n}\n\nAlmost there! Now onto the input elements. Here we want to match all inputs, except for the radio ones, and the textarea. For that we will use the negation pseudo-class (:not()). With it we can target all input elements except for the ones with type of radio.\n\nWe will also make sure to add some :focus styles and add the appropriate styling for the radio inputs:\n\nform#payment input:not([type=radio]),\nform#payment textarea {\n\tbackground: #ffffff;\n\tborder: none;\n\t-moz-border-radius: 3px;\n\t-webkit-border-radius: 3px;\n\t-khtml-border-radius: 3px;\n\tborder-radius: 3px;\n\tfont: italic 13px Georgia, \"Times New Roman\", Times, serif;\n\toutline: none;\n\tpadding: 5px;\n\twidth: 200px;\n}\nform#payment input:not([type=submit]):focus,\nform#payment textarea:focus {\n\tbackground: #eaeaea;\n}\nform#payment input[type=radio] {\n\tfloat: left;\n\tmargin-right: 5px;\n}\n\nAnd finally we come to our submit button. To it, we will just add some nice typography and text-shadow, align it to the center of the form and give it some background colors for its different states:\n\nform#payment button {\n\tbackground: #384313;\n\tborder: none;\n\t-moz-border-radius: 20px;\n\t-webkit-border-radius: 20px;\n\t-khtml-border-radius: 20px;\n\tborder-radius: 20px;\n\tcolor: #ffffff;\n\tdisplay: block;\n\tfont: 18px Georgia, \"Times New Roman\", Times, serif;\n\tletter-spacing: 1px;\n\tmargin: auto;\n\tpadding: 7px 25px;\n\ttext-shadow: 0 1px 1px #000000;\n\ttext-transform: uppercase;\n}\nform#payment button:hover {\n\tbackground: #1e2506;\n\tcursor: pointer;\n}\n\nAnd that\u2019s it! See the completed form.\n\nThis form will not look the same on every browser. Internet Explorer and Opera don\u2019t support border-radius (at least not for now); the new input types are rendered as just normal inputs on some browsers; and some of the most advanced CSS, like the counter, :last-of-type or text-shadow are not supported on some browsers. But that doesn\u2019t mean you can\u2019t use them right now, and simplify your development process. My gift to you!", "year": "2009", "author": "Inayaili de Le\u00f3n Persson", "author_slug": "inayailideleon", "published": "2009-12-03T00:00:00+00:00", "url": "https://24ways.org/2009/have-a-field-day-with-html5-forms/", "topic": "code"} {"rowid": 180, "title": "Going Nuts with CSS Transitions", "contents": "I\u2019m going to show you how CSS 3 transforms and WebKit transitions can add zing to the way you present images on your site.\n\nLaying the foundations\n\nFirst we are going to make our images look like mini polaroids with captions. Here\u2019s the markup:\n\n
                \n\t\"\"\n\t

                Found this little cutie on a walk in New Zealand!

                \n
                \n\nYou\u2019ll notice we\u2019re using a somewhat presentational class of pull-right here. This means the logic is kept separate from the code that applies the polaroid effect. The polaroid class has no positioning, which allows it to be used generically anywhere that the effect is required. The pull classes set a float and add appropriate margins\u2014they can be used for things like blockquotes as well.\n\n.polaroid {\n\twidth: 150px;\n\tpadding: 10px 10px 20px 10px;\n\tborder: 1px solid #BFBFBF;\n\tbackground-color: white;\n\t-webkit-box-shadow: 2px 2px 3px rgba(135, 139, 144, 0.4);\n\t-moz-box-shadow: 2px 2px 3px rgba(135, 139, 144, 0.4);\n\tbox-shadow: 2px 2px 3px rgba(135, 139, 144, 0.4);\n}\n\nThe actual polaroid effect itself is simply applied using padding, a border and a background colour. We also apply a nice subtle box shadow, using a property that is supported by modern WebKit browsers and Firefox 3.5+. We include the box-shadow property last to ensure that future browsers that support the eventual CSS3 specified version natively will use that implementation over the legacy browser specific version.\n\nThe box-shadow property takes four values: three lengths and a colour. The first is the horizontal offset of the shadow\u2014positive values place the shadow on the right, while negative values place it to the left. The second is the vertical offset, positive meaning below. If both of these are set to 0, the shadow is positioned equally on all four sides. The last length value sets the blur radius\u2014the larger the number, the blurrier the shadow (therefore the darker you need to make the colour to have an effect).\n\nThe colour value can be given in any format recognised by CSS. Here, we\u2019re using rgba as explained by Drew behind the first door of this year\u2019s calendar.\n\nRotation\n\nFor browsers that understand it (currently our old favourites WebKit and FF3.5+) we can add some visual flair by rotating the image, using the transform CSS 3 property.\n\n-webkit-transform: rotate(9deg);\n-moz-transform: rotate(9deg);\ntransform: rotate(9deg);\n\nRotations can be specified in degrees, radians (rads) or grads. WebKit also supports turns unfortunately Firefox doesn\u2019t just yet.\n\nFor our example, we want any polaroid images on the left hand side to be rotated in the opposite direction, using a negative degree value:\n\n.pull-left.polaroid {\n\t-webkit-transform: rotate(-9deg);\n\t-moz-transform: rotate(-9deg);\n\ttransform: rotate(-9deg);\n}\n\nMultiple class selectors don\u2019t work in IE6 but as luck would have it, the transform property doesn\u2019t work in any current IE version either. The above code is a good example of progressive enrichment: browsers that don\u2019t support box-shadow or transform will still see the image and basic polaroid effect.\n\n\n\nAnimation\n\nWebKit is unique amongst browser rendering engines in that it allows animation to be specified in pure CSS. Although this may never actually make it in to the CSS 3 specification, it degrades nicely and more importantly is an awful lot of fun!\n\nLet\u2019s go nuts.\n\nIn the next demo, the image is contained within a link and mousing over that link causes the polaroid to animate from being angled to being straight.\n\nHere\u2019s our new markup:\n\n\n\t\"\"\n\tWhite water rafting in Queenstown\n\n\nAnd here are the relevant lines of CSS:\n\na.polaroid {\n\t/* ... */\n -webkit-transform: rotate(10deg);\n -webkit-transition: -webkit-transform 0.5s ease-in;\n}\na.polaroid:hover,\na.polaroid:focus,\na.polaroid:active {\n\t/* ... */\n\t-webkit-transform: rotate(0deg);\n}\n\nThe @-webkit-transition@ property is the magic wand that sets up the animation. It takes three values: the property to be animated, the duration of the animation and a \u2018timing function\u2019 (which affects the animation\u2019s acceleration, for a smoother effect).\n\n-webkit-transition only takes affect when the specified property changes. In pure CSS, this is done using dynamic pseudo-classes. You can also change the properties using JavaScript, but that\u2019s a story for another time.\n\nThrowing polaroids at a table\n\nImagine there are lots of differently sized polaroid photos scattered on a table. That\u2019s the effect we are aiming for with our next demo.\n\n\n\nAs an aside: we are using absolute positioning to arrange the images inside a flexible width container (with a minimum and maximum width specified in pixels). As some are positioned from the left and some from the right when you resize the browser they shuffle underneath each other. This is an effect used on the UX London site.\n\nThis demo uses a darker colour shadow with more transparency than before. The grey shadow in the previous example worked fine, but it was against a solid background. Since the images are now overlapping each other, the more opaque shadow looked fake.\n\n-webkit-box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);\n-moz-box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);\nbox-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);\n\nOn hover, as well as our previous trick of animating the image rotation back to straight, we are also making the shadow darker and setting the z-index to be higher than the other images so that it appears on top.\n\nAnd Finally\u2026\n\nFinally, for a bit more fun, we\u2019re going to simulate the images coming towards you and lifting off the page. We\u2019ll achieve this by making them grow larger and by offsetting the shadow & making it longer.\n\n\n\n\nScreenshot 1 shows the default state, while 2 shows our previous hover effect. Screenshot 3 is the effect we are aiming for, illustrated by demo 4.\n\na.polaroid {\n\t/* ... */\n\tz-index: 2;\n\t-webkit-box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);\n\t-moz-box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);\n\tbox-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);\n\t-webkit-transform: rotate(10deg);\n\t-moz-transform: rotate(10deg);\n\ttransform: rotate(10deg);\n\t-webkit-transition: all 0.5s ease-in;\n}\na.polaroid:hover,\na.polaroid:focus,\na.polaroid:active {\n\tz-index: 999;\n\tborder-color: #6A6A6A;\n\t-webkit-box-shadow: 15px 15px 20px rgba(0,0, 0, 0.4);\n\t-moz-box-shadow: 15px 15px 20px rgba(0,0, 0, 0.4);\n\tbox-shadow: 15px 15px 20px rgba(0,0, 0, 0.4);\n\t-webkit-transform: rotate(0deg) scale(1.05);\n\t-moz-transform: rotate(0deg) scale(1.05);\n\ttransform: rotate(0deg) scale(1.05);\n}\n\nYou\u2019ll notice we are now giving the transform property another transform function: scale, which takes increases the size by the specified factor. Other things you can do with transform include skewing, translating or you can go mad creating your own transforms with a matrix.\n\nThe box-shadow has both its offset and blur radius increased dramatically, and is darkened using the alpha channel of the rgba colour.\n\nAnd because we want the effects to all animate smoothly, we pass a value of all to the -webkit-transition property, ensuring that any changed property on that link will be animated.\n\nDemo 5 is the finished example, bringing everything nicely together.\n\nCSS transitions and transforms are a great example of progressive enrichment, which means improving the experience for a portion of the audience without negatively affecting other users. They are also a lot of fun to play with!\n\nFurther reading\n\n\n\t-moz-transform \u2013 the mozilla developer center has a comprehensive explanation of transform that also applies to -webkit-transform and transform.\n\tCSS: Animation Using CSS Transforms \u2013 this is a good, more indepth tutorial on animations.\n\tCSS Animation \u2013 the Safari blog explains the usage of -webkit-transform.\n\tDinky pocketbooks with transform \u2013 another use for transforms, create your own printable pocketbook.\n\tA while back, Simon wrote a little bookmarklet to spin the entire page\u2026 warning: this will spin the entire page.", "year": "2009", "author": "Natalie Downe", "author_slug": "nataliedowne", "published": "2009-12-14T00:00:00+00:00", "url": "https://24ways.org/2009/going-nuts-with-css-transitions/", "topic": "code"} {"rowid": 181, "title": "Working With RGBA Colour", "contents": "When Tim and I were discussing the redesign of this site last year, one of the clear goals was to have a graphical style without making the pages heavy with a lot of images. When we launched, a lot of people were surprised that the design wasn\u2019t built with PNGs. Instead we\u2019d used RGBA colour values, which is part of the CSS3 specification.\n\nWhat is RGBA Colour?\n\nWe\u2019re all familiar with specifying colours in CSS using by defining the mix of red, green and blue light required to achieve our tone. This is fine and dandy, but whatever values we specify have one thing in common \u2014 the colours are all solid, flat, and well, a bit boring.\n\n Flat RGB colours\n\nCSS3 introduces a couple of new ways to specify colours, and one of those is RGBA. The A stands for Alpha, which refers to the level of opacity of the colour, or to put it another way, the amount of transparency. This means that we can set not only the red, green and blue values, but also control how much of what\u2019s behind the colour shows through. Like with layers in Photoshop.\n\nDon\u2019t We Have Opacity Already?\n\nThe ability to set the opacity on a colour differs subtly from setting the opacity on an element using the CSS opacity property. Let\u2019s look at an example.\n\nHere we have an H1 with foreground and background colours set against a page with a patterned background.\n\n Heading with no transparency applied\n\nh1 {\n\tcolor: rgb(0, 0, 0);\n\tbackground-color: rgb(255, 255, 255);\n}\n\nBy setting the CSS opacity property, we can adjust the transparency of the entire element and its contents:\n\n Heading with 50% opacity on the element\n\nh1 {\n\tcolor: rgb(0, 0, 0);\n\tbackground-color: rgb(255, 255, 255);\n\topacity: 0.5;\n}\n\nRGBA colour gives us something different \u2013 the ability to control the opacity of the individual colours rather than the entire element. So we can set the opacity on just the background:\n\n 50% opacity on just the background colour\n\nh1 {\n\tcolor: rgb(0, 0, 0);\n\tbackground-color: rgba(255, 255, 255, 0.5);\n}\n\nOr leave the background solid and change the opacity on just the text:\n\n 50% opacity on just the foreground colour\n\nh1 {\n\tcolor: rgba(0, 0, 0, 0.5);\n\tbackground-color: rgb(255, 255, 255);\n}\n\nThe How-To\n\nYou\u2019ll notice that above I\u2019ve been using the rgb() syntax for specifying colours. This is a bit less common than the usual hex codes (like #FFF) but it makes sense when starting to use RGBA. As there\u2019s no way to specify opacity with hex codes, we use rgba() like so:\n\ncolor: rgba(255, 255, 255, 0.5);\n\nJust like rgb() the first three values are red, green and blue. You can specify these 0-255 or 0%-100%. The fourth value is the opacity level from 0 (completely transparent) to 1 (completely opaque).\n\nYou can use this anywhere you\u2019d normally set a colour in CSS \u2014 so it\u2019s good for foregrounds and background, borders, outlines and so on. All the transparency effects on this site\u2019s current design are achieved this way.\n\nSupporting All Browsers\n\nLike a lot of the features we\u2019ll be looking at in this year\u2019s 24 ways, RGBA colour is supported by a lot of the newest browsers, but not the rest. Firefox, Safari, Chrome and Opera browsers all support RGBA, but Internet Explorer does not.\n\nFortunately, due to the robust design of CSS as a language, we can specify RGBA colours for browsers that support it and an alternative for browsers that do not.\n\nFalling back to solid colour\n\nThe simplest technique is to allow the browser to fall back to using a solid colour when opacity isn\u2019t available. The CSS parsing rules specify that any unrecognised value should be ignored. We can make use of this because a browser without RGBA support will treat a colour value specified with rgba() as unrecognised and discard it.\n\nSo if we specify the colour first using rgb() for all browsers, we can then overwrite it with an rgba() colour for browsers that understand RGBA.\n\nh1 {\n\tcolor: rgb(127, 127, 127);\n\tcolor: rgba(0, 0, 0, 0.5);\n}\n\nFalling back to a PNG\n\nIn cases where you\u2019re using transparency on a background-color (although not on borders or text) it\u2019s possible to fall back to using a PNG with alpha channel to get the same effect. This is less flexible than using CSS as you\u2019ll need to create a new PNG for each level of transparency required, but it can be a useful solution.\n\nUsing the same principal as before, we can specify the background in a style that all browsers will understand, and then overwrite it in a way that browsers without RGBA support will ignore.\n\nh1 {\n\tbackground: transparent url(black50.png);\n\tbackground: rgba(0, 0, 0, 0.5) none;\n}\n\nIt\u2019s important to note that this works because we\u2019re using the background shorthand property, enabling us to set both the background colour and background image in a single declaration. It\u2019s this that enables us to rely on the browser ignoring the second declaration when it encounters the unknown rgba() value.\n\nNext Steps\n\nThe really great thing about RGBA colour is that it gives us the ability to create far more graphically rich designs without the need to use images. Not only does that make for faster and lighter pages, but sites which are easier and quicker to build and maintain. CSS values can also be changed in response to user interaction or even manipulated with JavaScript in a way that\u2019s just not so easy using images.\n\n Opacity can be changed on :hover or manipulated with JavaScript\n\ndiv {\n\tcolor: rgba(255, 255, 255, 0.8);\n\tbackground-color: rgba(142, 213, 87, 0.3);\n}\ndiv:hover {\n\tcolor: rgba(255, 255, 255, 1);\n\tbackground-color: rgba(142, 213, 87, 0.6);\n}\n\nClever use of transparency in border colours can help ease the transition between overlay items and the page behind.\n\n Borders can receive the RGBA treatment, too\n\ndiv {\n\tcolor: rgb(0, 0, 0);\n\tbackground-color: rgb(255, 255, 255);\n\tborder: 10px solid rgba(255, 255, 255, 0.3);\n}\n\nIn Conclusion\n\n\nThat\u2019s a brief insight into RGBA colour, what it\u2019s good for and how it can be used whilst providing support for older browsers. With the current lack of support in Internet Explorer, it\u2019s probably not a technique that commercial designs will want to heavily rely on right away \u2013 simply because of the overhead of needing to think about fallback all the time. \n\nIt is, however, a useful tool to have for those smaller, less critical touches that can really help to finesse a design. As browser support becomes more mainstream, you\u2019ll already be familiar and practised with RGBA and ready to go.", "year": "2009", "author": "Drew McLellan", "author_slug": "drewmclellan", "published": "2009-12-01T00:00:00+00:00", "url": "https://24ways.org/2009/working-with-rgba-colour/", "topic": "code"} {"rowid": 182, "title": "Breaking Out The Edges of The Browser", "contents": "HTML5 contains more than just the new entities for a more meaningful document, it also contains an arsenal of JavaScript APIs. So many in fact, that some APIs have outgrown the HTML5 spec\u2019s backyard and have been sent away to grow up all on their own and been given the prestigious honour of being specs in their own right.\n\nSo when I refer to (bendy finger quote) \u201cHTML5\u201d, I mean the HTML5 specification and a handful of other specifications that help us authors build web applications.\n\nExamples of those specs I would include in the umbrella term would be: geolocation, web storage, web databases, web sockets and web workers, to name a few.\n\nFor all you guys and gals, on this special 2009 series of 24 ways, I\u2019m just going to focus on data storage and offline applications: boldly taking your browser where no browser has gone before!\n\nWeb Storage\n\nThe Web Storage API is basically cookies on steroids, a unhealthy dosage of steroids. Cookies are always a pain to work with. First of all you have the problem of setting, changing and deleting them. Typically solved by Googling and blindly relying on PPK\u2019s solution. If that wasn\u2019t enough, there\u2019s the 4Kb limit that some of you have hit when you really don\u2019t want to.\n\nThe Web Storage API gets around all of the hoops you have to jump through with cookies. Storage supports around 5Mb of data per domain (the spec\u2019s recommendation, but it\u2019s open to the browsers to implement anything they like) and splits in to two types of storage objects:\n\n\n\tsessionStorage \u2013 available to all pages on that domain while the window remains open\n\tlocalStorage \u2013 available on the domain until manually removed\n\n\nSupport\n\nIgnoring beta browsers for our support list, below is a list of the major browsers and their support for the Web Storage API:\n\n\n\tLatest: Internet Explorer, Firefox, Safari (desktop & mobile/iPhone)\n\tPartial: Google Chrome (only supports localStorage)\n\tNot supported: Opera (as of 10.10)\n\n\nUsage\n\nBoth sessionStorage and localStorage support the same interface for accessing their contents, so for these examples I\u2019ll use localStorage.\n\nThe storage interface includes the following methods:\n\n\n\tsetItem(key, value)\n\tgetItem(key)\n\tkey(index)\n\tremoveItem(key)\n\tclear()\n\n\nIn the simple example below, we\u2019ll use setItem and getItem to store and retrieve data:\n\nlocalStorage.setItem('name', 'Remy');\nalert( localStorage.getItem('name') );\n\nUsing alert boxes can be a pretty lame way of debugging. Conveniently Safari (and Chrome) include database tab in their debugging tools (cmd+alt+i), so you can get a visual handle on the state of your data:\n\n Viewing localStorage\n\nAs far as I know only Safari has this view on stored data natively in the browser. There may be a Firefox plugin (but I\u2019ve not found it yet!) and IE\u2026 well that\u2019s just IE.\n\nEven though we\u2019ve used setItem and getItem, there\u2019s also a few other ways you can set and access the data.\n\nIn the example below, we\u2019re accessing the stored value directly using an expando and equally, you can also set values this way:\n\nlocalStorage.name = \"Remy\";\nalert( localStorage.name ); // shows \"Remy\"\n\nThe Web Storage API also has a key method, which is zero based, and returns the key in which data has been stored. This should also be in the same order that you set the keys, for example:\n\nalert( localStorage.getItem(localStorage.key(0)) ); \n// shows \"Remy\"\n\nI mention the key() method because it\u2019s not an unlikely name for a stored value. This can cause serious problems though.\n\nWhen selecting the names for your keys, you need to be sure you don\u2019t take one of the method names that are already on the storage object, like key, clear, etc. As there are no warnings when you try to overwrite the methods, it means when you come to access the key() method, the call breaks as key is a string value and not a function.\n\nYou can try this yourself by creating a new stored value using localStorage.key = \"foo\" and you\u2019ll see that the Safari debugger breaks because it relies on the key() method to enumerate each of the stored values.\n\nUsage Notes\n\nCurrently all browsers only support storing strings. This also means if you store a numeric, it will get converted to a string:\n\nlocalStorage.setItem('count', 31);\nalert(typeof localStorage.getItem('count')); \n// shows \"string\"\n\nThis also means you can\u2019t store more complicated objects natively with the storage objects. To get around this, you can use Douglas Crockford\u2019s JSON parser (though Firefox 3.5 has JSON parsing support baked in to the browser \u2013 yay!) json2.js to convert the object to a stringified JSON object:\n\nvar person = {\n\tname: 'Remy',\n\theight: 'short',\n\tlocation: 'Brighton, UK'\n};\nlocalStorage.setItem('person', JSON.stringify(person));\nalert( JSON.parse(localStorage.getItem('person')).name ); \n// shows \"Remy\"\n\nAlternatives\n\nThere are a few solutions out there that provide storage solutions that detect the Web Storage API, and if it\u2019s not available, fall back to different technologies (for instance, using a flash object to store data). One comprehensive version of this is Dojo\u2019s storage library. I\u2019m personally more of a fan of libraries that plug missing functionality under the same namespace, just as Crockford\u2019s JSON parser does (above).\n\nFor those interested it what that might look like, I\u2019ve mocked together a simple implementation of sessionStorage. Note that it\u2019s incomplete (because it\u2019s missing the key method), and it could be refactored to not using the JSON stringify (but you would need to ensure that the values were properly and safely encoded):\n\n// requires json2.js for all browsers other than Firefox 3.5\nif (!window.sessionStorage && JSON) {\n\twindow.sessionStorage = (function () {\n\t\t// window.top.name ensures top level, and supports around 2Mb\n\t\tvar data = window.top.name ? JSON.parse(window.top.name) : {};\n\t\treturn { \n\t\t\tsetItem: function (key, value) {\n\t\t\t\tdata[key] = value+\"\"; // force to string\n\t\t\t\twindow.top.name = JSON.stringify(data);\n\t\t\t},\n\t\t\tremoveItem: function (key) {\n\t\t\t\tdelete data[key];\n\t\t\t\twindow.top.name = JSON.stringify(data); \n\t\t\t},\n\t\t\tgetItem: function (key) {\n\t\t\t\treturn data[key] || null;\n\t\t\t},\n\t\t\tclear: function () {\n\t\t\t\tdata = {};\n\t\t\t\twindow.top.name = '';\n\t\t\t}\n\t\t};\n\t})();\n}\n\nNow that we\u2019ve cracked the cookie jar with our oversized Web Storage API, let\u2019s have a look at how we take our applications offline entirely.\n\nOffline Applications\n\nOffline applications is (still) part of the HTML5 specification. It allows developers to build a web app and have it still function without an internet connection. The app is access via the same URL as it would be if the user were online, but the contents (or what the developer specifies) is served up to the browser from a local cache. From there it\u2019s just an everyday stroll through open web technologies, i.e. you still have access to the Web Storage API and anything else you can do without a web connection.\n\nFor this section, I\u2019ll refer you to a prototype demo I wrote recently of a contrived Rubik\u2019s cube (contrived because it doesn\u2019t work and it only works in Safari because I\u2019m using 3D transforms).\n\n Offline Rubik\u2019s cube\n\nSupport\n\nSupport for offline applications is still fairly limited, but the possibilities of offline applications is pretty exciting, particularly as we\u2019re seeing mobile support and support in applications such as Fluid (and I would expect other render engine wrapping apps).\n\nSupport currently, is as follows:\n\n\n\tLatest: Safari (desktop & mobile/iPhone)\n\tSort of: Firefox\u2021\n\tNot supported: Internet Explorer, Opera, Google Chrome\n\n\n\u2021 Firefox 3.5 was released to include offline support, but in fact has bugs where it doesn\u2019t work properly (certainly on the Mac), Minefield (Firefox beta) has resolved the bug.\n\nUsage\n\nThe status of the application\u2019s cache can be tested from the window.applicationCache object. However, we\u2019ll first look at how to enable your app for offline access.\n\nYou need to create a manifest file, which will tell the browser what to cache, and then we point our web page to that cache:\n\n\n\n\n\nFor the manifest to be properly read by the browser, your server needs to serve the .manifest files as text/manifest by adding the following to your mime.types:\n\ntext/cache-manifest manifest\n\nNext we need to populate our manifest file so the browser can read it:\n\nCACHE MANIFEST\n/demo/rubiks/index.html\n/demo/rubiks/style.css\n/demo/rubiks/jquery.min.js\n/demo/rubiks/rubiks.js\n# version 15\n\nThe first line of the manifest must read CACHE MANIFEST. Then subsequent lines tell the browser what to cache.\n\nThe HTML5 spec recommends that you include the calling web page (in my case index.html), but it\u2019s not required. If I didn\u2019t include index.html, the browser would cache it as part of the offline resources.\n\nThese resources are implicitly under the CACHE namespace (which you can specify any number of times if you want to).\n\nIn addition, there are two further namespaces: NETWORK and FALLBACK.\n\nNETWORK is a whitelist namespace that tells the browser not to cache this resource and always try to request it through the network.\n\nFALLBACK tells the browser that whilst in offline mode, if the resource isn\u2019t available, it should return the fallback resource.\n\nFinally, in my example I\u2019ve included a comment with a version number. This is because once you include a manifest, the only way you can tell the browser to reload the resources is if the manifest contents changes. So I\u2019ve included a version number in the manifest which I can change forcing the browser to reload all of the assets.\n\nHow it works\n\nIf you\u2019re building an app that makes use of the offline cache, I would strongly recommend that you add the manifest last. The browser implementations are very new, so can sometimes get a bit tricky to debug since once the resources are cached, they really stick in the browser.\n\nThese are the steps that happen during a request for an app with a manifest:\n\n\n\tBrowser: sends request for your app.html\n\tServer: serves all associated resources with app.html \u2013 as normal\n\tBrowser: notices that app.html has a manifest, it re-request the assets in the manifest\n\tServer: serves the requested manifest assets (again)\n\tBrowser: window.applicationCache has a status of UPDATEREADY\n\tBrowser: reloads\n\tBrowser: only request manifest file (which doesn\u2019t show on the net requests panel)\n\tServer: responds with 304 Not Modified on the manifest file\n\tBrowser: serves all the cached resources locally\n\n\nWhat might also add confusion to this process, is that the way the browsers work (currently) is if there is a cache already in place, it will use this first over updated resources. So if your manifest has changed, the browser will have already loaded the offline cache, so the user will only see the updated on the next reload. \n\nThis may seem a bit convoluted, but you can also trigger some of this manually through the applicationCache methods which can ease some of this pain.\n\nIf you bind to the online event you can manually try to update the offline cache. If the cache has then updated, swap the updated resources in to the cache and the next time the app loads it will be up to date. You could also prompt your user to reload the app (which is just a refresh) if there\u2019s an update available.\n\nFor example (though this is just pseudo code):\n\naddEvent(applicationCache, 'updateready', function () {\n\tapplicationCache.swapCache();\n\ttellUserToRefresh();\n});\naddEvent(window, 'online', function () {\n\tapplicationCache.update();\n});\n\nBreaking out of the Browser\n\nSo that\u2019s two different technologies that you can use to break out of the traditional browser/web page model and get your apps working in a more application-ny way.\n\nThere\u2019s loads more in the HTML5 and non-HTML5 APIs to play with, so take your Christmas break to check them out!", "year": "2009", "author": "Remy Sharp", "author_slug": "remysharp", "published": "2009-12-02T00:00:00+00:00", "url": "https://24ways.org/2009/breaking-out-the-edges-of-the-browser/", "topic": "code"} {"rowid": 184, "title": "Spruce It Up", "contents": "The landscape of web typography is changing quickly these days. We\u2019ve gone from the wild west days of sIFR to Cuf\u00f3n to finally seeing font embedding seeing wide spread adoption by browser developers (and soon web designers) with @font-face. For those who\u2019ve felt limited by the typographic possibilities before, this has been a good year.\n\nAs Mark Boulton has so eloquently elucidated, @font-face embedding doesn\u2019t come without its drawbacks. Font files can be quite large and FOUT\u2014that nasty flash of unstyled text\u2014can be a distraction for users.\n\nData URIs\n\nWe can battle FOUT by using Data URIs. A Data URI allows the font to be encoded right into the CSS file. When the font comes with the CSS, the flash of unstyled text is mitigated. No extra HTTP requests are required. \n\nDon\u2019t be a grinch, though. Sending hundreds of kilobytes down the pipe still isn\u2019t great. Sometimes, all we want to do is spruce up our site with a little typographic sugar. \n\nBe Selective\n\nDan Cederholm\u2019s SimpleBits is an attractive site. \n\n\n\nTake a look at the ampersand within the header of his site. It\u2019s the lovely (and free) Goudy Bookletter 1911 available from The League of Movable Type. The Opentype format is a respectable 28KB. Nothing too crazy but hold on here. Mr. Cederholm is only using the ampersand! Ouch. That\u2019s a lot of bandwidth just for one character.\n\nCan we optimize a font like we can an image? Yes. Image optimization essentially works by removing unnecessary image data such as colour data, hidden comments or using compression algorithms. How do you remove unnecessary information from a font? Subsetting. \n\nIf you\u2019re the adventurous type, grab a copy of FontForge, which is an open source font editing tool. You can open the font, view and edit any of the glyphs and then re-generate the font. The interface is a little clunky but you\u2019ll be able to select any character you don\u2019t want and then cut the glyphs. Re-generate your font and you\u2019ve now got a smaller file. \n\n\n\nThere are certainly more optimizations that can also be made such as removing hinting and kerning information. Keep in mind that removing this information may affect how well the type renders.\n\nAt this time of year, though, I\u2019m sure you\u2019re quite busy. Save yourself some time and head on over to the Font Squirrel Font Generator.\n\n\n\nThe Font Generator is extremely handy and allows for a number of optimizations and cross-platform options to be generated instantly. Select the font from your local system\u2014make sure that you are only using properly licensed fonts! \n\nIn this particular case, we only want the ampersand. Click on Subset Fonts which will open up a new menu. Unselect any preselected sets and enter the ampersand into the Single Characters text box. \n\nGenerate your font and what are you left with? 3KB. \n\n\n\nThe Font Generator even generates a base64 encoded data URI stylesheet to be imported easily into your project.\n\nCheck out the Demo page. (This demo won\u2019t work in Internet Explorer as we\u2019re only demonstrating the Data URI font embedding and not using the EOT file format that IE requires.) \n\nNo Unnecessary Additives\n\nIf you peeked under the hood of that demo, did you notice something interesting? There\u2019s no around the ampersand. The great thing about this is that we can take advantage of the font stack\u2019s natural ability to switch to a fallback font when a character isn\u2019t available.\n\nJust like that, we\u2019ve managed to spruce up our page with a little typographic sugar without having to put on too much weight.", "year": "2009", "author": "Jonathan Snook", "author_slug": "jonathansnook", "published": "2009-12-19T00:00:00+00:00", "url": "https://24ways.org/2009/spruce-it-up/", "topic": "code"} {"rowid": 186, "title": "The Web Is Your CMS", "contents": "It is amazing what you can do these days with the services offered on the web. Flickr stores terabytes of photos for us and converts them automatically to all kind of sizes, finds people in them and even allows us to edit them online. YouTube does almost the same complete job with videos, LinkedIn allows us to maintain our CV, Delicious our bookmarks and so on.\n\nWe don\u2019t have to do these tasks ourselves any more, as all of these systems also come with ways to use the data in the form of Application Programming Interfaces, or APIs for short. APIs give us raw data when we send requests telling the system what we want to get back.\n\nThe problem is that every API has a different idea of what is a simple way of accessing this data and in which format to give it back.\n\nMaking it easier to access APIs\n\nWhat we need is a way to abstract the pains of different data formats and authentication formats away from the developer \u2014 and this is the purpose of the Yahoo Query Language, or YQL for short. \n\nLibraries like jQuery and YUI make it easy and reliable to use JavaScript in browsers (yes, even IE6) and YQL allows us to access web services and even the data embedded in web documents in a simple fashion \u2013 SQL style.\n\nSelect * from the web and filter it the way I want\n\nYQL is a web service that takes a few inputs itself:\n\n\n\tA query that tells it what to get, update or access\n\tAn output format \u2013 XML, JSON, JSON-P or JSON-P-X\n\tA callback function (if you defined JSON-P or JSON-P-X)\n\n\nYou can try it out yourself \u2013 check out this link to get back Flickr photos for the search term \u2018santa\u2019*%20from%20flickr.photos.search%20where%20text%3D%22santa%22&format=xml in XML format. The YQL query for this is \n\nselect * from flickr.photos.search where text=\"santa\"\n\nThe easiest way to take your first steps with YQL is to look at the console. There you get sample queries, access to all the data sources available to you and you can easily put together complex queries. In this article, however, let\u2019s use PHP to put together a web page that pulls in Flickr photos, blog posts, Videos from YouTube and latest bookmarks from Delicious.\n\nCheck out the demo and get the source code on GitHub.\n\nquery->results->results;\n /* YouTube output */\n $youtube = '
                  ';\n foreach($results[0]->item as $r){\n\t$cleanHTML = undoYouTubeMarkupCrimes($r->description);\n\t$youtube .= '
                • '.$cleanHTML.'
                • ';\n }\n $youtube .= '
                ';\n /* Flickr output */\n $flickr = '';\n /* Delicious output */\n $delicious = '';\n /* Blog output */\n $blog = '';\n function undoYouTubeMarkupCrimes($str){\n\t$cleaner = preg_replace('/555px/','100%',$str);\n\t$cleaner = preg_replace('/width=\"[^\"]+\"/','',$cleaner);\n\t$cleaner = preg_replace('//','',$cleaner);\n\treturn $cleaner;\n }\n?>\n\nWhat we are doing here is create a few different YQL statements and queue them together with the query.multi table. Each of these can be run inside YQL itself. Check out the YouTube, Flickr, Delicious and Blog example in the console if you don\u2019t believe me. The benefit of using this table is that we don\u2019t make individual requests for each query but we get all the data in one single request \u2013 which means a much better performing solution as the YQL server farm is faster on the web than our servers.\n\nWe point the query to the YQL web service end point and get the resulting data using cURL. All that we need to do then is to convert the returned data to HTML lists that can be printed out inside an HTML template.\n\nMixing, matching and using HTML as a data source\n\nThis was a simple example of what YQL can do for you. Where it gets really powerful however is by mixing and matching different APIs. YQL is also a good tool to get information from HTML documents. By using the html table you can load the content of an HTML document (which gets fixed automatically by HTMLTidy) and use XPATH to filter down results to what you need. Take the following example which takes headlines from the news.bbc.co.uk homepage and runs the results through Yahoo\u2019s Term Extractor API to give you a list of currently hot topics.\n\nselect * from search.termextract where context in (\n select content from html where url=\"http://news.bbc.co.uk\" and xpath=\"//table[@width=800]//a\"\n)\n\nTry it out in the console or see the results here. In English, this means:\n\n\n\tGo to http://news.bbc.co.uk and get me the HTML\n\tRun it through HTML Tidy to clean it up.\n\tGet me only the links inside the table with an attribute of width and the value 800\n\tGet only the content of the link and for each of the links\n\t\n\t\tTake the content and send it as context to the Yahoo Term Extractor API\n\t\n\t\n\nIf we choose JSON-P as the output format we can use the outcome directly in JavaScript (see this demo or see its source):\n\n
                  \n\n\n\nUsing JSON, we can also use PHP which means the demo works for everybody \u2013 not only those with JavaScript enabled (see this demo or see its source):\n\n
                  • \nquery->results->Result);\necho join('
                  • ',$topics);\n?>\n
                  \n\nSummary\n\nThis article could only scratch the surface of YQL. You have not only read access to the web but you can also write to web services. For example you can update Twitter, post to your WordPress blog or shorten a URL with bit.ly. Using Open Tables you can add any web service to the YQL interface and you can even run server-side JavaScript which is for example useful to return Flickr photos as HTML or get the HTML content from a document that needs POST data.\n\nThe web of data is already here, and using YQL you don\u2019t have to be a web services expert to use it and be part of it.", "year": "2009", "author": "Christian Heilmann", "author_slug": "chrisheilmann", "published": "2009-12-17T00:00:00+00:00", "url": "https://24ways.org/2009/the-web-is-your-cms/", "topic": "code"} {"rowid": 188, "title": "Don't Lose Your :focus", "contents": "For many web designers, accessibility conjures up images of blind users with screenreaders, and the difficulties in making sites accessible to this particular audience. Of course, accessibility covers a wide range of situations that go beyond the extreme example of screenreader users. And while it\u2019s true that making a complex site accessible can often be a daunting prospect, there are also many small things that don\u2019t take anything more than a bit of judicious planning, are very easy to test (without having to buy expensive assistive technology), and can make all the difference to certain user groups.\n\nIn this short article we\u2019ll focus on keyboard accessibility and how careless use of CSS can potentially make your sites completely unusable.\n\nKeyboard Access\n\nUsers who for whatever reason can\u2019t use a mouse will employ a keyboard (or keyboard-like custom interface) to navigate around web pages. By default, they will use TAB and SHIFT + TAB to move from one focusable element (links, form controls and area) of a page to the next.\n\nNote: in OS X, you\u2019ll first need to turn on full keyboard access under System Preferences > Keyboard and Mouse > Keyboard Shortcuts. Safari under Windows needs to have the option Press Tab to highlight each item on a webpage in Preferences > Advanced enabled. Opera is the odd one out, as it has a variety of keyboard navigation options \u2013 the most relevant here being spatial navigation via Shift+Down, Shift+Up, Shift+Left, and Shift+Right).\n\nBut I Don\u2019t Like Your Dotted Lines\u2026\n\nTo show users where they are within a page, browsers place an outline around the element that currently has focus. The \u201cproblem\u201d with these default outlines is that some browsers (Internet Explorer and Firefox) also display them when a user clicks on a focusable element with the mouse. Particularly on sites that make extensive use of image replacement on links with \u201coff left\u201d techniques this can create very unsightly outlines that stretch from the replaced element all the way to the left edge of the browser.\n\n Outline bleeding off to the left (image-replacement example from carsonified.com)\n\nThere is a trivial workaround to prevent outlines from \u201cspilling over\u201d by adding a simple overflow:hidden, which keeps the outline in check around the clickable portion of the image-replaced element itself.\n\n Outline tamed with overflow:hidden\n\nBut for many designers, even this is not enough. As a final solution, many actively suppress outlines altogether in their stylesheets. Controversially, even Eric Meyer\u2019s popular reset.css \u2013 an otherwise excellent set of styles that levels the playing field of varying browser defaults \u2013 suppresses outlines.\n\nhtml, body, div, span, applet, object, iframe ... {\n\t...\n\toutline: 0;\n\t...\n}\n/* remember to define focus styles! */\n:focus {\n\toutline: 0;\n}\n\nYes, in his explanation (and in the CSS itself) Eric does remind designers to define relevant styles for :focus\u2026 but judging by the number of sites that seem to ignore this (and often remove the related comment from the stylesheet altogether), the message doesn\u2019t seem to have sunk in.\n\nAnyway\u2026 hurrah! No more unsightly dotted lines on our lovely design. But what about keyboard users? Although technically they can still TAB from one element to the next, they now get no default cue as to where they are within the page (one notable exception here is Opera, where the outline is displayed regardless of stylesheets)\u2026 and if they\u2019re Safari users, they won\u2019t even get an indication of a link\u2019s target in the status bar, like they would if they hovered over it with the mouse.\n\nOnly Suppress outline For Mouse Users\n\nIs there a way to allow users navigating with the keyboard to retain the standard outline behaviour they\u2019ve come to expect from their browser, while also ensuring that it doesn\u2019t show display for mouse users?\n\n Testing some convoluted style combinations\n\nAfter playing with various approaches (see Better CSS outline suppression for more details), the most elegant solution also seemed to be the simplest: don\u2019t remove the outline on :focus, do it on :active instead \u2013 after all, :active is the dynamic pseudo-class that deals explicitly with the styles that should be applied when a focusable element is clicked or otherwise activated.\n\na:active { outline: none; }\n\nThe only minor issues with this method: if a user activates a link and then uses the browser\u2019s back button, the outline becomes visible. Oh, and old versions of Internet Explorer notoriously get confused by the exact meaning of :focus, :hover and :active, so this method fails in IE6 and below. Personally, I can live with both of these.\n\nNote: at the last minute before submitting this article, I discovered a fatal flaw in my test. It appears that outline still manages to appear in the time between activating a link and the link target loading (which in hindsight is logical \u2013 after activation, the link does indeed receive focus). As my test page only used in-page links, this issue never came up before. The slightly less elegant solution is to also suppress the outline on :hover.\n\na:hover, a:active { outline: none; }\n\nIn Conclusion\n\nOf course, many web designers may argue that they know what\u2019s best, even for their keyboard-using audience. Maybe they\u2019ve removed the default outline and are instead providing some carefully designed :focus styles. If they know for sure that these custom styles are indeed a reliable alternative for their users, more power to them\u2026 but, at the risk of sounding like Jakob \u201cblue underlined links\u201d Nielsen, I\u2019d still argue that sometimes the default browser behaviours are best left alone. Complemented, yes (and if you\u2019re already defining some fancy styles for :hover, by all means feel free to also make them display on :focus)\u2026 but not suppressed.", "year": "2009", "author": "Patrick Lauke", "author_slug": "patricklauke", "published": "2009-12-09T00:00:00+00:00", "url": "https://24ways.org/2009/dont-lose-your-focus/", "topic": "code"} {"rowid": 191, "title": "CSS Animations", "contents": "Friend: You should learn how to write CSS!\nMe: \u2026\nFriend: CSS; Cascading Style Sheets. If you\u2019re serious about web design, that\u2019s the next thing you should learn.\nMe: What\u2019s wrong with tags?\n\nThat was 8 years ago. Thanks to the hard work of Jeffrey, Andy, Andy, Cameron, Colly, Dan and many others, learning how to decently markup a website and write lightweight stylesheets was surprisingly easy. They made it so easy even a complete idiot (OH HAI) was able to quickly master it.\n\nAnd then\u2026 nothing. For a long time, it seemed like there wasn\u2019t happening anything in the land of CSS, time stood still. Once you knew the basics, there wasn\u2019t anything new to keep up with. It looked like a great band split, but people just kept re-releasing their music in various \u201cBest Of!\u201d or \u201cRemastered!\u201d albums.\n\nFast forward a couple of years to late 2006. On the official WebKit blog Surfin\u2019 Safari, there\u2019s an article about something called CSS animations. Great new stuff to play with, but only supported by nightly builds (read: very, very beta) of WebKit. In the following months, they release other goodies, like CSS gradients, CSS reflections, CSS masks, and even more CSS animation sexiness. Whoa, looks like the band got back together, found their second youth, and went into overdrive! The problem was that if you wanted to listen to their new albums, you had to own some kind of new high-tech player no one on earth (besides some early adopters) owned.\n\nBack in the time machine. It is now late 2009, close to Christmas. Things have changed. Browsers supporting these new toys are widely available left and right. Even non-techies are using these advanced browsers to surf the web on a daily basis!\n\nEpic win? Almost, but at least this gives us enough reason to start learning how we could use all this new CSS voodoo. On Monday, Natalie Downe showed you a good tutorial on Going Nuts with CSS Transitions. Today, I\u2019m taking it one step further\u2026\n\nHowto: A basic spinner\n\nNo matter how fast internet tubes or servers are, we\u2019ll always need spinners to indicate something\u2019s happening behind the scenes. Up until now, people would go to some site, pick one of the available templates, customize their foreground and background colors, and download a beautiful GIF image.\n\nThere are some downsides to this though:\n\n\n\tIt\u2019s only _semi_-transparent: If you change your mind and pick a slightly different background color, you need to go back to the site, set all the parameters again, and replace your current image. There isn\u2019t even a way to pick an image or gradient as background.\n\tLimited number of frames, probable to keep the file-size as small as possible (don\u2019t forget this thing needs to be loaded before whatever process is finished in the background), and you don\u2019t have that 24 frames per second smoothness.\n\tThis is just too fucking easy. As a front-end code geek, there must be a \u201ccooler\u201d way to do this!\n\n\nWhat do we need to make a spinner with CSS animations? One image, and one element on our webpage we can hook on to. Yes, that\u2019s it. I created a simple transparent PNG that looks it might be a spinner, and for the element on the page, I wrote this piece of genius HTML:\n\n

                  Please wait while we do what we do best.

                  \n\nLooks semantic enough to me! Here\u2019s the basic HTML I\u2019m using to position the element in the center of the screen, and make the text inside it disappear:\n\n#spinner {\n\tposition: absolute;\n\ttop: 50%;\n\tleft: 50%;\n\tmargin: -100px 0 0 -100px;\n\theight: 200px;\n\twidth: 200px;\n\ttext-indent: 250px;\n\twhite-space: nowrap;\n\toverflow: hidden;\n}\n\nCool, but now we don\u2019t see anything. Let\u2019s pull rabbit number one out of the hat: -webkit-mask-image (accompanied by the previously mentioned transparent PNG image):\n\n#spinner {\n\t...\n\t-webkit-mask-image: url(../img/spinner.png);\n}\n\nBy now you should be feeling like a magician already. Oh, wait, we still have a blank screen, looks like we left something in the hat (tip: not rabbit droppings):\n\n#spinner {\n\t...\n\t-webkit-mask-image: url(../img/spinner.png);\n\tbackground-color: #000;\n}\n\nNice! What we\u2019ve done right here is telling the element to clip onto the PNG. It\u2019s a lot like clipping layers in Photoshop. So, spinners, they move, right? Into the hat again, and look what we pull out this time: CSS animations!\n\n#spinner {\n\t...\n\t-webkit-mask-image: url(../img/spinner.png);\n\tbackground-color: #000;\n\t-webkit-animation-name: spinnerRotate;\n\t-webkit-animation-duration: 2s;\n\t-webkit-animation-iteration-count: infinite;\n\t-webkit-animation-timing-function: linear;\n}\n\nSome explanation:\n\n\n\t-webkit-animation-name: Name of the animation we\u2019ll be defining later.\n\t-webkit-animation-duration: The timespan of the animation.\n\t-webkit-animation-iteration-count: Repeat once, a defined number of times or infinitely?\n\t-webkit-animation-timing-function: Linear is the one you\u2019ll be using mostly. Other options are ease-in, ease-out, ease-in-out\u2026\n\n\nLet\u2019s define spinnerRotate:\n\n@-webkit-keyframes spinnerRotate {\n\tfrom {\n\t\t-webkit-transform:rotate(0deg);\n\t}\n\tto {\n\t\t-webkit-transform:rotate(360deg);\n\t}\n}\n\nEn Anglais: Rotate #spinner starting at 0 degrees, ending at 360 degrees, over a timespan of 2 seconds, at a constant speed, and keep repeating this animation forever.\n\nThat\u2019s it! See it in action on the demo page.\n\nNote: these examples only work when you\u2019re using a WebKit-based browser like Safari, Mobile Safari or Google Chrome. I\u2019m confident though that Mozilla and Opera will try their very best catching up with all this new CSS goodness soon.\n\nWhen looking at this example, you see the possibilities are endless. Another advantage is you can change the look of it entirely by only changing a couple of lines of CSS, instead of re-creating and re-downloading the image from some website smelling like web 2.0 gone bad. I made another demo that shows how great it is to be able to change background and foreground colors (even on the fly!).\n\nSo there you have it, a smoothly animated, fully transparent and completely customizable spinner. Cool? I think so. (Ladies?)\n\nBut you can do a lot more with CSS animations than just create pretty spinners. Since I was fooling around with it anyway, I decided to test how far you can push this, space is the final limit, right?\n\nConclusion\n\nCSS has never been more exciting than it is right now. I\u2019m even prepared to say CSS is \u201ccool\u201d again, both for the more experienced front-end developers as for the new designers discovering CSS every day now.\n\nBut\u2026\n\nRemember when Javascript became popular? Remember when Flash became popular? Every time we\u2019re been given new toys, some people aren\u2019t ashamed to use it in a way you can barely call constructive. I\u2019m thinking of Geocities websites, loaded with glowing blocks of text, moving images, bad color usage\u2026 In the wise words of Stan Lee: With great power there must also come great responsibility! A sprinkle of CSS animations is better than a bucket load. Apply with care.", "year": "2009", "author": "Tim Van Damme", "author_slug": "timvandamme", "published": "2009-12-15T00:00:00+00:00", "url": "https://24ways.org/2009/css-animations/", "topic": "code"} {"rowid": 192, "title": "Cleaner Code with CSS3 Selectors", "contents": "The parts of CSS3 that seem to grab the most column inches on blogs and in articles are the shiny bits. Rounded corners, text shadow and new ways to achieve CSS layouts are all exciting and bring with them all kinds of possibilities for web design. However what really gets me, as a developer, excited is a bit more mundane. \n\nIn this article I\u2019m going to take a look at some of the ways our front and back-end code will be simplified by CSS3, by looking at the ways we achieve certain visual effects now in comparison to how we will achieve them in a glorious, CSS3-supported future. I\u2019m also going to demonstrate how we can use these selectors now with a little help from JavaScript \u2013 which can work out very useful if you find yourself in a situation where you can\u2019t change markup that is being output by some server-side code.\n\nThe wonder of nth-child\n\nSo why does nth-child get me so excited? Here is a really common situation, the designer would like the tables in the application to look like this:\n\n\n\nSetting every other table row to a different colour is a common way to enhance readability of long rows. The tried and tested way to implement this is by adding a class to every other row. If you are writing the markup for your table by hand this is a bit of a nuisance, and if you stick a row in the middle you have to change the rows the class is applied to. If your markup is generated by your content management system then you need to get the server-side code to add that class \u2013 if you have access to that code.\n\n\n\n\nStriping every other row - using classes\n\n\n\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t
                  NameCards sentCards receivedCards written but not sent
                  Ann40284
                  Joe22729
                  Paul5352
                  Louise65650
                  \n\n\n\nView Example 1\n\nThis situation is something I deal with on almost every project, and apart from being an extra thing to do, it just isn\u2019t ideal having the server-side code squirt classes into the markup for purely presentational reasons. This is where the nth-child pseudo-class selector comes in. The server-side code creates a valid HTML table for the data, and the CSS then selects the odd rows with the following selector:\n\ntr:nth-child(odd) td {\n\tbackground-color: #86B486;\n}\n\nView Example 2\n\nThe odd and even keywords are very handy in this situation \u2013 however you can also use a multiplier here. 2n would be equivalent to the keyword \u2018odd\u2019 3n would select every third row and so on.\n\nBrowser support\n\nSadly, nth-child has pretty poor browser support. It is not supported in Internet Explorer 8 and has somewhat buggy support in some other browsers. Firefox 3.5 does have support. In some situations however, you might want to consider using JavaScript to add this support to browsers that don\u2019t have it. This can be very useful if you are dealing with a Content Management System where you have no ability to change the server-side code to add classes into the markup.\n\nI\u2019m going to use jQuery in these examples as it is very simple to use the same CSS selector used in the CSS to target elements with jQuery \u2013 however you could use any library or write your own function to do the same job. In the CSS I have added the original class selector to the nth-child selector:\n\ntr:nth-child(odd) td, tr.odd td {\n\tbackground-color: #86B486;\n}\n\nThen I am adding some jQuery to add a class to the markup once the document has loaded \u2013 using the very same nth-child selector that works for browsers that support it. \n\n \n \n\nView Example 3\n\nWe could just add a background colour to the element using jQuery, however I prefer not to mix that information into the JavaScript as if we change the colour on our table rows I would need to remember to change it both in the CSS and in the JavaScript.\n\nDoing something different with the last element\n\nSo here\u2019s another thing that we often deal with. You have a list of items all floated left with a right hand margin on each element constrained within a fixed width layout. If each element has the right margin applied the margin on the final element will cause the set to become too wide forcing that last item down to the next row as shown in the below example where I have used a grey border to indicate the fixed width.\n\n\n\nCurrently we have two ways to deal with this. We can put a negative right margin on the list, the same width as the space between the elements. This means that the extra margin on the final element fills that space and the item doesn\u2019t drop down. \n\n\n\n\nThe last item is different\n\n\n\n\t
                  \n\t\t
                    \n\t\t\t
                  • \"baubles\"
                  • \n\t\t\t
                  • \"star\"
                  • \n\t\t\t
                  • \"wreath\"
                  • \n\t\t
                  \n\t
                  \n\n\n\nView Example 4\n\nThe other solution will be to put a class on the final element and in the CSS remove the margin for this class. \n\nul.gallery li.last {\n\tmargin-right: 0;\n}\n\nThis second solution may not be easy if the content is generated from server-side code that you don\u2019t have access to change.\n\nIt could all be so different. In CSS3 we have marvellously common-sense selectors such as last-child, meaning that we can simply add rules for the last list item. \n\nul.gallery li:last-child {\n\tmargin-right: 0;\n}\n\nView Example 5\n\nThis removed the margin on the li which is the last-child of the ul with a class of gallery. No messing about sticking classes on the last item, or pushing the width of the item out wit a negative margin.\n\nIf this list of items repeated ad infinitum then you could also use nth-child for this task. Creating a rule that makes every 3rd element margin-less.\n\nul.gallery li:nth-child(3n) {\n\tmargin-right: 0;\n}\n\nView Example 6\n\n\n\nA similar example is where the designer has added borders to the bottom of each element \u2013 but the last item does not have a border or is in some other way different. Again, only a class added to the last element will save you here if you cannot rely on using the last-child selector.\n\nBrowser support for last-child\n\nThe situation for last-child is similar to that of nth-child, in that there is no support in Internet Explorer 8. However, once again it is very simple to replicate the functionality using jQuery. Adding our .last class to the last list item.\n\n$(\"ul.gallery li:last-child\").addClass(\"last\");\n\nWe could also use the nth-child selector to add the .last class to every third list item.\n\n$(\"ul.gallery li:nth-child(3n)\").addClass(\"last\");\n\nView Example 7\n\nFun with forms\n\nStyling forms can be a bit of a trial, made difficult by the fact that any CSS applied to the input element will effect text fields, submit buttons, checkboxes and radio buttons. As developers we are left adding classes to our form fields to differentiate them. In most builds all of my text fields have a simple class of text whereas I wouldn\u2019t dream of adding a class of para to every paragraph element in a document.\n\n\n\n\nSyling form fields\n\n\n\n\t

                  Send your Christmas list to Santa

                  \n\t
                  \n\t\t
                  \n\t\t
                  \n\t\t
                  \n\t\t
                  \n\t\t
                  \n\t\t
                  \n\t\t
                  \n\t
                  \n\n\n\nView Example 8\n\nAttribute selectors provide a way of targeting elements by looking at the attributes of those elements. Unlike the other examples in this article which are CSS3 selectors, the attribute selector is actually a CSS2.1 selector \u2013 it just doesn\u2019t get much use because of lack of support in Internet Explorer 6. Using attribute selectors we can write rules for text inputs and form buttons without needing to add any classes to the markup. For example after removing the text and button classes from my text and submit button input elements I can use the following rules to target them:\n\nform input[type=\"text\"] {\n border: 1px solid #333;\n padding: 0.2em;\n width: 400px;\n}\nform input[type=\"submit\"]{\n border: 1px solid #333;\n background-color: #eee;\n color: #000;\n padding: 0.1em;\n} \n\nView Example 9\n\nAnother problem that I encounter with forms is where I am using CSS to position my labels and form elements by floating the labels. This works fine as long as I want all of my labels to be floated, however sometimes we get a set of radio buttons or a checkbox, and I don\u2019t want the label field to be floated. As you can see in the below example the label for the checkbox is squashed up into the space used for the other labels, yet it makes more sense for the checkbox to display after the text.\n\n\n\nI could use a class on this label element however CSS3 lets me to target the label attribute directly by looking at the value of the for attribute.\n\nlabel[for=\"fOptIn\"] {\n float: none;\n width: auto;\n}\n\n\n\nBeing able to precisely target attributes in this way is incredibly useful, and once IE6 is no longer an issue this will really help to clean up our markup and save us from having to create all kinds of special cases when generating this markup on the server-side.\n\nBrowser support\n\nThe news for attribute selectors is actually pretty good with Internet Explorer 7+, Firefox 2+ and all other modern browsers all having support. As I have already mentioned this is a CSS2.1 selector and so we really should expect to be able to use it as we head into 2010! Internet Explorer 7 has slightly buggy support and will fail on the label example shown above however I discovered a workaround in the Sitepoint CSS reference comments. Adding the selector label[htmlFor=\"fOptIn\"] to the correct selector will create a match for IE7.\n\nIE6 does not support these selector but, once again, you can use jQuery to plug the holes in IE6 support. The following jQuery will add the text and button classes to your fields and also add a checks class to the label for the checkbox, which you can use to remove the float and width for this element.\n\n$('form input[type=\"submit\"]').addClass(\"button\");\n$('form input[type=\"text\"]').addClass(\"text\");\n$('label[for=\"fOptIn\"]').addClass(\"checks\");\n\nView Example 10\n\nThe selectors I\u2019ve used in this article are easy to overlook as we do have ways to achieve these things currently. As developers \u2013 especially when we have frameworks and existing code that cope with these situations \u2013 it is easy to carry on as we always have done. \n\nI think that the time has come to start to clean up our front and backend code and replace our reliance on classes with these more advanced selectors. With the help of a little JavaScript almost all users will still get the full effect and, where we are dealing with purely visual effects, there is definitely a case to be made for not worrying about the very small percentage of people with old browsers and no JavaScript. They will still receive a readable website, it may just be missing some of the finesse offered to the modern browsing experience.", "year": "2009", "author": "Rachel Andrew", "author_slug": "rachelandrew", "published": "2009-12-20T00:00:00+00:00", "url": "https://24ways.org/2009/cleaner-code-with-css3-selectors/", "topic": "code"}