{"rowid": 101, "title": "Easing The Path from Design to Development", "contents": "As a web developer, I have the pleasure of working with a lot of different designers. There has been a lot of industry discussion of late about designers and developers, focusing on how different we sometimes are and how the interface between our respective phases of a project (that is to say moving from a design phase into production) can sometimes become a battleground.\n\nI don\u2019t believe it has to be a battleground. It\u2019s actually more like being a dance partner \u2013 our steps are different, but as long as we know our own part and have a little knowledge of our partner\u2019s steps, it all goes together to form a cohesive dance. Albeit with less spandex and fewer sequins (although that may depend on the project in question).\n\nAs the process usually flows from design towards development, it\u2019s most important that designers have a little knowledge of how the site is going to be built. At the specialist web development agency I\u2019m part of, we find that designs that have been well considered from a technical perspective help to keep the project on track and on budget.\n\nBased on that experience, I\u2019ve put together my checklist of things that designers should consider before handing their work over to a developer to build.\n\nLayout\n\nOne rookie mistake made by traditionally trained designers transferring to the web is to forget a web browser is not a fixed medium. Unlike designing a magazine layout or a piece of packaging, there are lots of available options to consider. Should the layout be fluid and resize with the window, or should it be set to a fixed width? If it\u2019s fluid, which parts expand and which not? If it\u2019s fixed, should it sit in the middle of the window or to one side?\n\nIf any part of the layout is going to be flexible (get wider and narrower as required), consider how any graphics are affected. Images don\u2019t usually look good if displayed at anything other that their original size, so should they behave? If a column is going to get wider than it\u2019s shown in the Photoshop comp, it may be necessary to provide separate wider versions of any background images.\n\nText size and content volume\n\nA related issue is considering how the layout behaves with both different sizes of text and different volumes of content. Whilst text zooming rather than text resizing is becoming more commonplace as the default behaviour in browsers, it\u2019s still a fundamentally important principal of web design that we are suggesting and not dictating how something should look. Designs must allow for a little give and take in the text size, and how this affects the design needs to be taken into consideration.\n\nKeep in mind that the same font can display differently in different places and platforms. Something as simple as Times will display wider on a Mac than on Windows. However, the main impact of text resizing is the change in how much vertical space copy takes up. This is particularly important where space is limited by the design (making text bigger causes many more problems than making text smaller). Each element from headings to box-outs to navigation items and buttons needs to be able to expand at least vertically, if not horizontally as well. This may require some thought about how elements on the page may wrap onto new lines, as well as again making sure to provide extended versions of any graphical elements.\n\nSimilarly, it\u2019s rare theses days to know exactly what content you\u2019re working with when a site is designed. Many, if not most sites are designed as a series of templates for some kind of content management system, and so designs cannot be tweaked around any specific item of content. Designs must be able to cope with both much greater and much lesser volumes of content that might be thrown in at the lorem ipsum phase.\n\nParticular things to watch out for are things like headings (how do they wrap onto multiple lines) and any user-generated items like usernames. It can be very easy to forget that whilst you might expect something like a username to be 8-12 characters, if the systems powering your site allow for 255 characters they\u2019ll always be someone who\u2019ll go there. Expect them to do so.\n\nAgain, if your site is content managed or not, consider the possibility that the structure might be expanded in the future. Consider how additional items might be added to each level of navigation. Whilst it\u2019s rarely desirable to make significant changes without revisiting the site\u2019s information architecture more thoroughly, it\u2019s an inevitable fact of life that the structure needs a little bit of flexibility to change over time.\n\nInteractions with and without JavaScript\n\nA great number of sites now make good use of JavaScript to streamline the user interface and make everything just that touch more usable. Remember, though, that any developer worth their salt will start by building the interface without JavaScript, get it all working, and then layer that JavaScript on top. This is to allow for users viewing the site without JavaScript available or enabled in their browser.\n\nDesigners need to consider both states of any feature they\u2019re designing \u2013 how it looks and functions with and without JavaScript. If the feature does something fancy with Ajax, consider how the same can be achieved with basic HTML forms, links and intermediary pages. These all need to be designed, because this is how some of your users will interact with the site.\n\nLogged in and logged out states\n\nWhen designing any type of web application or site that has a membership system \u2013 that is to say users can create an account and log into the site \u2013 the design will need to consider how any element is presented in both logged in and logged out states. For some items there\u2019ll be no difference, whereas for others there may be considerable differences.\n\nShould an item be hidden completely not logged out users? Should it look different in some way? Perhaps it should look the same, but prompt the user to log in when they interact with it. If so, what form should that prompt take on and how does the user progress through the authentication process to arrive back at the task they were originally trying to complete?\n\nCouple logged in and logged out states with the possible absence of JavaScript, and every feature needs to be designed in four different states:\n\n\n\tLogged out with JavaScript available\n\tLogged in with JavaScript available\n\tLogged out without JavaScript available\n\tLogged in without JavaScript available\n\n\nFonts\n\nThere are three main causes of war in this world; religions, politics and fonts. I\u2019ve said publicly before that I believe the responsibility for this falls squarely at the feet of Adobe Photoshop. Photoshop, like a mistress at a brothel, parades a vast array of ropey, yet strangely enticing typefaces past the eyes of weak, lily-livered designers, who can\u2019t help but crumble to their curvy charms.\n\nYet, on the web, we have to be a little more restrained in our choice of typefaces. The purest solution is always to make the best use of the available fonts, but this isn\u2019t always the most desirable solution from a design point of view. There are several technical solutions such as techniques that utilise Flash (like sIFR), dynamically generated images and even canvas in newer browsers. Discuss the best approach with your developer, as every different technique has different trade-offs, and this may impact the design in other ways.\n\nMessaging\n\nAny site that has interactive elements, from a simple contact form through to fully featured online software application, involves some kind of user messaging. By this I mean the error messages when something goes wrong and the success and thank-you messages when something goes right. These typically appear as the result of an interaction, so are easy to forget and miss off a Photoshop comp.\n\nFor every form, consider what gets displayed to the user if they make a mistake or miss something out, and also what gets displayed back when the interaction is successful. What do they see and where do the go next?\n\nWith Ajax interactions, the user doesn\u2019t get any visual feedback of the site waiting for a response from the server unless you design it that way. Consider using a \u2018waiting\u2019 or \u2018in progress\u2019 spinner to give the user some visual feedback of any background processes. How should these look? How do they animate?\n\nSimilarly, also consider the big error pages like a 404. With luck, these won\u2019t often be seen, but it\u2019s at the point that they are when careful design matters the most.\n\nForm fields\n\nDepending on the visual style of your site, the look of a browser\u2019s default form fields and buttons can sometimes jar. It\u2019s understandable that many a designer wants to change the way they look. Depending on the browser in question, various things can be done to style form fields and their buttons (although it\u2019s not as flexible as most would like).\n\nA common request is to replace the default buttons with a graphical button. This is usually achievable in most cases, although it\u2019s not easy to get a consistent result across all browsers \u2013 particularly when it comes to vertical positioning and the space surrounding the button. If the layout is very precise, or if space is at a premium, it\u2019s always best to try and live with the browser\u2019s default form controls.\n\nWhichever way you go, it\u2019s important to remember that in general, each form field should have a label, and each form should have a submit button. If you find that your form breaks either of those rules, you should double check.\n\nPractical tips for handing files over\n\nThere are a couple of basic steps that a design can carry out to make sure that the developer has the best chance of implementing the design exactly as envisioned.\n\nIf working with Photoshop of Fireworks or similar comping tool, it helps to group and label layers to make it easy for a developer to see which need to be turned on and off to get to isolate parts of the page and different states of the design. Also, if you don\u2019t work in the same office as your developer (and so they can\u2019t quickly check with you), provide a PDF of each page and state so that your developer can see how each page should look aside from any confusion with quick layers are switched on or off. These also act as a handy quick reference that can be used without firing up Photoshop (which can kill both productivity and your machine).\n\nFinally, provide a colour reference showing the RGB values of all the key colours used throughout the design. Without this, the developer will end up colour-picking from the comps, and could potentially end up with different colours to those you intended. Remember, for a lot of developers, working in a tool like Photoshop is like presenting a designer with an SSH terminal into a web server. It\u2019s unfamiliar ground and easy to get things wrong. Be the expert of your own domain and help your colleagues out when they\u2019re out of their comfort zone. That goes both ways.\n\nIn conclusion\n\nWhen asked the question of how to smooth hand-over between design and development, almost everyone who has experienced this situation could come up with their own list. This one is mine, based on some of the more common experiences we have at edgeofmyseat.com. So in bullet point form, here\u2019s my checklist for handing a design over.\n\n\n\tIs the layout fixed, or fluid?\n\tDoes each element cope with expanding for larger text and more content?\n\tAre all the graphics large enough to cope with an area expanding?\n\tDoes each interactive element have a state for with and without JavaScript?\n\tDoes each element have a state for logged in and logged out users?\n\tHow are any custom fonts being displayed? (and does the developer have the font to use?)\n\tDoes each interactive element have error and success messages designed?\n\tDo all form fields have a label and each form a submit button?\n\tIs your Photoshop comp document well organised?\n\tHave you provided flat PDFs of each state?\n\tHave you provided a colour reference?\n\tAre we having fun yet?", "year": "2008", "author": "Drew McLellan", "author_slug": "drewmclellan", "published": "2008-12-01T00:00:00+00:00", "url": "https://24ways.org/2008/easing-the-path-from-design-to-development/", "topic": "process"} {"rowid": 102, "title": "Art Directing with Looking Room", "contents": "Using photographic composition techniques to start to art direct on the template-driven web.\n\nThink back to last night. There you are, settled down in front of the TV, watching your favourite soap opera, with nice hot cup of tea in hand. Did you notice \u2013 whilst engrossed in the latest love-triangle \u2013 that the cameraman has worked very hard to support your eye\u2019s natural movement on-screen? He\u2019s carefully framed individual shots to create balance.\n\nThink back to last week. There you were, sat with your mates watching the big match. Did you notice that the cameraman frames the shot to go with the direction of play? A player moving right will always be framed so that he is on the far left, with plenty of \u2018room\u2019 to run into.\n\nBoth of these cameramen use a technique called Looking Room, sometimes called Lead Room. Looking Room is the space between the subject (be it a football, or a face), and the edge of the screen. Specifically, Looking Room is the negative space on the side the subject is looking or moving. The great thing is, it\u2019s not just limited to photography, film or television; we can use it in web design too.\n\nBasic Framing\n\nBefore we get into Looking Room, and how it applies to web, we need to have a look at some basics of photographic composition.\n\nMany web sites use imagery, or photographs, to enhance the content. But even with professionally shot photographs, without a basic understanding of framing or composition, you can damage how the image is perceived. \n\nA simple, easy way to make photographs more interesting is to fill the frame. \n\nTake this rather mundane photograph of a horse:\n\n\n\nA typical point and click affair. But, we can work with this.\n\nBy closely cropping, and filling the frame, we can instantly change the mood of the shot.\n\n\n\nI\u2019ve also added Looking Room on the right of the horse. This is space that the horse would be walking into. It gives the photograph movement.\n\nSubject, Space, and Movement\n\nGenerally speaking, a portrait photograph will have a subject and space around them. Visual interest in portrait photography can come from movement; how the eye moves around the shot. To get the eye moving, the photographer modifies the space around the subject.\n\nLook at this portrait:\n\n\n\nThe photography has framed the subject on the right, allowing for whitespace, or Looking Room, in the direction the subject is looking. The framing of the subject (1), with the space to the left (2) \u2013 the Looking Room \u2013 creates movement, shown by the arrow (3).\n\n\n\nNote the subject is not framed centrally (shown by the lighter dotted line).\n\nIf the photographer had framed the subject with equal space either side, the resulting composition is static, like our horse.\n\n\n\nIf the photographer framed the subject way over on the left, as she is looking that way, the resulting whitespace on the right leads a very uncomfortable composition.\n\n\n\nThe root of this discomfort is what the framing is telling our eye to do. The subject, looking to the left, suggests to us that we should do the same. However, the Looking Room on the right is telling our eye to occupy this space. The result is a confusing back and forth.\n\nHow Looking Room applies to the web\n\nWe can apply the same theory to laying out a web page or application. Taking the three same elements \u2013 Subject, Space, and resulting Movement \u2013 we can guide a user\u2019s eye to the elements we need to. As designers, or content editors, framing photographs correctly can have a subtle but important effect on how a page is visually scanned. Take this example:\n\n\n\nThe BBC homepage uses great photography as a way of promoting content. Here, they have cropped the main photograph to guide the user\u2019s eye into the content. \n\nBy applying the same theory, the designer or content editor has applied considerable Looking Room (2) to the photograph to create balance with the overall page design, but also to create movement of the user\u2019s eye toward the content (1)\n\n\n\nIf the image was flipped horizontally. The Looking Room is now on the right. The subject of the photograph is looking off the page, drawing the user\u2019s eye away from the content. Once again, this results in a confusing back and forth as your eye fights its way over to the left of the page.\n\n\n\nA little bit of Art Direction\n\nArt Direction can be described as the act or process of managing the visual presentation of content. Art Direction is difficult to do on the web, because content and presentation are, more often than not, separated. But where there are images, and when we know the templates that those images will populate, we can go a little way to bridging the gap between content and presentation.\n\nBy understanding the value of framing and Looking Room, and the fact that it extends beyond just a good looking photograph, we can start to see photography playing more of an integral role in the communication of content. \n\nWe won\u2019t just be populating templates. We\u2019ll be art directing.\n\nPhoto credits: \n\n\n\tPortrait by Carsten Tolkmit\n\tHorse by Mike Pedroncelli", "year": "2008", "author": "Mark Boulton", "author_slug": "markboulton", "published": "2008-12-05T00:00:00+00:00", "url": "https://24ways.org/2008/art-directing-with-looking-room/", "topic": "design"} {"rowid": 103, "title": "Recession Tips For Web Designers", "contents": "For web designers, there are four keys to surviving bad economic times: do good work, charge a fair price, lower your overhead, and be sure you are communicating with your client. As a reader of 24 ways, you already do good work, so let\u2019s focus on the rest.\n\nI know something about surviving bad times, having started my agency, Happy Cog, at the dawn of the dot-com bust. Of course, the recession we\u2019re in now may end up making the dot-com bust look like the years of bling and gravy. But the bust was rough enough at the time. \n\nBad times are hard on overweight companies and over-leveraged start-ups, but can be kind to freelancers and small agencies. Clients who once had money to burn and big agencies to help them burn it suddenly consider the quality of work more important than the marquee value of the business card. Fancy offices and ten people at every meeting are out. A close relationship with an individual or small team that listens is in.\n\nThin is in\n\nIf you were good in client meetings when you were an employee, print business cards and pick a name for your new agency. Once some cash rolls in, see an accountant. \n\nIf the one-person entrepreneur model isn\u2019t you, it\u2019s no problem. Form a virtual agency with colleagues who complement your creative, technical, and business skills. Athletics is a Brooklyn-based multi-disciplinary \u201cart and design collective.\u201d Talk about low overhead: they don\u2019t have a president, a payroll, or a pension plan. But that hasn\u2019t stopped clients like adidas, Nike, MTV, HBO, Disney, DKNY, and Sundance Channel from knocking on their (virtual) doors.\n\nRunning a traditional business is like securing a political position in Chicago: it costs a fortune. That\u2019s why bad times crush so many companies. But you are a creature of the internets. You don\u2019t need an office to do great work. I ran Happy Cog out of my apartment for far longer than anyone realized. My clients, when they learned my secret, didn\u2019t care. \n\nKeep it lean: if you can budget your incoming freelance money, you don\u2019t have to pay yourself a traditional salary. Removing the overhead associated with payroll means more of the budget stays in your pocket, enabling you to price your projects competitively, while still within industry norms. (Underpricing is uncool, and clients who knowingly choose below-market-rate vendors tend not to treat those vendors with respect.)\n\nGetting gigs\n\nWeb design is a people business. If things are slow, email former clients. If you just lost your job, email former agency clients with whom you worked closely to inform them of your freelance business and find out how they\u2019re doing. Best practice: focus the email on wishing them a happy holiday and asking how they\u2019re doing. Let your email signature file tell them you\u2019re now the president of Your Name Design. Leading with the fact that you just lost your job may earn sympathy (or commiseration: the client may have lost her job, too) but it\u2019s not exactly a sure-fire project getter.\n\nThe qualities that help you land a web design project are the same in good times or bad. Have a story to tell about the kind of services you offer, and the business benefits they provide. (If you design with web standards, you already have one great story line. What are the others?) \n\nDon\u2019t be shy about sharing your story, but don\u2019t make it the focus of the meeting. The client is the focus. Before you meet her, learn as much as you can about her users, her business, and her competitors. At the very least, read her site\u2019s About pages, and spend some quality time with Google. \n\nMost importantly, go to the meeting knowing how much you don\u2019t know. Arrive curious, and armed with questions. Maintain eye contact and keep your ears open. If a point you raise causes two people to nod at each other, follow up on that point, don\u2019t just keep grinding through your Keynote presentation. \n\nIf you pay attention and think on your feet, it tells the potential client that they can expect you to listen and be flexible. (Clients are like unhappy spouses: they\u2019re dying for someone to finally listen.) If you stick to a prepared presentation, it might send the message that you are inflexible or nervous or both. \u201cNervous\u201d is an especially bad signal to send. It indicates that you are either dishonest or inexperienced. Neither quality invites a client to sign on. Web design is a people business for the client, too: they should feel that their interactions with you will be pleasant and illuminating. And that you\u2019ll listen. Did I mention that?\n\nGive it time\n\nSecuring clients takes longer and requires more effort in a recession. If two emails used to land you a gig, it will now take four, plus an in-person meeting, plus a couple of follow-up calls. This level of salesmanship is painful to geeks and designers, who would rather spend four hours kerning type or debugging a style sheet than five minutes talking business on the telephone. I know. I\u2019m the same way. But we must overcome our natural shyness and inwardness if we intend not to fish our next meal out of a neighbor\u2019s garbage can. \n\nAs a bonus, once the recession ends, your hard-won account management skills will help you take your business to the next level. By the time jobs are plentiful again, you may not want to work for anyone but yourself. You\u2019ll be a captain of our industry. And talented people will be emailing to ask you for a job.", "year": "2008", "author": "Jeffrey Zeldman", "author_slug": "jeffreyzeldman", "published": "2008-12-24T00:00:00+00:00", "url": "https://24ways.org/2008/recession-tips-for-web-designers/", "topic": "business"} {"rowid": 104, "title": "Sitewide Search On A Shoe String", "contents": "One of the questions I got a lot when I was building web sites for smaller businesses was if I could create a search engine for their site. Visitors should be able to search only this site and find things without the maintainer having to put \u201crelated articles\u201d or \u201cfeatured content\u201d links on every page by hand. \n\nBack when this was all fields this wasn\u2019t easy as you either had to write your own scraping tool, use ht://dig or a paid service from providers like Yahoo, Altavista or later on Google. In the former case you had to swallow the bitter pill of computing and indexing all your content and storing it in a database for quick access and in the latter it hurt your wallet.\n\nTimes have moved on and nowadays you can have the same functionality for free using Yahoo\u2019s \u201cBuild your own search service\u201d \u2013 BOSS. The cool thing about BOSS is that it allows for a massive amount of hits a day and you can mash up the returned data in any format you want. Another good feature of it is that it comes with JSON-P as an output format which makes it possible to use it without any server-side component!\n\nStarting with a working HTML form\n\nIn order to add a search to your site, you start with a simple HTML form which you can use without JavaScript. Most search engines will allow you to filter results by domain. In this case we will search \u201cbbc.co.uk\u201d. If you use Yahoo as your standard search, this could be: \n\n
\n\t
\n\t\t\n\t\t\n\t\t\n\t\t\n\t
\n
\n\nThe Google equivalent is:\n\n
\n\t
\n\t\t\n\t\t\n\t\t\n\t\t\n\t
\n
\n\nIn any case make sure to use the ID term for the search term and site for the site, as this is what we are going to use for the script. To make things easier, also have an ID called customsearch on the form.\n\nTo use BOSS, you should get your own developer API for BOSS and replace the one in the demo code. There is click tracking on the search results to see how successful your app is, so you should make it your own.\n\nAdding the BOSS magic\n\nBOSS is a REST API, meaning you can use it in any HTTP request or in a browser by simply adding the right parameters to a URL. Say for example you want to search \u201cbbc.co.uk\u201d for \u201cchristmas\u201d all you need to do is open the following URL:\n\nhttp://boss.yahooapis.com/ysearch/web/v1/christmas?sites=bbc.co.uk&format=xml&appid=YOUR-APPLICATION-ID\n\nTry it out and click it to see the results in XML. We don\u2019t want XML though, which is why we get rid of the format=xml parameter which gives us the same information in JSON:\n\nhttp://boss.yahooapis.com/ysearch/web/v1/christmas?sites=bbc.co.uk&appid=YOUR-APPLICATION-ID\n\nJSON makes most sense when you can send the output to a function and immediately use it. For this to happen all you need is to add a callback parameter and the JSON will be wrapped in a function call. Say for example we want to call SITESEARCH.found() when the data was retrieved we can do it this way:\n\nhttp://boss.yahooapis.com/ysearch/web/v1/christmas?sites=bbc.co.uk&callback=SITESEARCH.found&appid=YOUR-APPLICATION-ID\n\nYou can use this immediately in a script node if you want to. The following code would display the total amount of search results for the term christmas on bbc.co.uk as an alert:\n\n\n\n\nHowever, for our example, we need to be a bit more clever with this.\n\nEnhancing the search form\n\n\n\n\nHere\u2019s the script that enhances a search form to show results below it.\n\nSITESEARCH = function(){\n\tvar config = {\n\t\tIDs:{\n\t\t\tsearchForm:'customsearch',\n\t\t\tterm:'term',\n\t\t\tsite:'site'\n\t\t},\n\t\tloading:'Loading results...',\n\t\tnoresults:'No results found.',\n\t\tappID:'YOUR-APP-ID',\n\t\tresults:20\n\t};\n\tvar form;\n\tvar out;\n\tfunction init(){\n\t\tif(config.appID === 'YOUR-APP-ID'){\n\t\t\talert('Please get a real application ID!');\n\t\t} else {\n\t\t\tform = document.getElementById(config.IDs.searchForm);\n\t\t\tif(form){\n\t\t\t\tform.onsubmit = function(){\n\t\t\t\t\tvar site = document.getElementById(config.IDs.site).value;\n\t\t\t\t\tvar term = document.getElementById(config.IDs.term).value;\n\t\t\t\t\tif(typeof site === 'string' && typeof term === 'string'){\n\t\t\t\t\t\tif(typeof out !== 'undefined'){\n\t\t\t\t\t\t\tout.parentNode.removeChild(out);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tout = document.createElement('p');\n\t\t\t\t\t\tout.appendChild(document.createTextNode(config.loading));\n\t\t\t\t\t\tform.appendChild(out);\n\t\t\t\t\t\tvar APIurl = 'http://boss.yahooapis.com/ysearch/web/v1/' + \n\t\t\t\t\t\t\t\t\t\t\t\t\tterm + '?callback=SITESEARCH.found&sites=' + \n\t\t\t\t\t\t\t\t\t\t\t\t\tsite + '&count=' + config.results + \n\t\t\t\t\t\t\t\t\t\t\t\t\t'&appid=' + config.appID;\n\t\t\t\t\t\tvar s = document.createElement('script');\n\t\t\t\t\t\ts.setAttribute('src',APIurl);\n\t\t\t\t\t\ts.setAttribute('type','text/javascript');\n\t\t\t\t\t\tdocument.getElementsByTagName('head')[0].appendChild(s);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t};\n\tfunction found(o){\n\t\tvar list = document.createElement('ul');\n\t\tvar results = o.ysearchresponse.resultset_web;\n\t\tif(results){\n\t\t\tvar item,link,description;\n\t\t\tfor(var i=0,j=results.length;i\n\t
\n\t\t\n\t\t\n\t\t\n\t\t\n\t
\n\n\n\n\nWhere to go from here\n\nThis is just a very simple example of what you can do with BOSS. You can define languages and regions, retrieve and display images and news and mix the results with other data sources before displaying them. One very cool feature is that by adding a view=keyterms parameter to the URL you can get the keywords of each of the results to drill deeper into the search. An example for this written in PHP is available on the YDN blog. For JavaScript solutions there is a handy wrapper called yboss available to help you go nuts.", "year": "2008", "author": "Christian Heilmann", "author_slug": "chrisheilmann", "published": "2008-12-04T00:00:00+00:00", "url": "https://24ways.org/2008/sitewide-search-on-a-shoestring/", "topic": "code"} {"rowid": 105, "title": "Contract Killer", "contents": "When times get tough, it can often feel like there are no good people left in the world, only people who haven\u2019t yet turned bad. These bad people will go back on their word, welch on a deal, put themselves first. You owe it to yourself to stay on top. You owe it to yourself to ensure that no matter how bad things get, you\u2019ll come away clean. You owe it yourself and your business not to be the guy lying bleeding in an alley with a slug in your gut.\n\nBut you\u2019re a professional, right? Nothing bad is going to happen to you.\n\nYou\u2019re a good guy. You do good work for good people.\n\nThink again chump.\n\nMaybe you\u2019re a gun for hire, a one man army with your back to the wall and nothing standing between you and the line at a soup kitchen but your wits. Maybe you work for the agency, or like me you run one of your own. Either way, when times get tough and people get nasty, you\u2019ll need more than a killer smile to save you. You\u2019ll need a killer contract too.\n\nIt was exactly ten years ago today that I first opened my doors for business. In that time I\u2019ve thumbed through enough contracts to fill a filing cabinet. I\u2019ve signed more contracts than I can remember, many so complicated that I should have hired a lawyer (or detective) to make sense of their complicated jargon and solve their cross-reference puzzles. These documents had not been written to be understood on first reading but to spin me around enough times so as to give the other player the upper-hand.\n\n\nIf signing a contract I didn\u2019t fully understand made me a stupid son-of-a-bitch, not asking my customers to sign one just makes me plain dumb. I\u2019ve not always been so careful about asking my customers to sign contracts with me as I am now. Somehow in the past I felt that insisting on a contract went against the friendly, trusting relationship that I like to build with my customers. Most of the time the game went my way. On rare the occasions when a fight broke out, I ended up bruised and bloodied. I learned that asking my customers to sign a contract matters to both sides, but what also matters to me is that these contracts should be more meaningful, understandable and less complicated than any of those that I have ever autographed.\n\n\nWriting a killer contract\n\nIf you are writing a contract between you and your customers it doesn\u2019t have to conform to the seemingly standard format of jargon and complicated legalese. You can be creative. A killer contract will clarify what is expected of both sides and it can also help you to communicate your approach to doing business. It will back-up your brand values and help you to build a great relationship between you and your customers. In other words, a creative contract can be a killer contract.\n\n\nYour killer contract should cover:\n\n\n\tA simple overview of who is hiring who, what they are being hired to do, when and for how much\n\tWhat both parties agree to do and what their respective responsibilities are\n\tThe specifics of the deal and what is or isn\u2019t included in the scope\n\tWhat happens when people change their minds (as they almost always do)\n\tA simple overview of liabilities and other legal matters\n\tYou might even include a few jokes\n\n\nTo help you along, I will illustrate those bullet points by pointing both barrels at the contract that I wrote and have been using at Stiffs & Nonsense for the past year. My contract has been worth its weight in lead and you are welcome to take all or any part of it to use for yourself. It\u2019s packing a creative-commons attribution share-a-like license. That means you are free to re-distribute it, translate it and otherwise re-use it in ways I never considered. In return I only ask you mention my name and link back to this article. As I am only an amateur detective, you should have it examined thoroughly by your own, trusted legal people if you use it.\n\nNB: The specific details of this killer contract work for me and my customers. That doesn\u2019t mean that they will work for you and yours. The ways that I handle design revisions, testing, copyright ownership and other specifics are not the main focus of this article. That you handle each of them carefully when you write your own killer contract is.\n\nKiss Me, Deadly\n\nSetting a tone and laying foundations for agreement\n\nThe first few paragraphs of a killer contract are the most important. Just like a well thought-out web page, these first few words should be simple, concise and include the key points in your contract. As this is the part of the contract that people absorb most easily, it is important that you make it count. Start by setting the overall tone and explaining how your killer contract is structured and why it is different.\n\n\n\n\tWe will always do our best to fulfill your needs and meet your goals, but sometimes it is best to have a few simple things written down so that we both know what is what, who should do what and what happens if stuff goes wrong. In this contract you won\u2019t find complicated legal terms or large passages of unreadable text. We have no desire to trick you into signing something that you might later regret. We do want what\u2019s best for the safety of both parties, now and in the future.\n\n\tIn short\n\n\tYou ([customer name]) are hiring us ([company name]) located at [address] to [design and develop a web site] for the estimated total price of [total] as outlined in our previous correspondence. Of course it\u2019s a little more complicated, but we\u2019ll get to that.\n\n\nThe Big Kill\n\nWhat both parties agree to do\n\nHave you ever done work on a project in good faith for a junior member of a customer\u2019s team, only to find out later that their spending hadn\u2019t been authorized? To make damn sure that does not happen to you, you should ask your customer to confirm that not only are they authorized to enter into your contract but that they will fulfill all of their obligations to help you meet yours. This will help you to avoid any gunfire if, as deadline day approaches, you have fulfilled your side of the bargain but your customer has not come up with the goods.\n\n\n\n\tAs our customer, you have the power and ability to enter into this contract on behalf of your company or organization. You agree to provide us with everything that we need to complete the project including text, images and other information as and when we need it, and in the format that we ask for. You agree to review our work, provide feedback and sign-off approval in a timely manner too. Deadlines work two ways and you will also be bound by any dates that we set together. You also agree to stick to the payment schedule set out at the end of this contract.\n\n\tWe have the experience and ability to perform the services you need from us and we will carry them out in a professional and timely manner. Along the way we will endeavor to meet all the deadlines set but we can\u2019t be responsible for a missed launch date or a deadline if you have been late in supplying materials or have not approved or signed off our work on-time at any stage. On top of this we will also maintain the confidentiality of any information that you give us.\n\n\nMy Gun Is Quick\n\nGetting down to the nitty gritty\n\nWhat appear at first to be a straight-forward projects can sometimes turn long and complicated and unless you play it straight from the beginning your relationship with your customer can suffer under the strain. Customers do, and should have the opportunity to, change their minds and give you new assignments. After-all, projects should be flexible and few customers know from the get-go exactly what they want to see. If you handle this well from the beginning you will help to keep yourself and your customers from becoming frustrated. You will also help yourself to dodge bullets in the event of a fire-fight.\n\n\n\n\tWe will create designs for the look-and-feel, layout and functionality of your web site. This contract includes one main design plus the opportunity for you to make up to two rounds of revisions. If you\u2019re not happy with the designs at this stage, you will pay us in full for all of the work that we have produced until that point and you may either cancel this contract or continue to commission us to make further design revisions at the daily rate set out in our original estimate.\n\n\tWe know from plenty of experience that fixed-price contracts are rarely beneficial to you, as they often limit you to your first idea about how something should look, or how it might work. We don\u2019t want to limit either your options or your opportunities to change your mind.\n\n\tThe estimate/quotation prices at the beginning of this document are based on the number of days that we estimate we\u2019ll need to accomplish everything that you have told us you want to achieve. If you do want to change your mind, add extra pages or templates or even add new functionality, that won\u2019t be a problem. You will be charged the daily rate set out in the estimate we gave you. Along the way we might ask you to put requests in writing so we can keep track of changes.\n\n\nAs I like to push my luck when it comes to CSS, it never hurts to head off the potential issue of progressive enrichment right from the start. You should do this too. But don\u2019t forget that when it comes to technical matters your customers may have different expectations or understanding, so be clear about what you will and won\u2019t do.\n\n\n\n\tIf the project includes XHTML or HTML markup and CSS templates, we will develop these using valid XHTML 1.0 Strict markup and CSS2.1 + 3 for styling. We will test all our markup and CSS in current versions of all major browsers including those made by Apple, Microsoft, Mozilla and Opera. We will also test to ensure that pages will display visually in a \u2018similar\u2019, albeit not necessarily an identical way, in Microsoft Internet Explorer 6 for Windows as this browser is now past it\u2019s sell-by date.\n\n\tWe will not test these templates in old or abandoned browsers, for example Microsoft Internet Explorer 5 or 5.5 for Windows or Mac, previous versions of Apple\u2019s Safari, Mozilla Firefox or Opera unless otherwise specified. If you need to show the same or similar visual design to visitors using these older browsers, we will charge you at the daily rate set out in our original estimate for any necessary additional code and its testing.\n\n\nThe Twisted Thing\n\nIt is not unheard of for customers to pass off stolen goods as their own. If this happens, make sure that you are not the one left holding the baby. You should also make it clear who owns the work that you make as customers often believe that because they pay for your time, that they own everything that you produce.\n\n\nCopyrights\n\n\n\tYou guarantee to us that any elements of text, graphics, photos, designs, trademarks, or other artwork that you provide us for inclusion in the web site are either owned by your good selfs, or that you have permission to use them. When we receive your final payment, copyright is automatically assigned as follows:\n\n\tYou own the graphics and other visual elements that we create for you for this project. We will give you a copy of all files and you should store them really safely as we are not required to keep them or provide any native source files that we used in making them.\n\n\tYou also own text content, photographs and other data you provided, unless someone else owns them. We own the XHTML markup, CSS and other code and we license it to you for use on only this project.\n\n\nVengeance Is Mine!\n\nThe fine print\n\nUnless your work is pro-bono, you should make sure that your customers keep you in shoe leather. It is important that your customers know from the outset that they must pay you on time if they want to stay on good terms.\n\n\n\tWe are sure you understand how important it is as a small business that you pay the invoices that we send you promptly. As we\u2019re also sure you\u2019ll want to stay friends, you agree to stick tight to the following payment schedule.\n\n\t[Payment schedule]\n\n\nNo killer contract would be complete without you making sure that you are watching your own back. Before you ask your customers to sign, make it clear-cut what your obligations are and what will happen if any part of your killer contract finds itself laying face down in the dirt.\n\n\n\n\tWe can\u2019t guarantee that the functions contained in any web page templates or in a completed web site will always be error-free and so we can\u2019t be liable to you or any third party for damages, including lost profits, lost savings or other incidental, consequential or special damages arising out of the operation of or inability to operate this web site and any other web pages, even if you have advised us of the possibilities of such damages.\n\n\tJust like a parking ticket, you cannot transfer this contract to anyone else without our permission. This contract stays in place and need not be renewed. If any provision of this agreement shall be unlawful, void, or for any reason unenforceable, then that provision shall be deemed severable from this agreement and shall not affect the validity and enforceability of any remaining provisions.\n\n\tPhew.\n\n\tAlthough the language is simple, the intentions are serious and this contract is a legal document under exclusive jurisdiction of [English] courts. Oh and don\u2019t forget those men with big dogs.\n\n\nSurvival\u2026 Zero!\n\nTake it from me, packing a killer contract will help to keep you safe when times get tough, but you must still keep your wits about you and stay on the right side of the law.\n\nDon\u2019t be a turkey this Christmas.\n\nBe a contract killer.\n\nUpdate, May 2010: For a follow-on to this article see Contract Killer: The Next Hit", "year": "2008", "author": "Andy Clarke", "author_slug": "andyclarke", "published": "2008-12-23T00:00:00+00:00", "url": "https://24ways.org/2008/contract-killer/", "topic": "business"} {"rowid": 106, "title": "Checking Out: Progress Meters", "contents": "It\u2019s the holiday season, so you know what that means: online shopping! When I started developing Web sites back in the 90s, many of my first clients were small local shops wanting to sell their goods online, so I developed many a checkout system. And because of slow dial-up speeds back then, informing the user about where they were in the checkout process was pretty important.\n\nEven though we\u2019re (mostly) beyond the dial-up days, informing users about where they are in a flow is still important. In usability tests at the companies I\u2019ve worked at, I\u2019ve seen time and time again how not adequately informing the user about their state can cause real frustration. This is especially true for two sets of users: mobile users and users of assistive devices, in particular, screen readers.\n\nThe progress meter is a very common design solution used to indicate to the user\u2019s state within a flow. On the design side, much effort may go in to crafting a solution that is as visually informative as possible. On the development side, however, solutions range widely. I\u2019ve checked out the checkouts at a number of sites and here\u2019s what I\u2019ve found when it comes to progress meters: they\u2019re sometimes inaccessible and often confusing or unhelpful \u2014 all because of the way in which they\u2019re coded. For those who use assistive devices or text-only browsers, there must be a better way to code the progress meter \u2014 and there is.\n\n(Note: All code samples are from live sites but have been tweaked to hide the culprits\u2019 identities.)\n\nHow not to make progress\n\nA number of sites assemble their progress meters using non- or semi-semantic markup and images with no alternate text. On text-only browsers (like my mobile phone) and to screen readers, this looks and reads like chunks of content with no context given.\n\n
\n\t\"\"\n\tShipping information\n\t\"\"\n\t\"\"\n\tPayment information\n\t\"\"\n\t\"\"\n\tPlace your order\n
\n\nIn the above example, the third state, \u201cPlace your order\u201d, is the current state. But a screen reader may not know that, and my cell phone only displays \"Shipping informationPayment informationPlace your order\". Not good.\n\nIs this progress?\n\nOther sites present the entire progress meter as a graphic, like the following:\n\n\n\nNow, I have no problem with using a graphic to render a very stylish progress meter (my sample above is probably not the most stylish example, of course, but you understand my point). What becomes important in this case is the use of appropriate alternate text to describe the image. Disappointingly, sites today have a wide range of solutions, including using no alternate text. Check out these code samples which call progress meter images.\n\n\"\"\n\nI think we can all agree that the above is bad, unless you really don\u2019t care whether or not users know where they are in a flow.\n\n\"Shipping\n\nThe alt text in the example above just copies all of the text found in the graphic, but it doesn\u2019t represent the status at all. So for every page in the checkout, the user sees or hears the same text. Sure, by the second or third page in the flow, the user has figured out what\u2019s going on, but she or he had to think about it. I don\u2019t think that\u2019s good.\n\n\"Checkout:\n\nThe above probably has the best alternate text out of these examples, because the user at least understands that they\u2019re in the Checkout process, on the Place your order page. But going through the flow with alt text like this, the user doesn\u2019t know how many steps are in the flow.\n\nSemantic progress\n\nOf course, there are some sites that use an ordered list when marking up the progress meter. Hooray! Unfortunately, no text-only browser or screen reader would be able to describe the user\u2019s current state given this markup.\n\n
    \n\t
  1. shipping information
  2. \n\t
  3. payment information
  4. \n\t
  5. place your order
  6. \n
\n\nWithout CSS enabled, the above is rendered as follows:\n\n\n\nProgress at last\n\nWe all know that semantic markup makes for the best foundation, so we\u2019ll start with the markup found above. In order to make the state information accessible, let\u2019s add some additional text in paragraph and span elements.\n\n
\n\t

There are three steps in this checkout process.

\n\t
    \n\t\t
  1. Enter your shipping information
  2. \n\t\t
  3. Enter your payment information
  4. \n\t\t
  5. Review details and place your order
  6. \n\t
\n
\n\nAdd on some simple CSS to hide the paragraph and spans, and arrange the list items on a single line with a background image to represent the large number, and this is what you\u2019ll get:\n\n \n\tThere are three steps in this checkout process.\n\t\n\t\tEnter your shipping information\n\t\tEnter your payment information\n\t\tReview details and place your order\n\t\n \n\nTo display and describe a state as active, add the class \u201ccurrent\u201d to one of the list items. Then change the hidden content such that it better describes the state to the user.\n\n
\n\t

There are three steps in this checkout process.

\n\t
    \n\t\t
  1. You are currently entering your shipping information
  2. \n\t\t
  3. In the next step, you will enter your payment information
  4. \n\t\t
  5. In the last step, you will review the details and place your order
  6. \n\t
\n
\n\nThe end result is an attractive progress meter that gives much greater semantic and contextual information.\n\n \n\tThere are three steps in this checkout process.\n\t\n\t\tYou are currently entering your shipping information\n\t\tIn the next step, you will enter your payment information\n\t\tIn the last step, you will review the details and place your order\n\t\n \n\nFor example, the above example renders in a text-only browser as follows:\n\n \n\tThere are three steps in this checkout process.\n\t\n\t\tYou are currently entering your shipping information\n\t\tIn the next step, you will enter your payment information\n\t\tIn the last step, you will review the details and place your order\n\t\n \n\nAnd the screen reader I use for testing announces the following:\n\n \n\tThere are three steps in this checkout process. List of three items. You are currently entering your shipping information. In the next step, you will enter your payment information. In the last step, you will review the details and place your order. List end.\n \n\nHere\u2019s a sample code page that summarises this approach.\n\nHappy frustration-free online shopping with this improved progress meter!", "year": "2008", "author": "Kimberly Blessing", "author_slug": "kimberlyblessing", "published": "2008-12-12T00:00:00+00:00", "url": "https://24ways.org/2008/checking-out-progress-meters/", "topic": "ux"} {"rowid": 107, "title": "Using Google App Engine as Your Own Content Delivery Network", "contents": "Do you remember, years ago, when hosting was expensive, domain names were the province of the rich, and you hosted your web pages on Geocities? It seems odd to me now that there was a time when each and every geek didn\u2019t have his own top-level domain and super hosting setup. But as the parts became more and more affordable a man could become an outcast if he didn\u2019t have his own slightly surreal-sounding TLD.\n\nAnd so it will be in the future when people realise with surprise there was a time before affordable content delivery networks.\n\nA content delivery network, or CDN, is a system of servers spread around the world, serving files from the nearest physical location. Instead of waiting for a file to find its way from a server farm in Silicon Valley 8,000 kilometres away, I can receive it from London, Dublin, or Paris, cutting down the time I wait. The big names \u2014 Google, Yahoo, Amazon, et al \u2014 use CDNs for their sites, but they\u2019ve always been far too expensive for us mere mortals. Until now.\n\nThere\u2019s a service out there ready for you to use as your very own CDN. You have the company\u2019s blessing, you won\u2019t need to write a line of code, and \u2014 best of all \u2014 it\u2019s free. The name? Google App Engine.\n\nIn this article you\u2019ll find out how to set up a CDN on Google App Engine. You\u2019ll get the development software running on your own computer, tell App Engine what files to serve, upload them to a web site, and give everyone round the world access to them.\n\nCreating your first Google App Engine project\n\nBefore we do anything else, you\u2019ll need to download the Google App Engine software development kit (SDK). You\u2019ll need Python 2.5 too \u2014 you won\u2019t be writing any Python code but the App Engine SDK will need it to run on your computer. If you don\u2019t have Python, App Engine will install it for you (if you use Mac OS X 10.5 or a Linux-based OS you\u2019ll have Python; if you use Windows you won\u2019t).\n\nDone that? Excellent, because that\u2019s the hardest step. The rest is plain sailing.\n\nYou\u2019ll need to choose a unique \u2018application id\u2019 \u2014 nothing more than a name \u2014 for your project. Make sure it consists only of lowercase letters and numbers. For this article I\u2019ll use 24ways2008, but you can choose anything you like.\n\nOn your computer, create a folder named after your application id. This folder can be anywhere you want: your desktop, your documents folder, or wherever you usually keep your web files. Within your new folder, create a folder called assets, and within that folder create three folders called images, css, and javascript. These three folders are the ones you\u2019ll fill with files and serve from your content delivery network. You can have other folders too, if you like.\n\nThat will leave you with a folder structure like this:\n\n24ways2008/\n\t\tassets/\n\t\t\tcss/\n\t\t\timages/\n\t\t\tjavascript/\n\nNow you need to put a few files in these folders, so we can later see our CDN in action. You can put anything you want in these folders, but for this example we\u2019ll include an HTML file, a style sheet, an image, and a Javascript library.\n\nIn the top-level folder (the one I\u2019ve called 24ways2008), create a file called index.html. Fill this with any content you want. In the assets/css folder, create a file named core.css and throw in a couple of CSS rules for good measure. In the assets/images directory save any image that takes your fancy \u2014 I\u2019ve used the silver badge from the App Engine download page. Finally, to fill the JavaScript folder, add in this jQuery library file. If you\u2019ve got the time and the inclination, you can build a page that uses all these elements.\n\nSo now we should have a set of files and folders that look something like this:\n\n24ways2008/\n\t\tassets/\n\t\t\t\tindex.html\n\t\t\t\tcss/\n\t\t\t\t\t\tcore.css\n\t\t\t\timages/\n\t\t\t\t\t\tappengine-silver-120x30.gif\n\t\t\t\tjavascript/\n\t\t\t\t\t\tjquery-1.2.6.min.js\n\nWhich leaves us with one last file to create. This is the important one: it tells App Engine what to do with your files. It\u2019s named app.yaml, it sits at the top-level (inside the folder I\u2019ve named 24ways2008), and it needs to include these lines:\n\napplication: 24ways2008\nversion: 1\nruntime: python\napi_version: 1\n\nhandlers:\n- url: /\n\tstatic_files: assets/index.html\n\tupload: assets/index.html\n\n- url: /\n\tstatic_dir: assets\n\nYou need to make sure you change 24ways2008 on the first line to whatever you chose as your application id, but otherwise the content of your app.yaml file should be identical. And with that, you\u2019ve created your first App Engine project. If you want it, you can download a zip file containing my project.\n\nTesting your project\n\nAs it stands, your project is ready to be uploaded to App Engine. But we couldn\u2019t call ourselves professionals if we didn\u2019t test it, could we? So, let\u2019s put that downloaded SDK to good use and run the project from your own computer.\n\nOne of the files you\u2019ll find App Engine installed is named dev_appserver.py, a Python script used to simulate App Engine on your computer. You\u2019ll find lots of information on how to do this in the documentation on the development web server, but it boils down to running the script like so (the space and the dot at the end are important):\n\ndev_appserver.py .\n\nYou\u2019ll need to run this from the command-line: Mac users can run the Terminal application, Linux users can run their favourite shell, and Windows users will need to run it via the Command Prompt (open the Start menu, choose \u2018Run\u2026\u2019, type \u2018cmd\u2018, and click \u2018OK\u2019). Before you run the script you\u2019ll need to make sure you\u2019re in the project folder \u2014 in my case, as I saved it to my desktop I can go there by typing \n\ncd ~/Desktop/24ways2008\n\nin my Mac\u2019s Terminal app; if you\u2019re using Windows you can type \n\ncd \"C:\\Documents and Settings\\username\\Desktop\\24ways2008\"\n\nIf that\u2019s successful, you\u2019ll see a few lines of output, the last looking something like this:\n\nINFO 2008-11-22 14:35:00,830 dev_appserver_main.py] Running application 24ways2008 on port 8080: http://localhost:8080\n\nNow you can power up your favourite browser, point it to http://localhost:8080/, and you\u2019ll see the page you saved as index.html. You\u2019ll also find your CSS file at http://localhost:8080/css/core.css. In fact, anything you put inside the assets folder in the project will be accessible from this domain. You\u2019re running our own App Engine web server!\n\nNote that no-one else will be able to see your files: localhost is a special domain that you can only see from your computer \u2014 and once you stop the development server (by pressing Control\u2013C) you\u2019ll not be able to see the files in your browser until you start it again.\n\nYou might notice a new file has turned up in your project: index.yaml. App Engine creates this file when you run the development server, and it\u2019s for internal App Engine use only. If you delete it there are no ill effects, but it will reappear when you next run the development server. If you\u2019re using version control (e.g. Subversion) there\u2019s no need to keep a copy in your repository.\n\nSo you\u2019ve tested your project and you\u2019ve seen it working on your own machine; now all you need to do is upload your project and the world will be able to see your files too.\n\nUploading your project\n\nIf you don\u2019t have a Google account, create one and then sign in to App Engine. Tell Google about your new project by clicking on the \u2018Create an Application\u2019 button. Enter your application id, give the application a name, and agree to the terms and conditions. That\u2019s it. All we need do now is upload the files.\n\nOpen your Mac OS X Terminal, Windows Command Prompt, or Linux shell window again, move to the project folder, and type (again, the space and the dot at the end are important):\n\nappcfg.py update .\n\nEnter your email address and password when prompted, and let App Engine do it\u2019s thing. It\u2019ll take no more than a few seconds, but in that time App Engine will have done the equivalent of logging in to an FTP server and copying files across. It\u2019s fairly understated, but you now have your own project up and running. You can see mine at http://24ways2008.appspot.com/, and everyone can see yours at http://your-application-id.appspot.com/. Your files are being served up over Google\u2019s content delivery network, at no cost to you!\n\nBenefits of using Google App Engine\n\nThe benefits of App Engine as a CDN are obvious: your own server doesn\u2019t suck up the bandwidth, while your visitors will appreciate a faster site. But there are also less obvious benefits.\n\nFirst, once you\u2019ve set up your site, updating it is an absolute breeze. Each time you update a file (or a batch of files) you need only run appcfg.py to see the changes appear on your site. To paraphrase Joel Spolsky, a good web site must be able to be updated in a single step. Many designers and developers can\u2019t make that claim, but with App Engine, you can.\n\nApp Engine also allows multiple people to work on one application. If you want a friend to be able to upload files to your site you can let him do so without giving him usernames and passwords \u2014 all he needs is his own Google account. App Engine also gives you a log of all actions taken by collaborators, so you can see who\u2019s made updates, and when.\n\nAnother bonus is the simple version control App Engine offers. Do you remember the file named app.yaml you created a while back? The second line looked like this:\n\nversion: 1\n\nIf you change the version number to 2 (or 3, or 4, etc), App Engine will keep a copy of the last version you uploaded. If anything goes wrong with your latest version, you can tell App Engine to revert back to that last saved version. It\u2019s no proper version control system, but it could get you out of a sticky situation.\n\nOne last thing to note: if you\u2019re not happy using your-application-id.appspot.com as your domain, App Engine will quite happily use any domain you own.\n\nThe weak points of Google App Engine\n\nIn the right circumstances, App Engine can be a real boon. I run my own site using the method I\u2019ve discussed above, and I\u2019m very happy with it. But App Engine does have its disadvantages, most notably those discussed by Aral Balkan in his post \u2018Why Google App Engine is broken and what Google must do to fix it\u2018.\n\nAral found the biggest problems while using App Engine as a web application platform; I wouldn\u2019t recommend using it as such either (at least for now) but for our purposes as a CDN for static files, it\u2019s much more worthy. Still, App Engine has two shortcomings you should be aware of.\n\nThe first is that you can\u2019t host a file larger than one megabyte. If you want to use App Engine to host that 4.3MB download for your latest-and-greatest desktop software, you\u2019re out of luck. The only solution is to stick to smaller files.\n\nThe second problem is the quota system. Google\u2019s own documentation says you\u2019re allowed 650,000 requests a day and 10,000 megabytes of bandwidth in and out (20,000 megabytes in total), which should be plenty for most sites. But people have seen sites shut down temporarily for breaching quotas \u2014 in some cases after inexplicable jumps in Google\u2019s server CPU usage. Aral, who\u2019s seen it happen to his own sites, seemed genuinely frustrated by this, and if you measure your hits in the hundreds of thousands and don\u2019t want to worry about uptime, App Engine isn\u2019t for you.\n\nThat said, for most of us, App Engine offers a fantastic resource: the ability to host files on Google\u2019s own content delivery network, at no charge.\n\nConclusion\n\nIf you\u2019ve come this far, you\u2019ve seen how to create a Google App Engine project and host your own files on Google\u2019s CDN. You\u2019ve seen the great advantages App Engine offers \u2014 an excellent content delivery network, the ability to update your site with a single command, multiple authors, simple version control, and the use of your own domain \u2014 and you\u2019ve come across some of its weaknesses \u2014 most importantly the limit on file sizes and the quota system. All that\u2019s left to do is upload those applications \u2014 but not before you\u2019ve finished your Christmas shopping.", "year": "2008", "author": "Matt Riggott", "author_slug": "mattriggott", "published": "2008-12-06T00:00:00+00:00", "url": "https://24ways.org/2008/using-google-app-engine-as-your-own-cdn/", "topic": "process"} {"rowid": 108, "title": "A Festive Type Folly", "contents": "\u2018Tis the season to be jolly, so the carol singers tell us. At 24 ways, we\u2019re keeping alive another British tradition that includes the odd faux-Greco-Roman building dotted around the British countryside, Tower Bridge built in 1894, and your Dad\u2019s Christmas jumper with the dancing reindeer motif. \u2018Tis the season of the folly!\n\n \n 24 Ways to impress your friends\n \n\nThe example is not an image, just text. You may wish to see a screenshot in Safari to compare with your own operating system and browser rendering.\n\nLike all follies this is an embellishment\u200a\u2014\u200aa bit of web typography fun. It\u2019s similar to the masthead text at my place, but it\u2019s also a hyperlink. Unlike the architectural follies of the past, no child labour was used to fund or build it, just some HTML flavoured with CSS, and a heavy dose of Times New Roman. Why Times New Roman, you ask? Well, after a few wasted hours experimenting with heaps of typefaces, seeking an elusive consistency of positioning and rendering across platforms, it proved to be the most consistent. Who\u2019d\u2018a thought? To make things more interesting, I wanted to use a traditional scale and make the whole thing elastic by using relative lengths that would react to a person\u2019s font size. So, to the meat of this festive frippery:\n\nThere are three things we rely on to create this indulgence:\n\n\n\tDescendant selectors\n\tAbsolute positioning\n\tInheritance\n\n\nHTML & Descendant Selectors\n\nThe markup for the folly might seem complex at first glance. To semantics pedants and purists it may seem outrageous. If that\u2019s you, read on at your peril! Here it is with lots of whitespace:\n\n
\n

\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a02\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a04 \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0w\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0a\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0y\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0s\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0 \n\u00a0\u00a0\u00a0\u00a0to \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0i\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0m\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0pre\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0s\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0s \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0your \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0friends\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0\t\n\u00a0\u00a0\n

\n
\n\nWhy so much markup? Well, we want to individually style many of the glyphs. By nesting the elements, we can pick out the bits we need as descendant selectors.\n\nTo retain a smidgen of semantics, the text is wrapped in

and elements. The two phrases, \u201c24 ways\u201d and \u201cto impress your friends\u201d are wrapped in and tags, respectively. Within those loving arms, their descendant s cascade invisibly, making a right mess of our source, but ready to be picked out in our CSS rules.\n\nSo, to select the \u201c2\u201d from the example we can simply write, #type h1 em{ }. Of course, that selects everything within the tags, but as we drill down the document tree, selecting other glyphs, any property / value styles can be reset or changed as required.\n\nPixels Versus Ems\n\nBefore we get stuck into the CSS, I should say that the goal here is to have everything expressed in relative \u201cem\u201d lengths. However, when I\u2019m starting out, I use pixels for all values, and only convert them to ems after I\u2019ve finished. It saves re-calculating the em length for every change I make as the folly evolves, but still makes the final result elastic, without relying on browser zoom.\n\nTo skip ahead, see the complete CSS.\n\nAbsolutely Positioned Glyphs\n\nIf a parent element has position: relative, or position: absolute applied to it, all children of that parent can be positioned absolutely relative to it. (See Dave Shea\u2019s excellent introduction to this.) That\u2019s exactly how the folly is achieved. As the parent, #type also has a font-size of 16px set, a width and height, and some basic style with a background and border:\n\n#type{\n\tfont-size: 16px;\n\ttext-align: left;\n\tbackground: #e8e9de;\n\tborder: 0.375em solid #fff;\n\twidth: 22.5em;\n\theight: 13.125em;\n\tposition: relative;\n}\n\nThe h1 is also given a default style with a font-size of 132px in ems relative to the parent font-size of 16px:\n\n#type h1{\n\tfont-family: \"Times New Roman\", serif;\n\tfont-size: 8.25em; /* 132px */\n\tline-height: 1em;\n\tfont-weight: 400;\n\tmargin: 0;\n\tpadding: 0;\n}\n\nTo get the em value, we divide the required size in pixels by the actual parent font-size in pixels\n\n132 \u00f7 16 = 8.25\n\nWe also give the descendants of the h1 some default properties. The line height, style and weight are normalised, they are positioned absolutely relative to #type, and a border and padding is applied:\n\n#type h1 em,\n#type h1 strong,\n#type h1 span{\n\tline-height: 1em;\n\tfont-style: normal;\n\tfont-weight: 400;\n\tposition: absolute;\n\tpadding: 0.1em;\n\tborder: 1px solid transparent;\n}\n\nThe padding ensures that some browsers don\u2019t forget about parts of a glyph that are drawn outside of their invisible container. When this happens, IE will trim the glyph, cutting off parts of descenders, for example. The border is there to make sure the glyphs have layout. Without this, positioning can be problematic. IE6 will not respect the transparent border colour\u200a\u2014\u200ait uses the actual text colour\u200a\u2014\u200abut in all other respects renders the example. You can hack around it, but it seemed unnecessary for this example.\n\nOnce these defaults are established, the rest is trial and error. As a quick example, the numeral \u201c2\u201d is first to be positioned:\n\n#type h1 a em{\n\tfont-size: 0.727em; /* (2) 96px */\n\tleft: 0.667em;\n\ttop: 0;\n}\n\nEvery element of the folly is positioned in exactly the same way as you can see in the complete CSS. When converting pixels to ems, the font-size is set first. Then, because we know what that is, we calculate the equivalent x- and y-position accordingly.\n\nInheritance\n\nCSS inheritance gave me a headache a long time ago when I first encountered it. After the penny dropped I came to experience something disturbingly close to affection for this characteristic. What it basically means is that children inherit the characteristics of their parents. For example:\n\n\n\tWe gave #type a font-size of 16px.\n\tFor #type h1 we changed it by setting font-size: 8.25em;. Than means that #type h1 now has a computed font-size of 8.25 \u00d7 16px = 132px.\n\tNow, all children of #type h1 in the document tree will inherit a font-size of 132px unless we explicitly change it as we did for #type h1 a em.\n\n\nThe \u201c2\u201d in the example\u200a\u2014\u200aselected with #type h1 a em\u200a\u2014\u200ais set at 96px with left and top positioning calculated relatively to that. So, the left position of 0.667em is 0.667 \u00d7 96 = 64px, approximately (three decimal points in em lengths don\u2019t always give exact pixel equivalents).\n\nOne way to look at inheritance is as a cascade of dependancy: In our example, the computed font size of any given element depends on that of the parent, and the absolute x- and y-position depends on the computed font size of the element itself.\n\nLink Colours\n\nThe same descendant selectors we use to set and position the type are also used to apply the colour by combining them with pseudo-selectors like :focus and :hover. Because the descendant selectors are available to us, we can pretty much pick out any glyph we like. First, we need to disable the underline:\n\n#type h1 a:link,\n#type h1 a:visited{\n\ttext-decoration: none;\n}\n\nIn our example, the \u201c24\u201d has a unique default state (colour):\n\n#type h1 a:link em,\n#type h1 a:visited em{\n\tcolor: #624;\n}\n\nThe rest of the \u201cWays\u201d text has a different colour, which it shares with the large \u201cs\u201d in \u201cimpress\u201d:\n\n#type h1 a:link em span span,\n#type h1 a:visited em span span,\n#type h1 a:link strong span span span span,\n#type h1 a:visited strong span span span span{\n\tcolor: #b32720;\n}\n\n\u201c24\u201d changes on :focus, :hover and :active. Critically though, the whole of the \u201c24 Ways\u201d text, and the large \u201cs\u201d in \u201cimpress\u201d all have the same style in this instance:\n\n#type h1 a:focus em,\n#type h1 a:hover em,\n#type h1 a:active em,\n#type h1 a:focus em span span,\n#type h1 a:hover em span span,\n#type h1 a:active em span span,\n#type h1 a:focus strong span span span span,\n#type h1 a:hover strong span span span span,\n#type h1 a:active strong span span span span{\n\tcolor: #804;\n}\n\nIf a descendant selector has a :link and :visited state set as a pseudo element, it needs to also have the corresponding :focus, :hover and :active states set.\n\nA Final Note About Web Typography\n\nFrom grids to basic leading to web fonts, and even absolute positioning, there\u2019s a wealth of things we can do to treat type on the Web with love and respect. However, experiments like this can highlight the vagaries of rasterisation and rendering that limit our ability to achieve truly subtle and refined results. At the operating system level, the differences in type rendering are extreme, and even between sequential iterations in Windows\u200a\u2014\u200afrom Standard to ClearType\u200a\u2014\u200athey can be daunting. Add to that huge variations in screen quality, and even the paper we print our type onto has many potential variations. Compare our example in Safari 3.2.1 / OS X 10.5.5 (left) and IE7 / Win XP (right). Both rendered on a 23\u201d Apple Cinema HD (LCD):\n\n\n\nBrowser developers continue to make great strides. However, those of us who set type on the Web need more consistency and quality if we want to avoid technologies like Flash and evolve web typography. Although web typography is inevitably\u200a\u2014\u200aand mistakenly\u200a\u2014\u200acompared unfavourably to print, it has the potential to achieve the same refinement in a different way. Perhaps one day, the glyphs of our favourite faces, so carefully crafted, kerned and hinted for the screen, will be rendered with the same precision with which they were drawn by type designers and styled by web designers. That would be my wish for the new year. Happy holidays!", "year": "2008", "author": "Jon Tan", "author_slug": "jontan", "published": "2008-12-17T00:00:00+00:00", "url": "https://24ways.org/2008/a-festive-type-folly/", "topic": "design"} {"rowid": 109, "title": "Geotag Everywhere with Fire Eagle", "contents": "A note from the editors: Since this article was written Yahoo! has retired the Fire Eagle service.\n \n \n \n Location, they say, is everywhere. Everyone has one, all of the time. But on the web, it\u2019s taken until this year to see the emergence of location in the applications we use and build.\n\nThe possibilities are broad. Increasingly, mobile phones provide SDKs to approximate your location wherever you are, browser extensions such as Loki and Mozilla\u2019s Geode provide browser-level APIs to establish your location from the proximity of wireless networks to your laptop. Yahoo\u2019s Brickhouse group launched Fire Eagle, an ambitious location broker enabling people to take their location from any of these devices or sources, and provide it to a plethora of web services. It enables you to take the location information that only your iPhone knows about and use it anywhere on the web.\n\nThat said, this is still a time of location as an emerging technology. Fire Eagle stores your location on the web (protected by application-specific access controls), but to try and give an idea of how useful and powerful your location can be \u2014 regardless of the services you use now \u2014 today\u2019s 24ways is going to build a bookmarklet to call up your location on demand, in any web application.\n\nLocation Support on the Web\n\nOver the past year, the number of applications implementing location features has increased dramatically. Plazes and Brightkite are both full featured social networks based around where you are, whilst Pownce rolled in Fire Eagle support to allow geotagging of all the content you post to their microblogging service. Dipity\u2019s beautiful timeline shows for you moving from place to place and Six Apart\u2019s activity stream for Movable Type started exposing your movements.\n\nThe number of services that hook into Fire Eagle will increase as location awareness spreads through the developer community, but you can use your location on other sites indirectly too.\n\nConsider Flickr. Now world renowned for their incredible mapping and places features, geotagging on Flickr started out as a grassroots extension of regular tagging. That same technique can be used to start rolling geotagging in any publishing platform you come across, for any kind of content. Machine-tags (geo:lat= and geo:lon=) and the adr and geo microformats can be used to enhance anything you write with location information.\n\nA crash course in avian inflammability\n\nFire Eagle is a location store. A broker between services and devices which provide location and those which consume it. It\u2019s a switchboard that controls which pieces of your location different applications can see and use, and keeps hidden anything you want kept private. A blog widget that displays your current location in public can be restricted to display just your current city, whilst a service that provides you with a list of the nearest ATMs will operate better with a precise street address. \n\nEven if your iPhone tells Fire Eagle exactly where you are, consuming applications only see what you want them to see. That\u2019s important for users to realise that they\u2019re in control, but also important for application developers to remember that you cannot rely on having super-accurate information available all the time. You need to build location aware applications which degrade gracefully, because users will provide fuzzier information \u2014 either through choice, or through less accurate sources.\n\nApplication specific permissions are controlled through an OAuth API. Each application has a unique key, used to request a second, user-specific key that permits access to that user\u2019s information. You store that user key and it remains valid until such a time as the user revokes your application\u2019s access. Unlike with passwords, these keys are unique per application, so revoking the access rights of one application doesn\u2019t break all the others.\n\nBuilding your first Fire Eagle app; Geomarklet\n\nFire Eagle\u2019s developer documentation can take you through examples of writing simple applications using server side technologies (PHP, Python). Here, we\u2019re going to write a client-side bookmarklet to make your location available in every site you use. It\u2019s designed to fast-track the experience of having location available everywhere on web, and show you how that can be really handy. Hopefully, this will set you thinking about how location can enhance the new applications you build in 2009.\n\nAn oddity of bookmarklets\n\nBookmarklets (or \u2018favlets\u2019, for those of an MSIE persuasion) are a strange environment to program in. Critically, you have no persistent storage available. As such, using token-auth APIs in a static environment requires you to build you application in a slightly strange way; authing yourself in advance and then hardcoding the keys into your script.\n\nGet started\n\nBefore you do anything else, go to http://fireeagle.com and log in, get set up if you need to and by all means take a look around. Take a look at the mobile updaters section of the application gallery and perhaps pick out an app that will update Fire Eagle from your phone or laptop.\n\nOnce that\u2019s done, you need to register for an application key in the developer section. Head straight to /developer/create and complete the form. Since you\u2019re building a standalone application, choose \u2018Auth for desktop applications\u2019 (rather than web applications), and select that you\u2019ll be \u2018accessing location\u2019, not updating.\n\nAt the end of this process, you\u2019ll have two application keys, a \u2018Consumer Key\u2019 and a \u2018Consumer Secret\u2019, which look like these:\n\n \n Consumer Key\n luKrM9U1pMnu\n Consumer Secret\n ZZl9YXXoJX5KLiKyVrMZffNEaBnxnd6M\n \n\nThese keys combined allow your application to make requests to Fire Eagle.\n\nNext up, you need to auth yourself; granting your new application permission to use your location. Because bookmarklets don\u2019t have local storage, you can\u2019t integrate the auth process into the bookmarklet itself \u2014 it would have no way of storing the returned key. Instead, I\u2019ve put together a simple web frontend through which you can auth with your application.\n\nHead to Auth me, Amadeus!, enter the application keys you just generated and hit \u2018Authorize with Fire Eagle\u2019. You\u2019ll be taken to the Fire Eagle website, just as in regular Fire Eagle applications, and after granting access to your app, be redirected back to Amadeus which will provide you your user tokens. These tokens are used in subsequent requests to read your location.\n\nAnd, skip to the end\u2026\n\nThe process of building the bookmarklet, making requests to Fire Eagle, rendering it to the page and so forth follows, but if you\u2019re the impatient type, you might like to try this out right now. Take your four API keys from above, and drag the following link to your Bookmarks Toolbar; it contains all the code described below. Before you can use it, you need to edit in your own API keys. Open your browser\u2019s bookmark editor and where you find text like \u2018YOUR_CONSUMER_KEY_HERE\u2019, swap in the corresponding key you just generated.\n\nGet Location\n\nBookmarklet Basics\n\nTo start on the bookmarklet code, set out a basic JavaScript module-pattern structure:\n\nvar Geomarklet = function() {\n\treturn ({\n\t\tcallback: function(json) {},\n\t\trun: function() {}\n\t});\n};\nGeomarklet.run();\n\nNext we\u2019ll add the keys obtained in the setup step, and also some basic Fire Eagle support objects:\n\nvar Geomarklet = function() {\n\tvar Keys = {\n\t\t\tconsumer_key: 'IuKrJUHU1pMnu',\n\t\t\tconsumer_secret: 'ZZl9YXXoJX5KLiKyVEERTfNEaBnxnd6M',\n\t\t\tuser_token: 'xxxxxxxxxxxx',\n\t\t\tuser_secret: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'\n\t};\n\tvar LocationDetail = {\n\t\t\tEXACT: 0,\n\t\t\tPOSTAL: 1,\n\t\t\tNEIGHBORHOOD: 2,\n\t\t\tCITY: 3,\n\t\t\tREGION: 4,\n\t\t\tSTATE: 5,\n\t\t\tCOUNTRY: 6\n\t};\n\tvar index_offset;\n\treturn ({\n\t\tcallback: function(json) {},\n\t\trun: function() {}\n\t});\n};\nGeomarklet.run();\n\nThe Location Hierarchy\n\nA successful Fire Eagle query returns an object called the \u2018location hierarchy\u2019. Depending on the level of detail shared, the index of a particular piece of information in the array will vary. The LocationDetail object maps the array indices of each level in the hierarchy to something comprehensible, whilst the index_offset variable is an adjustment based on the detail of the result returned.\n\nThe location hierarchy object looks like this, providing a granular breakdown of a location, in human consumable and machine-friendly forms.\n\n\"user\": {\n\t\t\"location_hierarchy\": [{\n\t\t\t\"level\": 0,\n\t\t\t\"level_name\": \"exact\",\n\t\t\t\"name\": \"707 19th St, San Francisco, CA\",\n\t\t\t\"normal_name\": \"94123\",\n\t\t\t\"geometry\": {\n\t\t\t\t\t\"type\": \"Point\",\n\t\t\t\t\t\"coordinates\": [ - 0.2347530752, 67.232323]\n\t\t\t},\n\t\t\t\"label\": null,\n\t\t\t\"best_guess\": true,\n\t\t\t\"id\": ,\n\t\t\t\"located_at\": \"2008-12-18T00:49:58-08:00\",\n\t\t\t\"query\": \"q=707%2019th%20Street,%20Sf\"\n\t\t},\n\t\t{\n\t\t\t\t\"level\": 1,\n\t\t\t\t\"level_name\": \"postal\",\n\t\t\t\t\"name\": \"San Francisco, CA 94114\",\n\t\t\t\t\"normal_name\": \"12345\",\n\t\t\t\t\"woeid\": ,\n\t\t\t\t\"place_id\": \"\",\n\t\t\t\t\"geometry\": {\n\t\t\t\t\t\t\"type\": \"Polygon\",\n\t\t\t\t\t\t\"coordinates\": [],\n\t\t\t\t\t\t\"bbox\": []\n\t\t\t\t},\n\t\t\t\t\"label\": null,\n\t\t\t\t\"best_guess\": false,\n\t\t\t\t\"id\": 59358791,\n\t\t\t\t\"located_at\": \"2008-12-18T00:49:58-08:00\"\n\t\t},\n\t\t{\n\t\t\t\t\"level\": 2,\n\t\t\t\t\"level_name\": \"neighborhood\",\n\t\t\t\t\"name\": \"The Mission, San Francisco, CA\",\n\t\t\t\t\"normal_name\": \"The Mission\",\n\t\t\t\t\"woeid\": 23512048,\n\t\t\t\t\"place_id\": \"Y12JWsKbApmnSQpbQg\",\n\t\t\t\t\"geometry\": {\n\t\t\t\t\t\t\"type\": \"Polygon\",\n\t\t\t\t\t\t\"coordinates\": [],\n\t\t\t\t\t\t\"bbox\": []\n\t\t\t\t},\n\t\t\t\t\"label\": null,\n\t\t\t\t\"best_guess\": false,\n\t\t\t\t\"id\": 59358801,\n\t\t\t\t\"located_at\": \"2008-12-18T00:49:58-08:00\"\n\t\t\t},\n\t\t}\n\nIn this case the first object has a level of 0, so the index_offset is also 0.\n\nPrerequisites\n\nTo query Fire Eagle we call in some existing libraries to handle the OAuth layer and the Fire Eagle API call. Your bookmarklet will need to add the following scripts into the page:\n\n\n\tThe SHA1 encryption algorithm\n\tThe OAuth wrapper\n\tAn extension for the OAuth wrapper\n\tThe Fire Eagle wrapper itself\n\n\nWhen the bookmarklet is first run, we\u2019ll insert these scripts into the document. We\u2019re also inserting a stylesheet to dress up the UI that will be generated.\n\nIf you want to follow along any of the more mundane parts of the bookmarklet, you can download the full source code.\n\nRendering\n\nThis bookmarklet can be extended to support any formatting of your location you like, but for sake of example I\u2019m going to build three common formatters that you\u2019ll find useful for common location scenarios: Sites which already ask for your location; and in publishing systems that accept tags or HTML mark-up.\n\nAll the rendering functions are items in a renderers object, so they can be iterated through easily, making it trivial to add new formatting functions as your find new use cases (just add another function to the object).\n\nvar renderers = {\ngeotag: function(user) {\n\tif(LocationDetail.EXACT !== index_offset) {\n\t\t\treturn false;\n\t}\n\telse {\n\t\tvar coords =\n\t\t\tuser.location_hierarchy[LocationDetail.EXACT].geometry.coordinates;\n\t\treturn \"geo:lat=\" + coords[0] + \", geo:lon=\" + coords[1];\n\t}\n},\ncity: function(user) {\n\tif(LocationDetail.CITY < index_offset) {\n\t\treturn false;\n\t}\n\telse {\n\t\treturn user.location_hierarchy[LocationDetail.CITY - index_offset].name; \n\t}\t\t\t\t\t\t \n}\n\nYou should always fail gracefully, and in line with catering to users who choose not to share their location precisely, always check that the location has been returned at the level you require. Geotags are expected to be precise, so if an exact location is unavailable, returning false will tell the rendering aspect of the bookmarklet to ignore the function altogether.\n\nThese first two are quite simple, geotag returns geo:lat=-0.2347530752, geo:lon=67.232323 and city returns San Francisco, CA.\n\nThis final renderer creates a chunk of HTML using the adr and geo microformats, using all available aspects of the location hierarchy, and can be used to geotag any content you write on your blog or in comments:\n\nhtml: function(user) {\n\tvar geostring = '';\n\tvar adrstring = '';\n\tvar adr = [];\t\t \n\tadr.push('

');\n\t// city\n\tif(LocationDetail.CITY >= index_offset) {\n\t\tadr.push(\n\t\t\t'\\n\t\t '\n\t\t+ user.location_hierarchy[LocationDetail.CITY-index_offset].normal_name\n\t\t+ ','\n\t\t);\n\t}\n\t// county\n\tif(LocationDetail.REGION >= index_offset) {\n\t\tadr.push(\n\t\t\t'\\n\t\t ' \n\t\t+ user.location_hierarchy[LocationDetail.REGION-index_offset].normal_name\n\t\t+ ','\n\t\t\t);\n\t}\n\t// locality\n\tif(LocationDetail.STATE >= index_offset) {\n\t\tadr.push(\n\t\t\t'\\n\t\t '\n\t\t+ user.location_hierarchy[LocationDetail.STATE-index_offset].normal_name\n\t\t+ ','\n\t\t);\n\t}\n\t// country\n\tif(LocationDetail.COUNTRY >= index_offset) {\n\t\tadr.push(\n\t\t\t'\\n\t\t '\n\t\t+ user.location_hierarchy[LocationDetail.COUNTRY-index_offset].normal_name\n\t\t+ ''\n\t\t);\n\t}\n\t// postal\n\tif(LocationDetail.POSTAL >= index_offset) {\n\t\tadr.push(\n\t\t\t'\\n\t\t '\n\t\t+ user.location_hierarchy[LocationDetail.POSTAL-index_offset].normal_name\n\t\t+ ','\n\t\t);\n\t}\n\tadr.push('\\n

\\n');\n\tadrstring = adr.join('');\n\tif(LocationDetail.EXACT === index_offset) {\n\t\tvar coords = \n\t\t\tuser.location_hierarchy[LocationDetail.EXACT].geometry.coordinates;\n\t\tgeostring = '

'\n\t\t\t+'\\n\t\t'\n\t\t\t+ coords[0]\n\t\t\t+ ';'\n\t\t\t+ '\\n\t\t '\n\t\t\t+ coords[1]\n\t\t\t+ '\\n

\\n';\n\t}\n\treturn (adrstring + geostring);\n}\n\nHere we check the availability of every level of location and build it into the adr and geo patterns as appropriate. Just as for the geotag function, if there\u2019s no exact location the geo markup won\u2019t be returned.\n\nFinally, there\u2019s a rendering method which creates a container for all this data, renders all the applicable location formats and then displays them in the page for a user to copy and paste. You can throw this together with DOM methods and some simple styling, or roll in some components from YUI or JQuery to handle drawing full featured overlays.\n\nYou can see this simple implementation for rendering in the full source code.\n\nMake the call\n\nWith a framework in place to render Fire Eagle\u2019s location hierarchy, the only thing that remains is to actually request your location. Having already authed through Amadeus earlier, that\u2019s as simple as instantiating the Fire Eagle JavaScript wrapper and making a single function call. It\u2019s a big deal that whilst a lot of new technologies like OAuth add some complexity and require new knowledge to work with, APIs like Fire Eagle are really very simple indeed.\n\nreturn {\n\trun: function() {\n\t\tinsert_prerequisites();\n\t\tsetTimeout(\n\t\t\tfunction() {\n\t\t\t\tvar fe = new FireEagle(\n\t\t\t\t\tKeys.consumer_key,\n\t\t\t\t\tKeys.consumer_secret,\n\t\t\t\t\tKeys.user_token,\n\t\t\t\t\tKeys.user_secret\n\t\t\t\t);\n\t\t\t\tvar script = document.createElement('script');\n\t\t\t\tscript.type = 'text/javascript';\n\t\t\t\tscript.src = fe.getUserUrl(\n\t\t\t\t\tFireEagle.RESPONSE_FORMAT.json,\n\t\t\t\t\t'Geomarklet.callback'\n\t\t\t\t);\n\t\t\t\tdocument.body.appendChild(script);\n\t\t\t},\n\t\t\t2000\n\t\t);\n\t},\n\tcallback: function(json) {\n\t\tif(json.rsp && 'fail' == json.rsp.stat) {\n\t\t\talert('Error ' + json.rsp.code + \": \" + json.rsp.message);\n\t\t}\n\t\telse {\n\t\t\tindex_offset = json.user.location_hierarchy[0].level;\t\t\t\t\t\t \n\t\t\tdraw_selector(json);\n\t\t}\n\t}\n};\n\nWe first insert the prerequisite scripts required for the Fire Eagle request to function, and to prevent trying to instantiate the FireEagle object before it\u2019s been loaded over the wire, the remaining instantiation and request is wrapped inside a setTimeout delay.\n\nWe then create the request URL, referencing the Geomarklet.callback callback function and then append the script to the document body \u2014 allowing a cross-domain request.\n\nThe callback itself is quite simple. Check for the presence and value of rsp.status to test for errors, and display them as required. If the request is successful set the index_offset \u2014 to adjust for the granularity of the location hierarchy \u2014 and then pass the object to the renderer.\n\nThe result? When Geomarklet.run() is called, your location from Fire Eagle is read, and each renderer displayed on the page in an easily copy and pasteable form, ready to be used however you need.\n\nDeploy\n\nThe final step is to convert this code into a long string for use as a bookmarklet. Easiest for Mac users is the JavaScript bundle in TextMate \u2014 choose Bundles: JavaScript: Copy as Bookmarklet to Clipboard. Then create a new \u2018Get Location\u2019 bookmark in your browser of choice and paste in.\n\nThose without TextMate can shrink their code down into a single line by first running their code through the JSLint tool (to ensure the code is free from errors and has all the required semi-colons) and then use a find-and-replace tool to remove line breaks from your code (or even run your code through JSMin to shrink it down).\n\nWith the bookmarklet created and added to your bookmarks bar, you can now call up your location on any page at all. Get a feel for a web where your location is just another reliable part of the browsing experience.\n\nWhere next?\n\nSo, the Geomarklet you\u2019ve been guided through is a pretty simple premise and pretty simple output. But from this base you can start to extend: Add code that will insert each of the location renderings directly into form fields, perhaps, or how about site-specific handlers to add your location tags into the correct form field in Wordpress or Tumblr? Paste in your current location to Google Maps? Or Flickr?\n\nGeomarklet gives you a base to start experimenting with location on your own pages and the sites you browse daily.\n\nThe introduction of consumer accessible geo to the web is an adventure of discovery; not so much discovering new locations, but discovering location itself.", "year": "2008", "author": "Ben Ward", "author_slug": "benward", "published": "2008-12-21T00:00:00+00:00", "url": "https://24ways.org/2008/geotag-everywhere-with-fire-eagle/", "topic": "code"} {"rowid": 110, "title": "Shiny Happy Buttons", "contents": "Since Mac OS X burst onto our screens, glossy, glassy, shiny buttons have been almost de rigeur, and have essentially, along with reflections and rounded corners, become a clich\u00e9 of Web 2.0 \u201cdesign\u201d. But if you can\u2019t beat \u2018em you\u2019d better join \u2018em. So, in this little contribution to our advent calendar, we\u2019re going to take a plain old boring HTML button, and 2.0 it up the wazoo. \n\nBut, here\u2019s the catch. We\u2019ll use no images, either in our HTML or our CSS. No sliding doors, no image replacement techniques. Just straight up, CSS, CSS3 and a bit of experimental CSS. And, it will be compatible with pretty much any browser (though with some progressive enhancement for those who keep up with the latest browsers).\n\nThe HTML\n\nWe\u2019ll start with our HTML.\n\n\n\nOK, so it\u2019s not shiny yet \u2013 but boy will it ever be.\n\nBefore styling, that\u2019s going to look like this.\n\nIronically, depending on the operating system and browser you are using, it may well be a shiny button already, but that\u2019s not the point. We want to make it shiny 2.0. Our mission is to make it look something like this\n\n\n\nIf you want to follow along at home keep in mind that depending on which browser you are using you may see fewer of the CSS effects we\u2019ve added to create the button. As of writing, only in Safari are all the effects we\u2019ll apply supported.\n\nTaking a look at our finished product, here\u2019s what we\u2019ve done to it:\n\n\n\tWe\u2019ve given the button some padding and a width.\n\tWe\u2019ve changed the text color, and given the text a drop shadow.\n\tWe\u2019ve given the button a border.\n\tWe\u2019ve given the button some rounded corners.\n\tWe\u2019ve given the button a drop shadow.\n\tWe\u2019ve given the button a gradient background.\n\n\nand remember, all without using any images.\n\nStyling the button\n\nSo, let\u2019s get to work.\n\nFirst, we\u2019ll add given the element some padding and a width:\n\nbutton {\n\tpadding: .5em;\n\twidth: 15em;\n}\n\nNext, we\u2019ll add the text color, and the drop shadow:\n\ncolor: #ffffff;\ntext-shadow: 1px 1px 1px #000;\n\nA note on text-shadow\n\nIf you\u2019ve not seen text-shadows before well, here\u2019s the quick back-story. Text shadow was introduced in CSS2, but only supported in Safari (version 1!) some years later. It was removed from CSS2.1, but returned in CSS3 (in the text module). It\u2019s now supported in Safari, Opera and Firefox (3.1). Internet Explorer has a shadow filter, but the syntax is completely different.\n\nSo, how do text-shadows work? The three length values specify respectively a horizontal offset, a vertical offset and a blur (the greater the number the more blurred the shadow will be), and finally a color value for the shadow.\n\nRounding the corners\n\nNow we\u2019ll add a border, and round the corners of the element:\n\nborder: solid thin #882d13;\n-webkit-border-radius: .7em;\n-moz-border-radius: .7em;\nborder-radius: .7em;\n\nHere, we\u2019ve used the same property in three slightly different forms. We add the browser specific prefix for Webkit and Mozilla browsers, because right now, both of these browsers only support border radius as an experimental property. We also add the standard property name, for browsers that do support the property fully in the future. \n\nThe benefit of the browser specific prefix is that if a browser only partly supports a given property, we can easily avoid using the property with that browser simply by not adding the browser specific prefix. At present, as you might guess, border-radius is supported in Safari and Firefox, but in each the relevant prefix is required.\n\nborder-radius takes a length value, such as pixels. (It can also take two length values, but that\u2019s for another Christmas.) In this case, as with padding, I\u2019ve used ems, which means that as the user scales the size of text up and down, the radius will scale as well. You can test the difference by making the radius have a value of say 5px, and then zooming up and down the text size. \n\nWe\u2019re well and truly on the way now. All we need to do is add a shadow to the button, and then a gradient background.\n\nIn CSS3 there\u2019s the box-shadow property, currently only supported in Safari 3. It\u2019s very similar to text-shadow \u2013 you specify a horizontal and vertical offset, a blur value and a color.\n\n-webkit-box-shadow: 2px 2px 3px #999; \nbox-shadow: 2px 2px 2px #bbb;\n\nOnce more, we require the \u201cexperimental\u201d -webkit- prefix, as Safari\u2019s support for this property is still considered by its developers to be less than perfect.\n\nGradient Background\n\nSo, all we have left now is to add our shiny gradient effect. Now of course, people have been doing this kind of thing with images for a long time. But if we can avoid them all the better. Smaller pages, faster downloads, and more scalable designs that adapt better to the user\u2019s font size preference. But how can we add a gradient background without an image?\n\nHere we\u2019ll look at the only property that is not as yet part of the CSS standard \u2013 Apple\u2019s gradient function for use anywhere you can use images with CSS (in this case backgrounds). In essence, this takes SVG gradients, and makes them available via CSS syntax.\n\nHere\u2019s what the property and its value looks like:\n\nbackground-image: -webkit-gradient(linear, left top, left bottom, from(#e9ede8), to(#ce401c),color-stop(0.4, #8c1b0b));\n\nZooming in on the gradient function, it has this basic form:\n\n-webkit-gradient(type, point, point, from(color), to(color),color-stop(where, color));\n\nWhich might look complicated, but is less so than at first glance.\n\nThe name of the function is gradient (and in this case, because it is an experimental property, we use the -webkit- prefix).\n\nYou might not have seen CSS functions before, but there are others, including the attr() function, used with generated content. A function returns a value that can be used as a property value \u2013 here we are using it as a background image.\n\nNext we specify the type of the gradient. Here we have a linear gradient, and there are also radial gradients. \n\nAfter that, we specify the start and end points of the gradient \u2013 in our case the top and bottom of the element, in a vertical line. \n\nWe then specify the start and end colors \u2013 and finally one stop color, located at 40% of the way down the element. Together, this creates a gradient that smoothly transitions from the start color in the top, vertically to the stop color, then smoothly transitions to the end color.\n\nThere\u2019s one last thing. What color will the background of our button be if the browser doesn\u2019t support gradients? It will be white (or possibly some default color for buttons). Which may make the text difficult or impossible to read. So, we\u2019ll add a background color as well (see why the validator is always warning you when a color but not a background color is specified for an element?).\n\nIf we put it all together, here\u2019s what we have:\n\nbutton {\n\twidth: 15em;\n\tpadding: .5em;\n\tcolor: #ffffff;\n\ttext-shadow: 1px 1px 1px #000;\n\tborder: solid thin #882d13;\n\t-webkit-border-radius: .7em;\n\t-moz-border-radius: .7em;\n\tborder-radius: .7em;\n\t-webkit-box-shadow: 2px 2px 3px #999; \n\tbox-shadow: 2px 2px 2px #bbb;\n\tbackground-color: #ce401c;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from(#e9ede8), to(#ce401c),color-stop(0.4, #8c1b0b));\n}\n\nWhich looks like this in various browsers:\n\nIn Safari (3)\n\n\n\nIn Firefox 3.1 (3.0 supports border-radius but not text-shadow)\n\n\n\nIn Opera 10\n\n\n\nand of course in Internet Explorer (version 8 shown here)\n\n\n\nBut it looks different in different browsers\n\nYes, it does look different in different browsers, but we all know the answer to the question \u201cdo web sites need to look the same in every browser?\u201c.\n\nEven if you really think sites should look the same in every browser, hopefully this little tutorial has whet your appetite for what CSS3 and experimental CSS that\u2019s already supported in widely used browsers (and we haven\u2019t even touched on animations and similar effects!).\n\nI hope you\u2019ve enjoyed out little CSSMas present, and look forward to seeing your shiny buttons everywhere on the web.\n\nOh, and there\u2019s just a bit of homework \u2013 your job is to use the :hover selector, and make a gradient in the hover state.", "year": "2008", "author": "John Allsopp", "author_slug": "johnallsopp", "published": "2008-12-18T00:00:00+00:00", "url": "https://24ways.org/2008/shiny-happy-buttons/", "topic": "code"} {"rowid": 111, "title": "Geometric Background Patterns", "contents": "When the design is finished and you\u2019re about to start the coding process, you have to prepare your graphics. If you\u2019re working with a pattern background you need to export only the repeating fragment. It can be a bit tricky to isolate a fragment to achieve a seamless pattern background. For geometric patterns there is a method I always follow and that I want to share with you. Take for example a perfect 45\u00b0 diagonal line pattern. \n\n\n\nHow do you define this pattern fragment so it will be rendered seamlessly?\n\n\n\nHere is the method I usually follow to avoid a mismatch. First, zoom in so you see enough detail and you can distinguish the pixels. Select the Rectangular Marquee Selection tool and start your selection at the intersection of 2 different colors of a diagonal line. Hold down the Shift key while dragging so you drag a perfect square.\n\n\n\nRelease the mouse when you reach the exact same intesection (as your starting) point at the top right. \n\n\n\nCopy this fragment (using Copy Merged: Cmd/Ctrl + Shift + C) and paste the fragment in a new layer. Give this layer the name \u2018pattern\u2019. Now hold down the Command Key (Control Key on Windows) and click on the \u2018pattern\u2019 layer in the Layers Palette to select the fragment. Now go to Edit > Define Pattern, enter a name for your pattern and click OK. Test your pattern in a new document. Create a new document of 600 px by 400px, hit Cmd/Ctrl + A and go to Edit > Fill\u2026 and choose your pattern. If the result is OK, you have created a perfect pattern fragment.\n\n\n\nBelow you see this pattern enlarged. The guides show the boundaries of the pattern fragment and the red pixels are the reference points. The red pixels at the top right, bottom right and bottom left should match the red pixel at the top left.\n\n\n\nThis technique should work for every geometric pattern. Some patterns are easier than others, but this, and the Photoshop pattern fill test, has always been my guideline.\n\nOther geometric pattern examples\n\nExample 1\n\nNot all geometric pattern fragments are squares. Some patterns look easy at first sight, because they look very repetitive, but they can be a bit tricky.\n\n\n\nZoomed in pattern fragment with point of reference shown:\n\n\n\nExample 2\n\nSome patterns have a clear repeating point that can guide you, such as the blue small circle of this pattern as you can see from this zoomed in screenshot:\n\n\n\nZoomed in pattern fragment with point of reference shown:\n\n\n\nExample 3\n\nThe different diagonal colors makes a bit more tricky to extract the correct pattern fragment. \n\n\n\nThe orange dot, which is the starting point of the selection is captured a few times inside the fragment selection:", "year": "2008", "author": "Veerle Pieters", "author_slug": "veerlepieters", "published": "2008-12-02T00:00:00+00:00", "url": "https://24ways.org/2008/geometric-background-patterns/", "topic": "design"} {"rowid": 112, "title": "User Styling", "contents": "During the recent US elections, Twitter decided to add an \u2018election bar\u2019 as part of their site design. You could close it if it annoyed you, but the action wasn\u2019t persistent and the bar would always come back like a bad penny. \n\nThe solution to common browsing problems like this is CSS. \u2018User styling\u2019 (or the creepy \u2018skinning\u2019) is the creation of CSS rules to customise and personalise a particular domain. Aside from hiding adverts and other annoyances, there are many reasons for taking the time and effort to do it:\n\n\n\tImproving personal readability by changing text size and colour\n\tPersonalising the look of a web app like GMail to look less insipid\n\tRevealing microformats\n\tSport! My dreams of site skinning tennis are not yet fully realised, but it\u2019ll be all the rage by next Christmas, believe me.\n\n\nHopefully you\u2019re now asking \u201cBut how? HOW?!\u201d. The process of creating a site skin is roughly as follows:\n\n\n\tSee something you want to change\n\tFind out what it\u2019s called, and if any rules already apply to it\n\tWrite CSS rule(s) to override and/or enhance it.\n\tApply the rules\n\n\nSo let\u2019s get stuck in\u2026\n\nSee something\n\nLet\u2019s start small with Multimap.com. Look at that big header \u2013 it takes up an awful lot of screen space doesn\u2019t it? \n\n\n\nNo matter, we can fix it.\n\nTools\n\nNow we need to find out where that big assed header is in the DOM, and make overriding CSS rules. The best tool I\u2019ve found yet is the Mac OS X app, CSS Edit. It utilises a slick \u2018override stylesheets\u2019 function and DOM Inspector. Rather than give you all the usual DOM inspection tools, CSS Edit\u2019s is solely concerned with style. Go into \u2018X-Ray\u2019 mode, click an element, and look at the inspector window to see every style rule governing it. Click the selector to be taken to where it lives in the CSS. It really is a user styling dream app.\n\n\n\nHaving said all that, you can achieve all this with free, cross platform tools \u2013 namely Firefox with the Firebug and Stylish extensions. We\u2019ll be using them for these examples, so make sure you have them installed if you want to follow along.\n\n\n\nUsing Firebug, we can see that the page is very helpfully marked up, and that whole top area is simply a div with an ID of header. \n\nChange Something\n\nWhen you installed Stylish, it added a page and brush icon to your status bar. Click on that, and choose Write Style > for Multimap.com. The other options allow you to only create a style for a particular part of a website or URL, but we want this to apply to the whole of Multimap:\n\n\n\nThe \u2018Add Style\u2019 window then pops up, with the @-moz-document query at the top:\n\n@namespace url(http://www.w3.org/1999/xhtml);\n@-moz-document domain(\"multimap.com\") {\n}\n\nAll you need to do is add the CSS to hide the header, in between the curly brackets.\n\n@namespace url(http://www.w3.org/1999/xhtml);\n@-moz-document domain(\"multimap.com\") {\n #header {display: none;} \n}\n\n\n\nA click of the preview button shows us that it\u2019s worked! Now the map appears further up the page. The ethics of hiding adverts is a discussion for another time, but let\u2019s face it, when did you last whoop at the sight of a banner?\n\nMake Something Better\n\nIf we\u2019re happy with our modifications, all we need to do is give it a name and save. Whenever you visit Multimap.com, the style will be available. Stylish also allows you to toggle a style on/off via the status bar menu. If you feel you want to share this style with the world, then userstyles.org is the place to do it. It\u2019s a grand repository of customisations that Stylish connects with. Whenever you visit a site, you can see if anyone else has written a style for it, again, via the status bar menu \u201cFind Styles for this Page\u201d. Selecting this with \u201cBBC News\u201d shows that there are plenty of options, ranging from small layout tweaks to redesigns:\n\n\n\nWhat\u2019s more, whenever a style is updated, Stylish will notify you, and offer a one-click process to update it. This does only work in Firefox and Flock, so I\u2019ll cover ways of applying site styles to other browsers later.\n\nSpecific Techniques\n\nImportant!\n\nIn the Multimap example there wasn\u2019t a display specified on that element, but it isn\u2019t always going to be that easy. You may have spent most of your CSS life being a good designer and not resorting to adding !important to give your rule priority. There\u2019s no way to avoid this in user styling \u2013 if you\u2019re overriding an existing rule it\u2019s a necessity! Be prepared to be typing !important a lot.\n\nStar Selector\n\nThe Universal Selector is a particularly useful way to start a style. For example, if we want to make Flickr use Helvetica before Arial (as they should\u2019ve done!), we can cover all occurrences with just one rule:\n\n* {font-family: \"Helvetica Neue\", Helvetica, sans-serif !important;}\n\nYou can also use it to select \u2018everything within an element\u2019, by placing it after the element name:\n\n#content * {font-family: \"Helvetica Neue\", Helvetica, sans-serif !important;}\n\nSwapping Images\n\nIf you\u2019re changing something a little more complex, such as Google Reader, then at some point you\u2019ll probably want to change an . The technique for replacing an image involves:\n\n\n\tmaking your replacement image the background of the tag\n\tadding padding top and left to the size of you image to push the \u2018top\u2019 image away\n\tmaking the height and width zero.\n\n\n\n\nThe old image is then pushed out of the way and hidden from view, allowing the replacement in the background to be revealed. Targeting the image may require using an attribute selector:\n\nimg[src=\"/reader/ui/3544433079-tree-view-folder-open.gif\"] {\n\tpadding: 16px 0 0 16px;\n\twidth: 0 !important;\n\theight: 0 !important;\n\tbackground-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYA\nAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAA\nBx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTM5jWRgMAAAAVdE\nVYdENyZWF0aW9uIFRpbWUAMjkvNi8wOJJ/BVgAAAG3SURBVDiNpZIhb5RBEIaf\n2W+vpIagIITSBIHBgsGjEYQaFLYShcITDL+ABIPnh4BFN0GQNFA4Cnf3fbszL2L3\njiuEVLDJbCazu8+8Mzsmif9ZBvDy7bvXlni0HRe8eXL/zuPzABng62J5kFKaAQS\nQgJAOgHMB9vDZq+d71689Hcyw9LfAZAYdioE10VSJo6OPL/KNvSuHD+7dhU\n0vHEsDUUWJChIlYJIjFx5BuMB2mJY/DnMoOJl/R147oBUR0QAm8LAGCOEh3IO\nULiAl8jSOy/nPetGsbGRKjktEiBCEHMlQj4loCuu4zCXCi4lUHTNDtGqEiACTqAFSI\nOgAUAKv4bkWVy2g6tAbJtGy0TNugM3HADmlurKH27dVZSecxjboXggiAsMItR\nh99wTILdewYRpXVJWtY85k7fPW8e1GpJFJacgesXs6VYYomz9G2yDhwPB7NEB\nBDAMK7WYJlisYVBCpfaJBeB+eocFyVyAgCaoMCTJSTOOCWSyILrAnaXpSexRsx\nGGAZ0AR+XT+5fjzyfwSpnUB/1w64xizVI/t6q3b+58+vJ96mWtLf9haxNoc8M\nv7N3d+AT4XPcFIxghoAAAAAElFTkSuQmCC) no-repeat !important;\n}\n\nWoah boy! What was all that gubbins in the background-image? It was a Data URI, and you can create these easily with Hixie\u2019s online tool. It\u2019s simply the image translated into text so that it can be embedded in the CSS, cutting down on the number of http requests. It\u2019s also a necessity with Mozilla browsers, as they don\u2019t allow user CSS to reference images stored locally. Converting images to URI\u2019s avoids this, as well as making a style easily portable \u2013 no images folder to pass around. \n\nDon\u2019t forget all your other CSS techniques at your disposal: inserting your own content with :before and :after pseudo classes, make elements semi-transparent with opacity and round box corners without hacking . You can have fun, and for once, enjoy the freedom of not worrying about IE!\n\nUser styling without Stylish\n\nInstead of using the Stylish extension, you can add rules to the userContent.css file, or use @import in that file to load a separate stylesheet. You can find this is in /Library/Application Support/Camino/chrome/ on OS X, or C/Program Files/Mozilla Firefox/Chrome on Windows. This is only way to apply user styles in Camino, but what about other browsers?\n\nOpera & Omniweb: \n\nBoth allow you to specify a custom CSS file as part of the site\u2019s preferences. Opera also allows custom javascript, using the same syntax as Greasemonkey scripts (more on that below)\n\nSafari\n\nThere are a few options here: the PithHelmet and SafariStand haxies both allow custom stylesheets, or alternatively, a Greasemonkey style user script can employed via GreaseKit. The latter is my favoured solution on my Helvetireader theme, as it can allow for more prescriptive domain rules, just like the Mozilla @-moz-document method. User scripts are also the solution supported by the widest range of browsers.\n\nWhat now?\n\nHopefully I\u2019ve given you enough information for you to be able start making your own styles. If you want to go straight in and tackle the \u2018Holy Grail\u2019, then off with you to GMail \u2013 I get more requests to theme that than anything else!\n\nIf you\u2019re a site author and want to encourage this sort of tom foolery, a good way is to provide a unique class or ID name with the body tag:\n\n\n\nThis makes it very easy to write rules that only apply to that particular site. If you wanted to use Safari without any of the haxies mentioned above, this method means you can include rules in a general CSS file (chosen via Preferences > Advanced > Stylesheet) without affecting other sites. \n\nOne final revelation on user styling \u2013 it\u2019s not just for web sites. You can tweak the UI of Firefox itself with the userChrome.css. You\u2019ll need to use the in-built DOM Inspector instead of Firebug to inspect the window chrome, instead of a page. Great if you want to make small tweaks (changing the size of tab text for example) without creating a full blown theme.", "year": "2008", "author": "Jon Hicks", "author_slug": "jonhicks", "published": "2008-12-03T00:00:00+00:00", "url": "https://24ways.org/2008/user-styling/", "topic": "process"} {"rowid": 113, "title": "What Your Turkey Can Teach You About Project Management", "contents": "The problem with project management is that everyone thinks it\u2019s boring. Well, that\u2019s not really the problem. The problem is that everyone thinks it\u2019s boring but it\u2019s still really important. Project management is what lets you deliver your art \u2013 whether that be design or development. \n\nIn the same way, a Christmas dinner cooked by a brilliant chef with no organizational skills is disastrous \u2013 courses arrive in the wrong order, some things are cold whilst others are raw and generally it\u2019s a trip to the ER waiting to happen. Continuing the Christmas dinner theme, here are my top tips for successful projects, wrapped up in a nice little festive analogy. Enjoy!\n\nTip 1: Know What You\u2019re Aiming For\n\n(Turkey? Ham? Both??)\n\nThe underlying cause for the failure of so many projects is mismatched expectations. Christmas dinner cannot be a success if you serve glazed ham and your guests view turkey as the essential Christmas dinner ingredient. It doesn\u2019t matter how delicious and well executed your glazed ham is, it\u2019s still fundamentally just not turkey. You might win one or two adventurous souls over, but the rest will go home disappointed.\n\nAdd to the mix the fact that most web design projects are nowhere near as emotive as Christmas dinner (trust me, a ham vs turkey debate will rage much longer than a fixed vs fluid debate in normal human circles) and the problem is compounded. In particular, as technologists, we forget that our ability to precisely imagine the outcome of a project, be it a website, a piece of software, or similar, is much more keenly developed than the average customer of such projects. \n\nSo what\u2019s the solution? Get very clear, from the very beginning, on exactly what the project is about. What are you trying to achieve? How will you measure success? Is the presence of turkey a critical success factor?\n\nSummarize all this information in some form of document (in PM-speak, it\u2019s called a Project Initiation Document typically). Ideally, get the people who are the real decision makers to sign their agreement to that summary in their own blood. Well, you get the picture, I suppose actual blood is not strictly necessary, but a bit of gothic music to set the tone can be useful!\n\nTip 2: Plan at the Right Level of Detail\n\nHugely detailed and useless Gantt charts are a personal bugbear of mine. For any project, you should plan at the appropriate level of detail (and in an appropriate format) for the project itself. In our Christmas dinner example, it may be perfectly fine to have a list of tasks for the preparation work, but for the intricate interplay of oven availability and cooking times, something more complex is usually due. Having cooked roast dinners for fourteen in a student house where only the top oven and two of the rings on the hob actually worked, I can attest to the need for sequence diagrams in some of these situations!\n\nThe mistake many small teams make is to end up with a project plan that is really the amalgamation of their individual todo lists. What is needed is a project plan that will:\n\n\n\treflect reality\n\tbe easy to update\n\thelp to track progress (i.e. are we on track or not?)\n\n\nA good approach is to break your project into stages (each representing something tangible) and then into deliverables (again, something tangible for each milestone, else you\u2019ll never know if you\u2019ve hit it or not!). \n\nMy personal rule of thumb is that the level of granularity needed on most projects is 2-3 days \u2013 i.e. we should never be more than two to three days from a definitive milestone which will either be complete or not. The added advantage of this approach is that if find yourself off track, you can only be two to three days off track\u2026 much easier to make up than if you went weeks or even months working hard but not actually delivering what was needed!\n\nIn our Christmas dinner example, there are a number of critical milestones \u2013 a tick list of questions. Do we have all the ingredients? Check. Has the turkey been basted? Check. On the actual day, the sequencing and timing will mean more specific questions: It\u2019s 12pm. Are the Brussels sprouts cooked to death yet? Check. (Allowing for the extra hour of boiling to go from soft and green to mushy and brown\u2026 Yeuch!) \n\nTip 3: Actively Manage Risks and Issues\n\nA risk is something that could go wrong. An issue is something that has already gone wrong. Risks and issues are where project management superstars are born. Anyone can manage things when everything is going according to plan; it\u2019s what you do when Cousin Jim refuses to eat anything but strawberry jam sandwiches that sorts the men from the boys. \n\nThe key with a Christmas dinner, as with any project, is to have contingency plans for the most likely and most damaging risks. These depend on your own particular situation, but some examples might be:\n\n \n\t\t\n\t\t\tRISK\n\t\t\tCONTINGENCY PLAN\n\t\t\n\t\t\n\t\t\tCousin Jim is a picky eater.\n\t\t\tHave strawberry jam and sliced white bread on hand to placate.\n\t\t\n\t\t\n\t\t\tPrime organic turkey might not be available at Waitrose on Christmas eve.\n\t\t\tShop in advance!\n\t\t\n\t\t\n\t\t\tYou live somewhere remote that seems to lose power around Christmas on a disturbingly regular basis.\n\t\t\t(number of options here depending on how far you want to go\u2026)\n\n\t\t\t\t\tBuy a backup generator.\n\n\t\t\t\t\tInvent a new cooking method using only candles.\n\n\t\t\t\t\tStock up on \u201cChristmas dinner in a tin\u201d.\n\t\t\n\t\t\n\t\t\tYour mother in law is likely to be annoying.\n\t\t\tBottle of sherry at the ready (whether it\u2019s for you or her, you can decide!).\n\t\t\n \n\n\nThe point of planning in advance is so that most of your issues don\u2019t blindside you \u2013 you can spring into action with the contingency plan immediately. This leaves you with plenty of ingenuity and ability to cope in reserve for those truly unexpected events. \n\nBack in your regular projects, you should have a risk management plan (developed at the beginning of the project and regularly reviewed) as well as an issue list, tracking open, in progress and closed issues. Importantly, your issue list should be separate from any kind of bug list \u2013 issues are at a project level, bugs are at a technical level.\n\nTip 4: Have a Project Board\n\nA project board consists of the overall sponsor of your project (often, but not always, the guy with the cheque book) and typically a business expert and a technical expert to help advise the sponsor. The project board is the entity that is meant to make the big, critical decisions. As a project manager, your role is to prepare a recommendation, but leave the actual decision up to the board. \n\nAdmittedly this is where our Christmas dinner analogy has to stretch the most, but if you imagine that instead of just cooking for your family you are the caterer preparing a Christmas feast for a company. In this case, you obviously want to please the diners who will be eating the food, but key decisions are likely to be taken by whoever is organizing the event. They, in turn, will involve the boss if there are really big decisions that would affect the project drastically \u2013 for instance, having to move it to January, or it exceeding the set budget by a significant amount.\n\nMost projects suffer from not having a project board to consult for these major decisions, or from having the wrong people selected. The first ailment is eased by ensuring that you have a functioning project board, with whom you either meet regularly to update on status, or where there is a special process for convening the board if they are needed. The second problem is a little more subtle. Key questions to ask yourself are:\n\n\n\tWho is funding this project?\n\tWho has the authority to stop the project if it was the right thing to do?\n\tWho are the right business and technical advisors?\n\tWho are the folks who don\u2019t look like they are powerful on the org chart, but in fact might scupper this project? (e.g. administrators, tech support, personal assistants\u2026)\n\n\nTip 5: Finish Unequivocably and Well\n\nNo one is ever uncertain as to when Christmas dinner ends. Once the flaming pudding has been consumed and the cheese tray picked at, the end of the dinner is heralded by groaning and everyone collapsing in their chairs. Different households have different rituals, so you might only open your presents after Christmas dinner (unlikely if you have small children!), or you might round off the afternoon watching the Queen\u2019s speech (in Britland, certainly) or if you live in warmer climes you might round off Christmas dinner with a swim (which was our tradition in Cape Town \u2013 after 30 mins of food settling so you didn\u2019t get cramp, of course!). \n\nThe problem with projects is that they are one time efforts and so nowhere near as ritualized. Unless you have been incredibly lucky, you\u2019ve probably worked on a project where you thought you were finished but seemed unable to lose your \u201czombie customers\u201d \u2013 those folks who just didn\u2019t realise it was over and kept coming back with more and more requests. You might even have fallen prey to this yourself, believing that the website going live was the end of the project and not realising that a number of things still needed to be wrapped up.\n\nThe essence of this final tip is to inject some of that end-of-Christmas finality ritual into your projects. Find your own ritual for closing down projects \u2013 more than just sending the customer the invoice and archiving the files. Consider things like documentation, support structure handover and training to make sure that those zombies are going to the right people (hopefully not you!). \n\nSo, to summarise:\n\n\n\tMake sure you start your projects well \u2013 with an agreed (written) vision of what you\u2019re trying to achieve.\n\tPlan your projects at the right level of detail and in an appropriate format \u2013 never be more than a few days away from knowing for sure whether you\u2019re on track or not.\n\tPlan for likely and important risks and make sure you track and resolve those you actually encounter.\n\tInstitute a project board, made up of the people with the real power over your project.\n\tCreate rituals for closing projects well \u2013 don\u2019t leave anyone in doubt that the project has been delivered, or of who they should go to for further help.", "year": "2008", "author": "Meri Williams", "author_slug": "meriwilliams", "published": "2008-12-16T00:00:00+00:00", "url": "https://24ways.org/2008/what-your-turkey-can-teach-you-about-project-management/", "topic": "business"} {"rowid": 114, "title": "How To Create Rockband'ism", "contents": "There are mysteries happening in the world of business these days. We want something else by now. The business of business has to become more than business. We want to be able to identify ourselves with the brands we purchase and we want them to do good things. We want to feel cool because we buy stuff, and we don\u2019t just want a shopping experience \u2013 we want an engagement with a company we can relate to.\n\nLet me get back to \u201cfeeling cool\u201d \u2013 if we want to feel cool, we might get the companies we buy from to support that. That\u2019s why I am on a mission to make companies into rockbands.\n\nNow when I say rockbands \u2013 I don\u2019t mean the puke-y, drunky, nasty stuff that some people would highlight is also a part of rockbands. Therefore I have created my own word \u201crockband\u2019ism\u201d. This word is the definition of a childhood dream version of being in a rockband \u2013 the feeling of being more respected and loved and cool, than a cockroach or a suit on the floor of a company.\n\nRockband\u2019ism\n\nRockband\u2019ism is what we aspire to, to feel cool and happy.\n\nSo basically what I am arguing is that companies should look upon themselves as rockbands. Because the world has changed, so business needs to change as well.\n\nI have listed a couple of things you could do today to become a rockband, as a person or as a company.\n\n1 \u2013 Give your support to companies that make a difference to their surroundings \u2013 if you are buying electronics look up what the electronic producers are doing of good in the world (check out the Greenpeace Guide to Greener Electronics).\n\n2 \u2013 Implement good karma in your everyday life (and do well by doing good). What you give out you get back at some point in some shape \u2013 this can also be implemented for business.\n\n3 \u2013 WWRD? \u2013 \u201cwhat would a rockband do\u201d? or if you are into Kenny Rogers \u2013 what would he do in any given situation? This will also show yourself where your business or personal integrity lies because you actually act as a person or a rockband you admire.\n\n4 \u2013 Start leading instead of managing \u2013 If we can measure stuff why should we manage it? Leadership is key here instead of management. When you lead you tell people how to reach the stars, when you manage you keep them on the ground.\n\n5 \u2013 Respect and confide in, that people are the best at what they do. If they aren\u2019t, they won\u2019t be around for long. If they are and you keep on buggin\u2019 them, they won\u2019t be around for long either.\n\n6 \u2013 Don\u2019t be arrogant \u2013 Because audiences can\u2019t stand it \u2013 talk to people as a person not as a company.\n\n7 \u2013 Focus on your return on involvement \u2013 know that you get a return on, what you involve yourself in. No matter if it\u2019s bingo, communities, talks, ornithology or un-conferences.\n\n8 \u2013 Find out where you can make a difference and do it. Don\u2019t leave it up to everybody else to save the world.\n\n9 \u2013 Find out what you can do to become an authentic, trustworthy and remarkable company. Maybe you could even think about this a lot and make these thoughts into an actionplan.\n\n10 \u2013 Last but not least \u2013 if you\u2019re not happy \u2013 do something else, become another type of rockband, maybe a soloist of a sort, or an orchestra.\n\nNo more business as usual\n\nThis really isn\u2019t time for more business as usual, our environment (digital, natural, work or any other kind of environment) is changing. You are going to have to change too.\n\nThis article actually sprang from a talk I did at the Shift08 conference in Lisbon in October. In addition to this article for 24 ways I have turned the talk into an eBook that you can get on Toothless Tiger Press for free.\n\nMay you all have a sustainable and great Christmas full of great moments with your loved ones. December is a month for gratitude, enjoyment and love.", "year": "2008", "author": "Henriette Weber", "author_slug": "henrietteweber", "published": "2008-12-07T00:00:00+00:00", "url": "https://24ways.org/2008/how-to-create-rockbandism/", "topic": "business"} {"rowid": 115, "title": "Charm Clients, Win Pitches", "contents": "Over the years I have picked up a number of sales techniques that have lead to us doing pretty well in the pitches we go for. Of course, up until now, these top secret practices have remained firmly locked in the company vault but now I am going to share them with you. They are cunningly hidden within the following paragraphs so I\u2019m afraid you\u2019re going to have to read the whole thing.\n\nOk, so where to start? I guess a good place would be getting invited to pitch for work in the first place.\n\nShameless self promotion\n\nWhat not to do\n\nYou\u2019re as keen as mustard to \u2018sell\u2019 what you do, but you have no idea as to the right approach. From personal experience (sometimes bitter!), the following methods are as useful as the proverbial chocolate teapot:\n\n\n\tCold calling\n\tAdvertising\n\tBidding websites\n\tSales people\n\tNetworking events\n\n\nOk, I\u2019m exaggerating; sometimes these things work. For example, cold calling can work if you have a story \u2013 a reason to call and introduce yourself other than \u201cwe do web design and you have a website\u201d. \u201cWe do web design and we\u2019ve just moved in next door to you\u201d would be fine. \n\nAdvertising can work if your offering is highly specialist. However, paying oodles of dollars a day to Google Ads to appear under the search term \u2018web design\u2019 is probably not the best use of your budget. \n\nSpecialising is, in fact, probably a good way to go. Though it can feel counter intuitive in that you are not spreading yourself as widely as you might, you will eventually become an expert and therefore gain a reputation in your field. Specialism doesn\u2019t necessarily have to be in a particular skillset or technology, it could just as easily be in a particular supply chain or across a market.\n\nTarget audience\n\n\u2018Who to target?\u2019 is the next question. If you\u2019re starting out then do tap-up your family and friends. Anything that comes your way from them will almost certainly come with a strong recommendation. Also, there\u2019s nothing wrong with calling clients you had dealings with in previous employment (though beware of any contractual terms that may prevent this). You are informing your previous clients that your situation has changed; leave it up to them to make any move towards working with you. After all, you\u2019re simply asking to be included on the list of agencies invited to tender for any new work.\n\nLook to target clients similar to those you have worked with previously. Again, you have a story \u2013 hopefully a good one!\n\nSo how do you reach these people?\n\n\n\tMailing lists\n\tForums\n\tWriting articles\n\tConferences / Meetups\n\tSpeaking opportunities\n\tSharing Expertise\n\n\nIn essence: blog, chat, talk, enthuse, show off (a little)\u2026 share.\n\nThere are many ways you can do this. There\u2019s the traditional portfolio, almost obligatory blog (regularly updated of course), podcast, \u2018giveaways\u2019 like Wordpress templates, CSS galleries and testimonials. Testimonials are your greatest friend. Always ask clients for quotes (write them and ask for their permission to use) and even better, film them talking about how great you are.\n\nFinally, social networking sites can offer a way to reach your target audiences. You do have to be careful here though. You are looking to build a reputation by contributing value. Do not self promote or spam!\n\nWriting proposals\n\nIs it worth it?\n\nOk, so you have been invited to respond to a tender or brief in the form of a proposal. Good proposals take time to put together so you need to be sure that you are not wasting your time. There are two fundamental questions that you need to ask prior to getting started on your proposal:\n\n\n\tCan I deliver within the client\u2019s timescales?\n\tDoes the client\u2019s budget match my price?\n\n\nThe timescales that clients set are often plucked from the air and a little explanation about how long projects usually take can be enough to change expectations with regard to delivery. However, if a deadline is set in stone ask yourself if you can realistically meet it. Agreeing to a deadline that you know you cannot meet just to win a project is a recipe for an unhappy client, no chance of repeat business and no chance of any recommendations to other potential clients.\n\nPrice is another thing altogether. So why do we need to know?\n\nThe first reason, and most honest reason, is that we don\u2019t want to do a lot of unpaid pitch work when there is no chance that our price will be accepted. Who would? But this goes both ways \u2013 the client\u2019s time is also being wasted. It may only be the time to read the proposal and reject it, but what if all the bids are too expensive? Then the client needs to go through the whole process again.\n\nThe second reason why we need to know budgets relates to what we would like to include in a proposal over what we need to include. For example, take usability testing. We always highly recommend that a client pays for at least one round of usability testing because it will definitely improve their new site \u2013 no question. But, not doing it doesn\u2019t mean they\u2019ll end up with an unusable turkey. It\u2019s just more likely that any usability issues will crop up after launch.\n\nI have found that the best way to discover a budget is to simply provide a ballpark total, usually accompanied by a list of \u2018likely tasks for this type of project\u2019, in an initial email or telephone response. Expect a lot of people to dismiss you out of hand. This is good. Don\u2019t be tempted to \u2018just go for it\u2019 anyway because you like the client or work is short \u2013 you will regret it.\n\nOthers will say that the ballpark is ok. This is not as good as getting into a proper discussion about what priorities they might have but it does mean that you are not wasting your time and you do have a chance of winning the work. The only real risk with this approach is that you misinterpret the requirements and produce an inaccurate ballpark.\n\nFinally, there is a less confrontational approach that I sometimes use that involves modular pricing. We break down our pricing into quite detailed tasks for all proposals but when I really do not have a clue about a client\u2019s budget, I will often separate pricing into \u2018core\u2019 items and \u2018optional\u2019 items. This has proved to be a very effective method of presenting price.\n\nWhat to include\n\nSo, what should go into a proposal? It does depend on the size of the piece of work. If it\u2019s a quick update for an existing client then they don\u2019t want to read through all your blurb about why they should choose to work with you \u2013 a simple email will suffice.\n\nBut, for a potential new client I would look to include the following:\n\n\n\tYour suitability\n\tSummary of tasks\n\tTimescales\n\tProject management methodology\n\tPricing\n\tTesting methodology\n\tHosting options\n\tTechnologies\n\tImagery\n\tReferences\n\tFinancial information\n\tBiographies\n\n\nHowever, probably the most important aspect of any proposal is that you respond fully to the brief. In other words, don\u2019t ignore the bits that either don\u2019t make sense to you or you think irrelevant. If something is questionable, cover it and explain why you don\u2019t think it is something that warrants inclusion in the project.\n\nShould you provide speculative designs? If the brief doesn\u2019t ask for any, then certainly not. If it does, then speak to the client about why you don\u2019t like to do speculative designs. Explain that any designs included as part of a proposal are created to impress the client and not the website\u2019s target audience. Producing good web design is a partnership between client and agency. This can often impress and promote you as a professional. However, if they insist then you need to make a decision because not delivering any mock-ups will mean that all your other work will be a waste of time.\n\nWalking away\n\nAs I have already mentioned, all of this takes a lot of work. So, when should you be prepared to walk away from a potential job? I have already covered unrealistic deadlines and insufficient budget but there are a couple of other reasons. Firstly, would this new client damage your reputation, particularly within current sectors you are working in? Secondly, can you work with this client? A difficult client will almost certainly lead to a loss-making project.\n\nPerfect pitch\n\nRequirements\n\nIf the original brief didn\u2019t spell out what is expected of you at a presentation then make sure you ask beforehand. The critical element is how much time you have. It seems that panels are providing less and less time these days.\n\nThe usual formula is that you get an hour; half of which should be a presentation of your ideas followed by 30 minutes of questions. This isn\u2019t that much time, particularly for a big project that covers all aspect of web design and production. Don\u2019t be afraid to ask for more time, though it is very rare that you will be granted any.\n\nAsk if there any areas that a) they particularly want you to cover and b) if there are any areas of your proposal that were weak.\n\nAsk who will be attending. The main reason for this is to see if the decision maker(s) will be present but it\u2019s also good to know if you\u2019re presenting to 3 or 30 people.\n\nWho should be there\n\nGenerally speaking, I think two is the ideal number. Though I have done many presentations on my own, I always feel having two people to bounce ideas around with and have a bit of banter with, works well. You are not only trying to sell your ideas and expertise but also yourselves. One of the main things in the panels minds will be \u2013 \u201ccan I work with these people?\u201d\n\nHaving more than two people at a presentation often looks like you\u2019re wheeling people out just to demonstrate that they exist.\n\nWhat makes a client want to hire you?\n\nIn a nutshell: Confidence, Personality, Enthusiasm.\n\nYou can impart confidence by being well prepared and professional, providing examples and demonstrations and talking about your processes. You may find project management boring but pretty much every potential client will want to feel reassured that you manage your projects effectively.\n\nAs well as demonstrating that you know what you\u2019re talking about, it is important to encourage, and be part of, discussion about the project. Be prepared to suggest and challenge and be willing to say \u201cI don\u2019t know\u201d.\n\nAlso, no-one likes a show-off so don\u2019t over promote yourself; encourage them to contact your existing clients.\n\nWhat makes a client like you?\n\nEngaging with a potential client is tricky and it\u2019s probably the area where you need to be most on your toes and try to gauge the reaction of the client. We recommend the following:\n\n\n\tEncourage questions throughout\n\tAsk if you make sense \u2013 which encourages questions if you\u2019re not getting any\n\tHumour \u2013 though don\u2019t keep trying to be funny if you\u2019re not getting any laughs!\n\tBe willing to go off track\n\tRead your audience\n\tEmpathise with the process \u2013 chances are, most of the people in front of you would rather be doing something else\n\tThink about what you wear \u2013 this sounds daft but do you want to be seen as either the \u2018stiff in the suit\u2019 or the \u2018scruffy art student\u2019? Chances are neither character would get hired.\n\n\nDifferentiation\n\nSometimes, especially if you think you are an outsider, it\u2019s worth taking a few risks. I remember my colleague Paul starting off a presentation once with the line (backed up on screen) \u2013 \u201cHeadscape is not a usability consultancy\u201d. This was in response to the clients request to engage a usability consultancy. The thrust of Paul\u2019s argument was that we are a lot more than that.\n\nThis really worked. We were the outside choice but they ended up hiring us. Basically, this differentiated us from the crowd. It showed that we are prepared to take risks and think, dare I say it, outside of the box.\n\nDealing with difficult characters \n\nHow you react to tricky questioning is likely to be what determines whether you have a good or bad presentation. Here are a few of those characters that so often turn up in panels:\n\nThe techie \u2013 this is likely to be the situation where you need to say \u201cI don\u2019t know\u201d. Don\u2019t bluff as you are likely to dig yourself a great big embarrassment-filled hole. Promise to follow up with more information and make sure that you do so as quickly as possible after the pitch. \n\nThe \u2018hard man\u2019 MD \u2013 this the guy who thinks it is his duty to throw \u2018curve ball\u2019 questions to see how you react. Focus on your track record (big name clients will impress this guy) and emphasise your processes.\n\nThe \u2018no clue\u2019 client \u2013 you need to take control and be the expert though you do need to explain the reasoning behind any suggestions you make. This person will be judging you on how much you are prepared to help them deliver the project.\n\nThe price negotiator \u2013 be prepared to discuss price but do not reduce your rate or the effort associated with your proposal. Fall back on modular pricing and try to reduce scope to come within budget. You may wish to offer a one-off discount to win a new piece of work but don\u2019t get into detail at the pitch.\n\nDon\u2019t panic\u2026\n\nIf you go into a presentation thinking \u2018we must win this\u2019 then, chances are, you won\u2019t. Relax and be yourself. If you\u2019re not hitting it off with the panel then so be it. You have to remember that quite often you will be making up the numbers in a tendering process. This is massively frustrating but, unfortunately, part of it. If it\u2019s not going well, concentrate on what you are offering and try to demonstrate your professionalism rather than your personality. Finally, be on your toes, watch people\u2019s reactions and pay attention to what they say and try to react accordingly.\n\nSo where are the secret techniques I hear you ask? Well, using the words \u2018secret\u2019 and \u2018technique\u2019 was probably a bit naughty. Most of this stuff is about being keen, using your brain and believing in yourself and what you are selling rather than following a strict set of rules.", "year": "2008", "author": "Marcus Lillington", "author_slug": "marcuslillington", "published": "2008-12-09T00:00:00+00:00", "url": "https://24ways.org/2008/charm-clients-win-pitches/", "topic": "business"} {"rowid": 116, "title": "The IE6 Equation", "contents": "It is the destiny of one browser to serve as the nemesis of web developers everywhere. At the birth of the Web Standards movement, that role was played by Netscape Navigator 4; an outdated browser that refused to die. Its tenacious existence hampered the adoption of modern standards. Today that role is played by Internet Explorer 6.\n\nThere\u2019s a sensation that I\u2019m sure you\u2019re familiar with. It\u2019s a horrible mixture of dread and nervousness. It\u2019s the feeling you get when\u2014after working on a design for a while in a standards-compliant browser like Firefox, Safari or Opera\u2014you decide that you can no longer put off the inevitable moment when you must check the site in IE6. Fingers are crossed, prayers are muttered, but alas, to no avail. The nemesis browser invariably screws something up.\n\nWhat do you do next? If the differences in IE6 are minor, you could just leave it be. After all, websites don\u2019t need to look exactly the same in all browsers. But if there are major layout issues and a significant portion of your audience is still using IE6, you\u2019ll probably need to roll up your sleeves and start fixing the problems.\n\nA common approach is to quarantine IE6-specific CSS in a separate stylesheet. This stylesheet can then be referenced from the HTML document using conditional comments like this:\n\n\n\nThat stylesheet will only be served up to Internet Explorer where the version number is less than 7.\n\nYou can put anything inside a conditional comment. You could put a script element in there. So as well as serving up browser-specific CSS, it\u2019s possible to serve up browser-specific JavaScript.\n\nA few years back, before Microsoft released Internet Explorer 7, JavaScript genius Dean Edwards wrote a script called IE7. This amazing piece of code uses JavaScript to make Internet Explorer 5 and 6 behave like a standards-compliant browser. Dean used JavaScript to bootstrap IE\u2019s CSS support.\n\nBecause the script is specifically targeted at Internet Explorer, there\u2019s no point in serving it up to other browsers. Conditional comments to the rescue:\n\n\n\nStandards-compliant browsers won\u2019t fetch the script. Users of IE6, on the hand, will pay a kind of bad browser tax by having to download the JavaScript file.\n\nSo when should you develop an IE6-specific stylesheet and when should you just use Dean\u2019s JavaScript code? This is the question that myself and my co-worker Natalie Downe set out to answer one morning at Clearleft. We realised that in order to answer that question you need to first answer two other questions, how much time does it take to develop for IE6? and how much of your audience is using IE6?\n\nLet\u2019s say that t represents the total development time. Let t6 represent the portion of that time you spend developing for IE6. If your total audience is a, then a6 is the portion of your audience using IE6. With some algebraic help from our mathematically minded co-worker Cennydd Bowles, Natalie and I came up with the following equation to calculate the percentage likelihood that you should be using Dean\u2019s IE7 script:\n\n\n\np = 50 [ log ( at6 / ta6 ) + 1 ]\n\nTry plugging in your own numbers. If you spend a lot of time developing for IE6 and only a small portion of your audience is using that browser, you\u2019ll get a very high number out of the equation; you should probably use the IE7 script. But if you only spend a little time developing for IE6 and a significant portion of you audience are still using that browser, you\u2019ll get a very small value for p; you might as well write an IE6-specific stylesheet.\n\nOf course this equation is somewhat disingenuous. While it\u2019s entirely possible to research the percentage of your audience still using IE6, it\u2019s not so easy to figure out how much of your development time will be spent developing for that one browser. You can\u2019t really know until you\u2019ve already done the development, by which time the equation is irrelevant.\n\nInstead of using the equation, you could try imposing a limit on how long you will spend developing for IE6. Get your site working in standards-compliant browsers first, then give yourself a time limit to get it working in IE6. If you can\u2019t solve all the issues in that time limit, switch over to using Dean\u2019s script. You could even make the time limit directly proportional to the percentage of your audience using IE6. If 20% of your audience is still using IE6 and you\u2019ve just spent five days getting the site working in standards-compliant browsers, give yourself one day to get it working in IE6. But if 50% of your audience is still using IE6, be prepared to spend 2.5 days wrestling with your nemesis.\n\nAll of these different methods for dealing with IE6 demonstrate that there\u2019s no one single answer that works for everyone. They also highlight a problem with the current debate around dealing with IE6. There\u2019s no shortage of blog posts, articles and even entire websites discussing when to drop support for IE6. But very few of them take the time to define what they mean by \u201csupport.\u201d This isn\u2019t a binary issue. There is no Boolean answer. Instead, there\u2019s a sliding scale of support:\n\n\n\tBlock IE6 users from your site.\n\tDevelop with web standards and don\u2019t spend any development time testing in IE6.\n\tUse the Dean Edwards IE7 script to bootstrap CSS support in IE6.\n\tWrite an IE6 stylesheet to address layout issues.\n\tMake your site look exactly the same in IE6 as in any other browser.\n\n\nEach end of that scale is extreme. I don\u2019t think that anybody should be actively blocking any browser but neither do I think that users of an outdated browser should get exactly the same experience as users of a more modern browser. The real meanings of \u201csupporting\u201d or \u201cnot supporting\u201d IE6 lie somewhere in-between those extremes.\n\nJust as I think that semantics are important in markup, they are equally important in our discussion of web development. So let\u2019s try to come up with some better terms than using the catch-all verb \u201csupport.\u201d If you say in your client contract that you \u201csupport\u201d IE6, define exactly what that means. If you find yourself in a discussion about \u201cdropping support\u201d for IE6, take the time to explain what you think that entails.\n\nThe web developers at Yahoo! are on the right track with their concept of graded browser support. I\u2019m interested in hearing more ideas of how to frame this discussion. If we can all agree to use clear and precise language, we stand a better chance of defeating our nemesis.", "year": "2008", "author": "Jeremy Keith", "author_slug": "jeremykeith", "published": "2008-12-08T00:00:00+00:00", "url": "https://24ways.org/2008/the-ie6-equation/", "topic": "code"} {"rowid": 117, "title": "The First Tool You Reach For", "contents": "Microsoft recently announced that Internet Explorer 8 will be released in the first half of 2009. Compared to the standards support of other major browsers, IE8 will not be especially great, but it will finally catch up with the state of the art in one specific area: support for CSS tables. This milestone has the potential to trigger an important change in the way you approach web design.\n\nTo show you just how big a difference CSS tables can make, think about how you might code a fluid, three-column layout from scratch. Just to make your life more difficult, give it one fixed-width column, with a background colour that differs from the rest of the page. Ready? Go!\n\nOkay, since you\u2019re the sort of discerning web designer who reads 24ways, I\u2019m going to assume you at least considered doing this without using HTML tables for the layout. If you\u2019re especially hardcore, I imagine you began thinking of CSS floats, negative margins, and faux columns. If you did, colour me impressed!\n\nNow admit it: you probably also gave an inward sigh about the time it would take to figure out the math on the negative margin overlaps, check for dropped floats in Internet Explorer and generally wrestle each of the major browsers into giving you what you want. If after all that you simply gave up and used HTML tables, I can\u2019t say I blame you.\n\nThere are plenty of professional web designers out there who still choose to use HTML tables as their main layout tool. Sure, they may know that users with screen readers get confused by inappropriate use of tables, but they have a job to do, and they want tools that will make that job easy, not difficult.\n\nNow let me show you how to do it with CSS tables. First, we have a div element for each of our columns, and we wrap them all in another two divs:\n\n
\n\t
\n\t\t
\n\t\t\u22ee\n\t\t
\n\t\t
\n\t\t\u22ee\n\t\t
\n\t\t
\n\t\t\u22ee\n\t\t
\n\t
\n
\n\nDon\u2019t sweat the \u201cdiv clutter\u201d in this code. Unlike tables, divs have no semantic meaning, and can therefore be used liberally (within reason) to provide hooks for the styles you want to apply to your page.\n\nUsing CSS, we can set the outer div to display as a table with collapsed borders (i.e. adjacent cells share a border) and a fixed layout (i.e. cell widths unaffected by their contents):\n\n.container {\n\tdisplay: table;\n\tborder-collapse: collapse;\n\ttable-layout: fixed;\n}\n\nWith another two rules, we set the middle div to display as a table row, and each of the inner divs to display as table cells:\n\n.container > div {\n\tdisplay: table-row;\n}\n.container > div > div {\n\tdisplay: table-cell;\n}\n\nFinally, we can set the widths of the cells (and of the table itself) directly:\n\n.container {\n\twidth: 100%;\n}\n#menu {\n\twidth: 200px;\n}\n#content {\n\twidth: auto;\n}\n#sidebar {\n\twidth: 25%;\n}\n\nAnd, just like that, we have a rock solid three-column layout, ready to be styled to your own taste, like in this example:\n\n\n\nThis example will render perfectly in reasonably up-to-date versions of Firefox, Safari and Opera, as well as the current beta release of Internet Explorer 8.\n\nCSS tables aren\u2019t only useful for multi-column page layout; they can come in handy in most any situation that calls for elements to be displayed side-by-side on the page. Consider this simple login form layout:\n\n\n\nThe incantation required to achieve this layout using CSS floats may be old hat to you by now, but try to teach it to a beginner, and watch his eyes widen in horror at the hoops you have to jump through (not to mention the assumptions you have to build into your design about the length of the form labels).\n\nHere\u2019s how to do it with CSS tables:\n\n
\n\t
\n\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
\n\t\t
\n\t\t\t\n\t\t\t\n\t\t
\n\t
\n
\n\nThis time, we\u2019re using a mixture of divs and spans as semantically transparent styling hooks. Let\u2019s look at the CSS code.\n\nFirst, we set up the outer div to display as a table, the inner divs to display as table rows, and the labels and spans as table cells (with right-aligned text):\n\nform > div {\n\tdisplay: table;\n}\nform > div > div {\n\tdisplay: table-row;\n}\nform label,\nform span {\n\tdisplay: table-cell;\n\ttext-align: right;\n}\n\nWe want the first column of the table to be wide enough to accommodate our labels, but no wider. With CSS float techniques, we had to guess at what that width was likely to be, and adjust it whenever we changed our form labels. With CSS tables, we can simply set the width of the first column to something very small (1em), and then use the white-space property to force the column to the required width:\n\nform label {\n\twhite-space: nowrap;\n\twidth: 1em;\n}\n\nTo polish off the layout, we\u2019ll make our text and password fields occupy the full width of the table cells that contain them:\n\ninput[type=text],\ninput[type=password] {\n\twidth: 100%;\n}\n\nThe rest is margins, padding and borders to get the desired look. Check out the finished example.\n\nAs the first tool you reach for when approaching any layout task, CSS tables make a lot more sense to your average designer than the cryptic incantations called for by CSS floats. When IE8 is released and all major browsers support CSS tables, we can begin to gradually deploy CSS table-based layouts on sites that are more and more mainstream.\n\nIn our new book, Everything You Know About CSS Is Wrong!, Rachel Andrew and I explore in much greater detail how CSS tables work as a page layout tool in the real world. CSS tables have their quirks just like floats do, but they don\u2019t tend to affect common layout tasks, and the workarounds tend to be less fiddly too. Check it out, and get ready for the next big step forward in web design with CSS.", "year": "2008", "author": "Kevin Yank", "author_slug": "kevinyank", "published": "2008-12-13T00:00:00+00:00", "url": "https://24ways.org/2008/the-first-tool-you-reach-for/", "topic": "code"} {"rowid": 118, "title": "Ghosts On The Internet", "contents": "By rights the internet should be full of poltergeists, poor rootless things looking for their real homes. Many events on the internet are not properly associated with their correct timeframe. I don\u2019t mean a server set to the wrong time, though that happens too. Much of the content published on the internet is separated from any proper reference to its publication time. What does publication even mean? Let me tell you a story\u2026\n\n\n\t\u201cIt is 2019 and this is Kathy Clees reporting on the story of the moment, the shock purchase of Microsoft by Apple Inc. A Internet Explorer security scare story from 2008 was responsible, yes from 11 years ago, accidently promoted by an analyst, who neglected to check the date of their sources.\u201d\n\n\nIf you think this is fanciful nonsense, then cast your mind back to September 2008, this story in Wired or The Times (UK) about a huge United Airlines stock tumble. A Florida newspaper had a automated popular story section. A random reader looking at a story about United\u2019s 2002 Bankruptcy proceedings caused this story to get picked up by Google\u2019s later visit to the South Florida Sun Sentinel\u2019s news home page. \n\nThe story was undated, Google\u2019s news engine apparently gave it a 2008 date, an analyst picked it up and pushed it to Bloomberg and within minutes the United stock was tumbling. Their stock price dropped from $12 to $3, then recovered to $11 over the day. An eight percent fall in share price over a mis-configured date\n\nCompleting this out of order Christmas Carol, lets look at what is current practice and how dates are managed, we might even get to clank some chains. Publication date used to be inseparable from publication, the two things where stamped on the same piece of paper. How can we determine when things have been published, now?\n\nDetermining publication dates\n\nTime as defined by http://www.w3.org/TR/NOTE-datetime extends ISO 8601, mandating the use of a year value. This is pretty well defined, we can even get very accurate timings down to milliseconds, Ruby and other languages can even handle Calendar reformation. So accuracy is not the issue.\n\nOne problem is that there are many dates which could be interpreted as the publication date. Publication can mean any of date written or created; date placed on server; last modified date; or the current date from the web server. Created and modified have parallels with file systems, but the large number of database driven websites means that this no longer holds much meaning, as there are no longer any files. \n\nChecking web server HEAD may also not correspond, it might give the creation time for the HTML file you are viewing or it might give the last modified time for a file from disk. It is too unreliable and lacking in context to be of real value. So if the web server will not help, then how can we get the right timeframe for our content? \n\nWe are left with URLs and the actual page content.\n\n\n\nLooking at Flickr, this picture (by Douglas County History Research Center) has four date values which can be associated with it. It was taken around 1900, scanned in 1992 and placed on Flickr on July 29th, 2008 and replaced later that day. Which dates should be represented here? \n\nThis is hard question to answer, but currently the date of upload to Flickr is the best represented in terms of the date URL, /photos/douglascountyhistory/archives/date-posted/2008/07/29/, plus some Dublin Core RDF for the year. Flickr uses 2008 as the value for this image. Not accurate, but a reasonable compromise for the millions of other images on their site.\n\nFlickr represents location much better than it represents time. For the most part this is fine, but once you go back in time to the 1800s then the maps of the world start to change a lot and you need to reference both time and place.\n\nThe Google timeline search offers another interesting window on the world, showing results organised by decade for any search term. Being able to jump to a specific occurrence of a term makes it easier to get primary results rather than later reporting. \n\nThe 1918 \u201cSpanish flu\u201d results jump out in this timeline. \n\n\n\nAny major news event will have multiple analysis articles after the event, finding the original reporting of hurricane Katrina is harder now. Many publishers are putting older content online, e.g. Harpers or Nature or The Times, often these use good date based URLs, sometimes they are unhelpful database references. If this content is available for free, then how much better would it be to provide good metadata on date of publication.\n\nDate based URLs\n\nA quick word on date based URLs, they can be brilliant at capturing first published date. However they can be hard to interpret. Is /03/04 a date in March or April, what about 08/03/04? Obviously 2008/03/04 is easier to understand, it is probably March 4th. Including a proper timestamp in the page content avoid this kind of guesswork. \n\nMany sites represent the date as a plain text string; a few hook an HTML class of date around it, a very few provide an actual timestamp. Associating the date with the individual content makes it harder to get the date wrong.\n\nMovable Type and TypePad are a notable exceptions, they will embed Dublin Core RDF to represent each posting e.g. dc:date=\"2008-12-18T02:57:28-08:00\". WordPress doesn\u2019t support date markup out of the box, though there is a patch and a howto for hAtom available.\n\nIn terms of newspapers, the BBC use along with opaque URLs such as http://news.bbc.co.uk/1/hi/technology/7787335.stm. \n\nThe Guardian use nice clear URLs http://www.guardian.co.uk/business/2008/dec/18/car-industry-recession but have no marked up date on the page. \n\nThe New York Times are similar to the Guardian with nice URLs, http://www.nytimes.com/2008/12/19/business/19markets.html, but again no timestamps. All of these papers have all the data available, but it is not marked up in a useful manner.\n\nSyndication formats\n\nSyndication formats are better at supporting dates, RSS uses RFC 822 for dates, just like email so dates such as Wed, 17 Dec 2008 12:52:40 GMT are valid, with all the white space issues that entails. \n\nThe Atom syndication format uses the much clearer http://tools.ietf.org/html/rfc3339 with timestamps of the form 1996-12-19T16:39:57-08:00. Both syndication formats encourage the use of last modified. This is understandable, but a pity as published date is a very useful value. The Atom syndication format supports \u201cpublished\u201d and mandates \u201cupdated\u201d as timestamps, see the Atom RFC 4287 for more detail.\n\nMarking up dates\n\nHowever the aim of this short article is to encourage you to use microformats or RDF to encode dates. A good example of this is Twitter, they use hAtom for each individual entry, http://twitter.com/zzgavin/status/1065835819 contains the following markup, which represents a human and a machine readable version of the time of that tweet.\n\nabout 3 hours ago \n\nThe spec for datetime is still draft at the minute and there is still ongoing conversation around the right format and semantics for representing date and time in microformats, see the datetime design pattern for details. \n\nThe hAtom example page shows the minimal changes required to implement hAtom on well formed blog post content and for other less well behaved content. You have the information already in your content publication systems, this is not some additional onerous content entry task, simply some template formatting.\n\nI started to see this as a serious issue after reading Stewart Brand\u2019s Clock of the Long Now about five years ago. Brand\u2019s book explores the issues of short term thinking that permeate our society, thinking beyond the end of the financial year is a stretch for many people. The Long Now has a world view of a 10,000 year timeframe, see http://longnow.org/ for much more information. Freebase from Long Now Board member Danny Hillis, supports dates quite well \u2013 see the entry for A Christmas Carol.\n\nIn conclusion\n\nI feel we should be making it easier for people searching for our content in the future. We\u2019ve moved through tagging content and on to geo-tagging content. Now it is time to get the timestamps right on our content. How do I know when something happened and how can I find other things that happened at the same time is a fair question. This should be something I can satisfy simply and easily. There are a range of tools available to us in either hAtom or RDF to specify time accurately alongside the content, so what is stopping you?\n\nThinking of the long term it is hard for us to know now what will be of relevance for future generations, so we should aim to raise the floor for publishing tools so that all content has the right timeframe associated with it. We are moving from publishing words and pictures on the internet to being able to associate publication with an individual via XFN and OpenID. We can associate place quite well too, the last piece of useful metadata is timeframe.", "year": "2008", "author": "Gavin Bell", "author_slug": "gavinbell", "published": "2008-12-20T00:00:00+00:00", "url": "https://24ways.org/2008/ghosts-on-the-internet/", "topic": "ux"} {"rowid": 119, "title": "Rocking Restrictions", "contents": "I love my job. I live my job. For every project I do, I try to make it look special. I\u2019ll be honest: I have a fetish for comments like \u201cI never saw anything like that!\u201d or, \u201cI wish I thought of that!\u201d. I know, I have an ego-problem. (Eleven I\u2019s already)\n\nBut sometimes, you run out of inspiration. Happens to everybody, and everybody hates it. \u201cI\u2019m the worst designer in the world.\u201d \u201cEverything I designed before this was just pure luck!\u201d No it wasn\u2019t.\n\nCountless articles about finding inspiration have already been written. Great, but they\u2019re not the magic potion you\u2019d expect them to be when you need it. Here\u2019s a list of small tips that can have immediate effect when applying them/using them. Main theme: Liberate yourself from the designers\u2019 block by restricting yourself.\n\nDo\u2019s\n\nGrids\n\nIf you aren\u2019t already using grids, you\u2019re doing something wrong. Not only are they a great help for aligning your design, they also restrict you to certain widths and heights. (For more information about grids, I suggest you read Mark Boulton\u2019s series on designing grid systems. Oh, he\u2019s also publishing a book I think.)\n\nSo what\u2019s the link between grids and restrictions? Instead of having the option to style a piece of layout with a width of 1 to 960 pixels, you have to choose from values like 60 pixels, 140, 220, 300, \u2026\n\nStart small\n\nHaving a hard time finding a style for the layout, why don\u2019t you start with one small object? No, not that small object, I meant a piece of a form, or a link, or try styling your headers (h1 \u2013 h6).\n\nLet\u2019s take a submit button of a form: it\u2019s small, but needs much attention. People will click it. People will hover it. Maybe sometimes it\u2019s disabled? Also: a button needs to look like a button, so typically it requires more styling then a regular link. Once you\u2019ve got the button, move on, following the button\u2019s style.\n\nColor palettes\n\nThere are lots of resources on the web for finding inspiration for color palettes. Some of the most famous are COLOURlovers, wear palettes and Adobe\u2019s Kuler. Browse through them (or create your own from a picture), pick a color palette you like and which works with the subject you\u2019re handling, and stick with it. 4-5 colors, maybe with some tonal variations, but that\u2019s it.\n\nFonts\n\nThere aren\u2019t many fonts available for the web (Richard Rutter has a great article on this subject), but you\u2019d be surprised how long they go. A simple text-transform: uppercase; or font-style: italic; can change a dull looking font into something entirely fresh.\n\nPlay around with the fonts you want to use and the variations you\u2019ll be using, and make a list. Pick five combinations of fonts and their variations, and stick with them throughout the layout.\n\nSingle-task\n\nMost of us use multiple monitors. They\u2019re great to increase productivity, but make it harder to focus on a single task. Here\u2019s what you do: try using only your smallest monitor. Maybe it\u2019s the one from your laptop, maybe it\u2019s an old 1024\u00d7768 you found in the attic. Having Photoshop (or Fireworks or\u2026) taking over your entire workspace blocks out all the other distractions on your screen, and works quite liberating.\n\nMute everything\u2026\n\n\u2026but not entirely. I noticed I was way more focused when I set NetNewsWire to refresh it\u2019s feeds only once every two hours. After two hours, I need a break anyway. Turning off Twitterrific was a mistake, as it\u2019s my window to the world, and it\u2019s the place where the people I like to call colleagues live. You can\u2019t exactly ask them to bring you a cup of coffee when they go to the vending machine, but they do keep you fresh, and it stops you from going human-shy. Instead I changed the settings to not play a notification sound when new Tweets arrive so it doesn\u2019t disturb me when I\u2019m zoning.\n\nDon\u2019ts\n\nCSS galleries\n\nDon\u2019t start browsing all kinds of CSS galleries. Either you\u2019ll feel bad, or you just start using elements in a way you can\u2019t call \u201cinspired\u201d anymore. Instead gather your own collection of inspiration. Example: I use LittleSnapper in which I dump everything I find inspiring. This goes from a smart layout idea, to a failed picture someone posted on Flickr. Everything is inspiring.\n\nPanicking\n\nDon\u2019t panic. It\u2019s the worst thing you could do. Instead, get away from the computer, and go to bed early. A good night of sleep combined with a hot/cold shower can give you a totally new perspective on a design. Got a deadline by tomorrow? Well, you should\u2019ve started earlier. Got a good excuse to start on this design this late? Tell your client it was either that or a bad design.\n\n120-hour work-week\n\nDon\u2019t work all day long, including evenings and early mornings. Write off that first hour, you don\u2019t really think you\u2019ll get anything productive done before 9AM?! I don\u2019t even think you should work on one and the same design all day long. If you\u2019re stuck, try working in blocks of 1 or 2 hours on a certain design. Mixing projects isn\u2019t for everyone, but it might just do the trick for you.\n\nSummary\n\n\n\tUse grids, not only for layout purposes.\n\tPick a specific element to start with.\n\tUse a colour palette.\n\tLimit the amount of fonts and variations you\u2019ll use.\n\tSearch for the smallest monitor around, and restrict yourself to that one.\n\tReduce the amount of noise.\n\tDon\u2019t start looking on the internet for inspiration. Build your own little inspirarchive.\n\tWork in blocks.", "year": "2008", "author": "Tim Van Damme", "author_slug": "timvandamme", "published": "2008-12-14T00:00:00+00:00", "url": "https://24ways.org/2008/rocking-restrictions/", "topic": "process"} {"rowid": 120, "title": "Easier Page States for Wireframes", "contents": "When designing wireframes for web sites and web apps, it is often overlooked that the same \u2018page\u2019 can look wildly different depending on its context. A logged-in page will look different from a logged-out page; an administrator\u2019s view may have different buttons than a regular user\u2019s view; a power user\u2019s profile will be more extensive than a new user\u2019s.\n\nThese different page states need designing at some point, especially if the wireframes are to form a useful communication medium between designer and developer. Documenting the different permutations can be a time consuming exercise involving either multiple pages in one\u2019s preferred box-and-arrow software, or a fully fledged drawing containing all the possible combinations annotated accordingly.\n\nEnter interactive wireframes and Polypage\n\nInteractive wireframes built in HTML are a great design and communication tool. They provide a clickable prototype, running in the browser as would the final site. As such they give a great feel for how the site will be to use. Once you add in the possibilities of JavaScript and a library such as jQuery, they become even more flexible and powerful.\n\nPolypage is a jQuery plugin which makes it really easy to design multiple page states in HTML wireframes. There\u2019s no JavaScript knowledge required (other than cutting and pasting in a few lines). The page views are created by simply writing all the alternatives into your HTML page and adding special class names to apply state and conditional view logic to the various options. \n\nWhen the page is loaded Polypage automatically detects the page states defined by the class names and creates a control bar enabling the user to toggle page states with the click of a mouse or the clack of a keyboard.\n\n\n\nUsing cookies by way of the jQuery cookie plugin, Polypage retains the view state throughout your prototype. This means you could navigate through your wireframes as if you were logged out; as if you were logged in as an administrator; with notes on or off; or with any other view or state you might require. The possibilities are entirely up to you.\n\nHow does it work?\n\nFirstly you need to link to jQuery, the jQuery cookie plugin and to Polypage. Something like this:\n\n\n\n\n\nThen you need to initialise Polypage on page load using something along these lines:\n\n\n\nNext you need to define the areas of your wireframe which are particular to a given state or view. Do this by applying classes beginning with pp_. Polypage will ignore all other classes in the document.\n\nThe pp_ prefix should be followed by a state name. This can be any text string you like, bearing in mind it will appear in the control bar. Typical page states might include \u2018logged_in\u2019, \u2018administrator\u2019 or \u2018group_owner\u2019. A complete class name would therefore look something like pp_logged_in.\n\nExamples\n\nIf a user is logged in, you might want to specify an option for him or her to sign out. Using Polypage, this could be put in the wireframe as follows:\n\n
Sign out \n\nPolypage will identify the pp_logged_in class on the link and hide it (as the \u2018Sign out\u2019 link should only be shown when the page is in the \u2018logged in\u2019 view). Polypage will then automatically write a \u2018logged in\u2019 toggle to the control bar, enabling you to show or hide the \u2018Sign out\u2019 link by toggling the \u2018logged in\u2019 view. The same will apply to all content marked with a pp_logged_in class.\n\nStates can also be negated by adding a not keyword to the class name. For example you might want to provide a log in link for users who are not signed in. Using Polypage, you would insert the not keyword after the pp prefix as follows:\n\n Login \n\nAgain Polypage identifies the pp prefix but this time sees that the \u2018Login\u2019 link should not be shown when the \u2018logged in\u2019 state is selected.\n\nStates can also be joined together to add some basic logic to pages. The syntax follows natural language and uses the or and and keywords in addition to the afore-mentioned not. Some examples would be pp_logged_in_and_admin, pp_admin_or_group_owner and pp_logged_in_and_not_admin.\n\nFinally, you can set default states for a page by passing an array to the polypage.init() function like this:\n\n$.polypage.init(['logged_in', 'admin']);\n\nYou can see a fully fledged example in this fictional social network group page. The example page defaults to a logged in state. You can see the logged out state by toggling \u2018logged in\u2019 off in the Polypage control bar. There are also views specified for a group member, a group admin, a new group and notes. \n\nWhere can I get hold of it?\n\nYou can download the current version from GitHub.\n\nPolypage was originally developed by Clearleft and New Bamboo, with particular contributions from Andy Kent and Natalie Downe. It has been used in numerous real projects, but it is still an early release so there is bound to be room for improvement. We\u2019re pleased to say that Polypage is now an open source project so any feedback, particularly by way of actual improvements, is extremely welcome.", "year": "2008", "author": "Richard Rutter", "author_slug": "richardrutter", "published": "2008-12-11T00:00:00+00:00", "url": "https://24ways.org/2008/easier-page-states-for-wireframes/", "topic": "process"} {"rowid": 121, "title": "Hide And Seek in The Head", "contents": "If you want your JavaScript-enhanced pages to remain accessible and understandable to scripted and noscript users alike, you have to think before you code. Which functionalities are required (ie. should work without JavaScript)? Which ones are merely nice-to-have (ie. can be scripted)? You should only start creating the site when you\u2019ve taken these decisions.\n\nSpecial HTML elements\n\nOnce you have a clear idea of what will work with and without JavaScript, you\u2019ll likely find that you need a few HTML elements for the noscript version only.\n\nTake this example: A form has a nifty bit of Ajax that automatically and silently sends a request once the user enters something in a form field. However, in order to preserve accessibility, the user should also be able to submit the form normally. So the form should have a submit button in noscript browsers, but not when the browser supports sufficient JavaScript.\n\nSince the button is meant for noscript browsers, it must be hard-coded in the HTML:\n\n\n\nWhen JavaScript is supported, it should be removed:\n\nvar checkJS = [check JavaScript support];\nwindow.onload = function () {\n\tif (!checkJS) return;\n\tdocument.getElementById('noScriptButton').style.display = 'none';\n}\n\nProblem: the load event\n\nAlthough this will likely work fine in your testing environment, it\u2019s not completely correct. What if a user with a modern, JavaScript-capable browser visits your page, but has to wait for a huge graphic to load? The load event fires only after all assets, including images, have been loaded. So this user will first see a submit button, but then all of a sudden it\u2019s removed. That\u2019s potentially confusing.\n\nFortunately there\u2019s a simple solution: play a bit of hide and seek in the :\n\nvar checkJS = [check JavaScript support];\nif (checkJS) {\n\tdocument.write('');\n}\n\nFirst, check if the browser supports enough JavaScript. If it does, document.write an extra \n\nSo we end up with a nice simple to understand but also quick to write XSL which can be used on ATOM Flickr feeds and ATOM News feeds. With a little playing around with XSL, you can make XML beautiful again.\n\nAll the files can be found in the zip file (14k)", "year": "2006", "author": "Ian Forrester", "author_slug": "ianforrester", "published": "2006-12-07T00:00:00+00:00", "url": "https://24ways.org/2006/beautiful-xml-with-xsl/", "topic": "code"} {"rowid": 137, "title": "Cheating Color", "contents": "Have you ever been strapped to use specific colors outlined in a branding guide? Felt restricted because those colors ended up being too light or dark for the way you want to use them?\n\nHere\u2019s the solution: throw out your brand guide.\n\ngasp!\n\nOK, don\u2019t throw it out. Just put it in a drawer for a few minutes.\n\nBranding Guides be Damned\n\nWhen dealing with color on screen, it\u2019s easy to get caught up in literal values from hex colors, you can cheat colors ever so slightly to achieve the right optical value. This is especially prevalent when trying to bring a company\u2019s identity colors to a screen design. Because the most important idea behind a brand guide is to help a company maintain the visual integrity of their business, consider hex numbers to be guidelines rather than law. Once you are familiar enough with the colors your company uses, you can start to flex them a bit, and take a few liberties.\n\nThis is a quick method for cheating to get the color you really want. With a little sleight of design, we can swap a color that might be part of your identity guidelines, with one that works better optically, and no one will be the wiser!\n\nColor is a Wily Beast\n\nThis might be hard: You might have to break out of the idea that a color can only be made using one method. Color is fluid. It interacts and changes based on its surroundings. Some colors can appear lighter or darker based on what color they appear on or next to. The RGB gamut is additive color, and as such, has a tendency to push contrast in the direction that objects may already be leaning\u2014increasing the contrast of light colors on dark colors and decreasing the contrast of light on light. Obviously, because we are talking about monitors here, these aren\u2019t hard and fast rules.\n\nCheat and Feel Good About It\n\nOn a light background, when you have a large element of a light color, a small element of the same color will appear lighter.\n\nEnter our fake company: Double Dagger. They manufacture footnotes. Take a look at Fig. 1 below. The logo (Double Dagger), rule, and small text are all #6699CC. Because the logo so large, we get a good sense of the light blue color. Unfortunately, the rule and small text beneath it feel much lighter because we can\u2019t create enough contrast with such small shapes in that color.\n\nNow take a look at Fig. 2. Our logo is still #6699CC, but now the rule and smaller text have been cheated to #4477BB, effectively giving us the same optical color that we used in the logo. You will find that we get a better sense of the light blue, and the added benefit of more contrast for our text. Doesn\u2019t that feel good?\n\n\n\nConversely, when you have a large element of a dark color, a small element of the same color will appear darker.\n\nLet\u2019s look at Fig. 3 below. Double Dagger has decided to change its identity colors from blue to red. In Fig. 3, our logo, rule, and small text are all #330000, a very dark red. If you look at the rule and small text below the logo, you will notice that they seem dark enough to be confused with black. The dark red can\u2019t be sustained by the smaller shapes. Now let\u2019s look at Fig. 4. The logo is still #33000, but we\u2019ve now cheated the rule and smaller text to #550000. This gives us a better sense of a red, but preserves the dark and moody direction the company has taken.\n\n\n\nBut we\u2019ve only touched on color against a white background. For colors against a darker background, you may find lighter colors work fine, but darker colors need to be cheated a bit to the lighter side in order to reach a good optical equivalent. Take a look below at Fig. 5 and Fig. 6. Both use the same exact corresponding colors as Fig. 1 and Fig. 2 above, but now they are set against a dark background. Where the blue used in Fig. 1 above was too light for the smaller elements, we find it is just right for them in Fig. 5, and the darker blue we used in Fig. 2 has now proven too dark for a dark background, as evidenced in Fig. 6.\n\n\n\nYour mileage may vary, and this may not be applicable in all situations, but consider it to be just another tool on your utility belt for dealing with color problems.", "year": "2006", "author": "Jason Santa Maria", "author_slug": "jasonsantamaria", "published": "2006-12-23T00:00:00+00:00", "url": "https://24ways.org/2006/cheating-color/", "topic": "design"} {"rowid": 138, "title": "Rounded Corner Boxes the CSS3 Way", "contents": "If you\u2019ve been doing CSS for a while you\u2019ll know that there are approximately 3,762 ways to create a rounded corner box. The simplest techniques rely on the addition of extra mark-up directly to your page, while the more complicated ones add the mark-up though DOM manipulation. While these techniques are all very interesting, they do seem somewhat of a kludge. The goal of CSS is to separate structure from presentation, yet here we are adding superfluous mark-up to our code in order to create a visual effect. The reason we are doing this is simple. CSS2.1 only allows a single background image per element.\n\nThankfully this looks set to change with the addition of multiple background images into the CSS3 specification. With CSS3 you\u2019ll be able to add not one, not four, but eight background images to a single element. This means you\u2019ll be able to create all kinds of interesting effects without the need of those additional elements.\n\nWhile the CSS working group still seem to be arguing over the exact syntax, Dave Hyatt went ahead and implemented the currently suggested mechanism into Safari. The technique is fiendishly simple, and I think we\u2019ll all be a lot better off once the W3C stop arguing over the details and allow browser vendors to get on and provide the tools we need to build better websites.\n\nTo create a CSS3 rounded corner box, simply start with your box element and apply your 4 corner images, separated by commas.\n\n.box {\n\tbackground-image: url(top-left.gif), url(top-right.gif), url(bottom-left.gif), url(bottom-right.gif);\n}\n\nWe don\u2019t want these background images to repeat, which is the normal behaviour, so lets set all their background-repeat properties to no-repeat.\n\n.box {\n\tbackground-image: url(top-left.gif), url(top-right.gif), url(bottom-left.gif), url(bottom-right.gif);\n\tbackground-repeat: no-repeat, no-repeat, no-repeat, no-repeat;\n}\n\nLastly, we need to define the positioning of each corner image.\n\n.box {\n\tbackground-image: url(top-left.gif), url(top-right.gif), url(bottom-left.gif), url(bottom-right.gif);\n\tbackground-repeat: no-repeat, no-repeat, no-repeat, no-repeat;\n\tbackground-position: top left, top right, bottom left, bottom right;\n}\n\nAnd there we have it, a simple rounded corner box with no additional mark-up.\n\nAs well as using multiple background images, CSS3 also has the ability to create rounded corners without the need of any images at all. You can do this by setting the border-radius property to your desired value as seen in the next example.\n\n.box {\n\tborder-radius: 1.6em;\n}\n\nThis technique currently works in Firefox/Camino and creates a nice, if somewhat jagged rounded corner. If you want to create a box that works in both Mozilla and WebKit based browsers, why not combine both techniques and see what happens.", "year": "2006", "author": "Andy Budd", "author_slug": "andybudd", "published": "2006-12-04T00:00:00+00:00", "url": "https://24ways.org/2006/rounded-corner-boxes-the-css3-way/", "topic": "code"} {"rowid": 139, "title": "Flickr Photos On Demand with getFlickr", "contents": "In case you don\u2019t know it yet, Flickr is great. It is a lot of fun to upload, tag and caption photos and it is really handy to get a vast network of contacts through it. \n\nUsing Flickr photos outside of it is a bit of a problem though. There is a Flickr API, and you can get almost every page as an RSS feed, but in general it is a bit tricky to use Flickr photos inside your blog posts or web sites. You might not want to get into the whole API game or use a server side proxy script as you cannot retrieve RSS with Ajax because of the cross-domain security settings.\n\nHowever, Flickr also provides an undocumented JSON output, that can be used to hack your own solutions in JavaScript without having to use a server side script.\n\n\n\tIf you enter the URL http://flickr.com/photos/tags/panda you get to the flickr page with photos tagged \u201cpanda\u201d.\n\tIf you enter the URL http://api.flickr.com/services/feeds/photos_public.gne?tags=panda&format=rss_200 you get the same page as an RSS feed.\n\tIf you enter the URL http://api.flickr.com/services/feeds/photos_public.gne?tags=panda&format=json you get a JavaScript function called jsonFlickrFeed with a parameter that contains the same data in JSON format\n\n\nYou can use this to easily hack together your own output by just providing a function with the same name. I wanted to make it easier for you, which is why I created the helper getFlickr for you to download and use.\n\ngetFlickr for Non-Scripters\n\nSimply include the javascript file getflickr.js and the style getflickr.css in the head of your document:\n\n\n\n\nOnce this is done you can add links to Flickr pages anywhere in your document, and when you give them the CSS class getflickrphotos they get turned into gallery links. When a visitor clicks these links they turn into loading messages and show a \u201cpopup\u201d gallery with the connected photos once they were loaded. As the JSON returned is very small it won\u2019t take long. You can close the gallery, or click any of the thumbnails to view a photo. Clicking the photo makes it disappear and go back to the thumbnails.\n\nCheck out the example page and click the different gallery links to see the results.\n\nNotice that getFlickr works with Unobtrusive JavaScript as when scripting is disabled the links still get to the photos on Flickr.\n\ngetFlickr for JavaScript Hackers\n\nIf you want to use getFlickr with your own JavaScripts you can use its main method leech():\n\ngetFlickr.leech(sTag, sCallback);\n\n \n\tsTag\n\tthe tag you are looking for\n\tsCallback\n\tan optional function to call when the data was retrieved.\n \n\nAfter you called the leech() method you have two strings to use:\n\n \n\tgetFlickr.html[sTag]\n\tcontains an HTML list (without the outer UL element) of all the images linked to the correct pages at flickr. The images are the medium size, you can easily change that by replacing _m.jpg with _s.jpg for thumbnails.\n\tgetFlickr.tags[sTag]\n\tcontains a string of all the other tags flickr users added with the tag you searched for(space separated)\n \n\nYou can call getFlickr.leech() several times when the page has loaded to cache several result feeds before the page gets loaded. This\u2019ll make the photos quicker for the end user to show up. If you want to offer a form for people to search for flickr photos and display them immediately you can use the following HTML:\n\n
\n \n \n \n

Tags:

\n

Photos:

    \n
    \n\nAll the JavaScript you\u2019ll need (for a basic display) is this:\n\nfunction populate(){\n var tag = document.getElementById('tag').value;\n document.getElementById('photos').innerHTML = getFlickr.html[tag].replace(/_m\\.jpg/g,'_s.jpg');\n document.getElementById('tags').innerHTML = getFlickr.tags[tag];\n return false;\n}\n\nEasy as pie, enjoy!\n\nCheck out the example page and try the form to see the results.", "year": "2006", "author": "Christian Heilmann", "author_slug": "chrisheilmann", "published": "2006-12-03T00:00:00+00:00", "url": "https://24ways.org/2006/flickr-photos-on-demand/", "topic": "code"} {"rowid": 140, "title": "Styling hCards with CSS", "contents": "There are plenty of places online where you can learn about using the hCard microformat to mark up contact details at your site (there are some resources at the end of the article). But there\u2019s not yet been a lot of focus on using microformats with CSS. So in this installment of 24 ways, we\u2019re going to look at just that \u2013 how microformats help make CSS based styling simpler and more logical.\n\nBeing rich, quite complex structures, hCards provide designers with a sophisticated scaffolding for styling them. A recent example of styling hCards I saw, playing on the business card metaphor, was by Andy Hume, at http://thedredge.org/2005/06/using-hcards-in-your-blog/. While his approach uses fixed width cards, let\u2019s take a look at how we might style a variable width business card style for our hCards.\n\nLet\u2019s take a common hCard, which includes address, telephone and email details\n\n
    \n\t

    Web Directions North\n\t\t\n\t\t\t\"download\n\t

    \n\n\t\n\t\t 1485 Laperri\u00e8re Avenue \n\t\t Ottawa ON K1Z 7S8 \n\t\tCanada\n\t\n\n\t\n\t\tPhone/Fax: Work: 61 2 9365 5007\n\t\tEmail: info@webdirections.org\n\t\n\n\nWe\u2019ll be using a variation on the now well established \u201csliding doors\u201d technique (if you create a CSS technique, remember it\u2019s very important to give it a memorable name or acronym, and bonus points if you get your name in there!) by Douglas Bowman, enhanced by Scott Schiller (see http://www.schillmania.com/projects/dialog/,) which will give us a design which looks like this\n\n\n\nThe technique, in a nutshell, uses background images on four elements, two at the top, and two at the bottom, to add each rounded corner.\n\nWe are going to make this design \u201cfluid\u201d in the sense that it grows and shrinks in proportion with the size of the font that the text of the element is displayed with. This is sometimes referred to as an \u201cem driven design\u201d (we\u2019ll see why in a moment).\n\nTo see how this works in practice, here\u2019s the same design with the text \u201czoomed\u201d up in size\n\n\n\nand the same design again, when we zoom the text size down\n\n\n\nBy the way, the hCard image comes from Chris Messina, and you can download it and other microformat icons from the microformats wiki.\n\nNow, with CSS3, this whole task would be considerably easier, because we can add multiple background images to an element, and border images for each edge of an element. Safari, version 1.3 up, actually supports multiple background images, but sadly, it\u2019s not supported in Firefox 1.5, or even Firefox 2.0 (let\u2019s not mention IE7 eh?). So it\u2019s probably too little supported to use now. So instead we\u2019ll use a technique that only involves CSS2, and works in pretty much any browser.\n\nVery often, developers add div or span elements as containers for these background images, and in fact, if you visit Scott Shiller\u2019s site, that\u2019s what he has done there. But if at all possible we shouldn\u2019t be adding any HTML simply for presentational purposes, even if the presentation is done via CSS. What we can do is to use the HTML we have already, as much as is possible, to add the style we want. This can take some creative thinking, but once you get the hang of this approach it becomes a more natural way of using HTML compared with simply adding divs and spans at will as hooks for style. Of course, this technique isn\u2019t always simple, and in fact sometimes simply not possible, requiring us to add just a little HTML to provide the \u201chooks\u201d for CSS.\n\nLet\u2019s go to work\n\nThe first step is to add a background image to the whole vCard element.\n\n\n\nWe make this wide enough (for example 1000 or more pixels) and tall enough that no matter how large the content of the vCard grows, it will never overflow this area. We can\u2019t simply repeat the image, because the top left corner will show when the image repeats.\n\nWe add this as the background image of the vCard element using CSS.\n\nWhile we are at it, let\u2019s give the text a sans-serif font, some color so that it will be visible, and stop the image repeating.\n\n.vcard {\n\tbackground-image: url(images/vcardfill.png);\n\tbackground-repeat: no-repeat;\n\tcolor: #666;\n\tfont-family: \"Lucida Grande\", Verdana, Helvetica, Arial, sans-serif;\n}\n\nWhich in a browser, will look something like this.\n\n\n\nNext step we need to add the top right hand corner of the hCard. In keeping with our aim of not adding HTML simply for styling purposes, we want to use the existing structure of the page where possible. Here, we\u2019ll use the paragraph of class fn and org, which is the first child element of the vcard element.\n\n

    Web Directions Conference Pty Ltd \"download

    \n\nHere\u2019s our CSS for this element\n\n.fn {\n\tbackground-image: url(images/topright.png);\n\tbackground-repeat: no-repeat;\n\tbackground-position: top right;\n\tpadding-top: 2em;\n\tfont-weight: bold;\n\tfont-size: 1.1em;\n}\n\nAgain, we don\u2019t want it to repeat, but this time, we\u2019ve specified a background position for the image. This will make the background image start from the top, but its right edge will be located at the right edge of the element. I also made the font size a little bigger, and the weight bold, to differentiate it from the rest of the text in the hCard.\n\nHere\u2019s the image we are adding as the background to this element.\n\n\n\nSo, putting these two CSS statements together we get\n\n\n\nWe specified a padding-top of 2em to give some space between the content of the fn element and the edge of the fn element. Otherwise the top of the hCard image would be hard against the border. To see this in action, just remove the padding-top: 2em; declaration and preview in a browser.\n\nSo, with just two statements, we are well under way. We\u2019ve not even had to add any HTML so far. Let\u2019s turn to the bottom of the element, and add the bottom border (well, the background image which will serve as that border).\n\nNow, which element are we going to use to add this background image to?\n\nOK, here I have to admit to a little, teensie bit of cheating. If you look at the HTML of the hCard, I\u2019ve grouped the email and telephone properties into a div, with a class of telecommunications. This grouping is not strictly requred for our hCard.\n\n
    \n\t

    Phone/Fax: Work:\n\t\t61 2 9365 5007

    \n\t

    Email: info@webdirections.org

    \n
    \n\nNow, I chose that class name because that is what the vCard specification calls this group of properties. And typically, I do tend to group together related elements using divs when I mark up content. I find it makes the page structure more logical and readable. But strictly speaking, this isn\u2019t necessary, so you may consider it cheating. But my lesson in this would be, if you are going to add markup, try to make it as meaningful as possible.\n\nAs you have probably guessed by now, we are going to add one part of the bottom border image to this element. We\u2019re going to add this image as the background-image.\n\n\n\nAgain, it will be a very wide image, like the top left one, so that no matter how wide the element might get, the background image will still be wide enough. Now, we\u2019ll need to make this image sit in the bottom left of the element we attach it to, so we use a backgound position of left bottom (we put the horizontal position before the vertical). Here\u2019s our CSS statement for this\n\n.telecommunications {\n\tbackground-image: url(images/bottom-left.png);\n\tbackground-repeat: no-repeat;\n\tbackground-position: left bottom;\n\tmargin-bottom: 2em;\n}\n\nAnd that will look like this\n\n\n\nNot quite there, but well on the way. Time for the final piece in the puzzle.\n\nOK, I admit, I might have cheated just a little bit more in this step. But like the previous step, all valid, and (hopefully) quite justifiable markup. If we look at the HTML again, you\u2019ll find that our email address is marked up like this\n\n

    Email: info@webdirections.org

    \n\nTypically, in hCard, the value part of this property isn\u2019t required, and we could get away with\n\ninfo@webdirections.org\n\nThe form I\u2019ve used, with the span of class value is however, perfectly valid hCard markup (hard allows for multiple email addresses of different types, which is where this typically comes in handy). Why have I gone to all this trouble? Well, when it came to styling the hCard, I realized I needed a block element to attach the background image for the bottom right hand corner to. Typically the last block element in the containing element is the ideal choice (and sometimes it\u2019s possible to take an inline element, for example the link here, and use CSS to make it a block element, and attach it to that, but that really doesn\u2019t work with this design).\n\nSo, if we are going to use the paragraph which contains the email link, we need a way to select it exclusively, which means that with CSS2 at least, we need a class or id as a hook for our CSS selector (in CSS3 we could use the last-child selector, which selects the last child element of a specified element, but again, as last child is not widely supported, we won\u2019t rely on it here.)\n\nSo, the least worst thing we could do is take an existing element, and add some reasonably meaningful markup to it. That\u2019s why we gave the paragraph a class of email, and the email address a class of value. Which reminds me a little of a moment in Hamlet\n\n\n\tThe lady doth protest too much, methinks\n\n\nOK, let\u2019s get back to the CSS.\n\nWe add the bottom right corner image, positioning it in the bottom right of the element, and making sure it doesn\u2019t repeat. We also add some padding to the bottom, to balance out the padding we added to the top of the hCard.\n\np.email {\n\tbackground-image: url(images/bottom-right.png);\n\tbackground-position: right bottom;\n\tbackground-repeat: no-repeat;\n\tpadding-bottom: 2em;\n}\n\nWhich all goes to make our hCard look like this\n\n\n\nIt just remains for us to clean up a little.\n\nLet\u2019s start from the top. We\u2019ll float the download image to the right like this\n\n.vcard img {\n\tfloat: right;\n\tpadding-right: 1em;\n\tmargin-top: -1em\n}\n\nSee how we didn\u2019t have to add a class to style the image, we used the fact that the image is a descendent of the vcard element, and a descendent selector. In my experience, the very widely supported, powerful descendent selector is one of the most underused aspects of CSS. So if you don\u2019t use it frequently, look into it in more detail.\n\nWe added some space to the right of the image, and pulled it up a bit closer to the top of the hCard, like this\n\n\n\nWe also want to add some whitespace between the edge of the hCard and the text. We would typically add padding to the left of the containing element, (in this case the vcard element) but this would break our bottom left hand corner, like this\n\n\n\nThat\u2019s because the div element we added this bottom left background image to would be moved in by the padding on its containing element.\n\nSo instead, we add left margin to all the paragraphs in the hCard\n\n.vcard p {\n\tmargin-left: 1em;\n}\n\n(there is the descendent selector again \u2013 it is the swiss army knife of CSS)\n\nNow, we\u2019ve not yet made the width of the hCard a function of the size of the text inside it (or \u201cem driven\u201d as we described it earlier). We do this by giving the hCard a width that is specified in em units. Here we\u2019ll set a width of say 28em, which makes the hCard always roughly as wide as 28 characters (strictly speaking 28 times the width of the letter capital M). \n\nSo the statement for our containing vcard element becomes\n\n.vcard {\n\tbackground-image: url(images/vcardfill.png);\n\tbackground-repeat: no-repeat;\n\tcolor: #666;\n\tfont-family: \"Lucida Grande\", Verdana, Helvetica, Arial, sans-serif;\n\twidth: 28em;\n}\n\nand now our element will look like this\n\n\n\nWe\u2019ve used almost entirely the existing HTML from our original hCard (adding just a little, and trying as much as possible to keep that additional markup meaningful), and just 6 CSS statements.\n\nHoliday Bonus \u2013 a downloadable vCard\n\nDid you notice this part of the HTML\n\n\n \"download\n\nWhat\u2019s with the odd looking url\n\nbody {\n\tfont-size: 12px; \n}\np {\n\tline-height 1.5em; \n}\n\nThere are many ways to size text in CSS and the above approach provides and accessible method of achieving the pixel-precision solid typography requires. By way of explanation, the first font-size reduces the body text from the 16px default (common to most browsers and OS set-ups) down to the 12px we require. This rule is primarily there for Internet Explorer 6 and below on Windows: the percentage value means that the text will scale predictably should a user bump the text size up or down. The second font-size sets the text size specifically and is ignored by IE6, but used by Firefox, Safari, IE7, Opera and other modern browsers which allow users to resize text sized in pixels.\n\nSpacing between paragraphs\n\nWith our rhythmic unit set at 18px we need to ensure that it is maintained throughout the body copy. A common place to lose the rhythm is the gaps set between margins. The default treatment by web browsers of paragraphs is to insert a top- and bottom-margin of 1em. In our case this would give a spacing between the paragraphs of 12px and hence throw the text out of rhythm. If the rhythm of the page is to be maintained, the spacing of paragraphs should be related to the basic line height unit. This is achieved simply by setting top- and bottom-margins equal to the line height.\n\nIn order that typographic integrity is maintained when text is resized by the user we must use ems for all our vertical measurements, including line-height, padding and margins.\n\np {\n\tfont-size:1em;\n\tmargin-top: 1.5em;\n\tmargin-bottom: 1.5em; \n}\n\nBrowsers set margins on all block-level elements (such as headings, lists and blockquotes) so a way of ensuring that typographic attention is paid to all such elements is to reset the margins at the beginning of your style sheet. You could use a rule such as:\n\nbody,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,p,blockquote,th,td { \n\tmargin:0; \n\tpadding:0; \n}\n\nAlternatively you could look into using the Yahoo! UI Reset style sheet which removes most default styling, so providing a solid foundation upon which you can explicitly declare your design intentions.\n\nVariations in text size\n\nWhen there is a change in text size, perhaps with a heading or sidenotes, the differing text should also take up a multiple of the basic leading. This means that, in our example, every diversion from the basic text size should take up multiples of 18px. This can be accomplished by adjusting the line-height and margin accordingly, as described following.\n\nHeadings\n\nSubheadings in the example page are set to 14px. In order that the height of each line is 18px, the line-height should be set to 18\u00a0\u00f7\u00a014 =\u00a01.286. Similarly the margins above and below the heading must be adjusted to fit. The temptation is to set heading margins to a simple 1em, but in order to maintain the rhythm, the top and bottom margins should be set at 1.286em so that the spacing is equal to the full 18px unit.\n\nh2 {\n\tfont-size:1.1667em;\n\tline-height: 1.286em;\n\tmargin-top: 1.286em;\n\tmargin-bottom: 1.286em; \n}\n\nOne can also set asymmetrical margins for headings, provided the margins combine to be multiples of the basic line height. In our example, a top margin of 1\u00bd lines is combined with a bottom margin of half a line as follows:\n\nh2 {\n\tfont-size:1.1667em;\n\tline-height: 1.286em;\n\tmargin-top: 1.929em;\n\tmargin-bottom: 0.643em; \n}\n\nAlso in our example, the main heading is given a text size of 18px, therefore the line-height has been set to 1em, as has the margin:\n\nh1 {\n\tfont-size:1.5em;\n\tline-height: 1em;\n\tmargin-top: 0;\n\tmargin-bottom: 1em; \n}\n\nSidenotes\n\nSidenotes (and other supplementary material) are often set at a smaller size to the basic text. To keep the rhythm, this smaller text should still line up with body copy, so a calculation similar to that for headings is required. In our example, the sidenotes are set at 10px and so their line-height must be increased to 18\u00a0\u00f7\u00a010 =\u00a01.8.\n\n.sidenote {\n\tfont-size:0.8333em;\n\tline-height:1.8em; \n}\n\nBorders\n\nOne additional point where vertical rhythm is often lost is with the introduction of horizontal borders. These effectively act as shims pushing the subsequent text downwards, so a two pixel horizontal border will throw out the vertical rhythm by two pixels. A way around this is to specify horizontal lines using background images or, as in our example, specify the width of the border in ems and adjust the padding to take up the slack. \n\nThe design of the footnote in our example requires a 1px horizontal border. The footnote contains 12px text, so 1px in ems is 1\u00a0\u00f7\u00a012 =\u00a00.0833. I have added a margin of 1\u00bd lines above the border (1.5\u00a0\u00d7\u00a018\u00a0\u00f7\u00a012 =\u00a02.5ems), so to maintain the rhythm the border + padding must equal a \u00bd (9px). We know the border is set to 1px, so the padding must be set to 8px. To specify this in ems we use the familiar calculation: 8\u00a0\u00f7\u00a012 =\u00a00.667.\n\nHit me with your rhythm stick\n\nComposing to a vertical rhythm helps engage and guide the reader down the page, but it takes typographic discipline to do so. It may seem like a lot of fiddly maths is involved (a few divisions and multiplications never hurt anyone) but good type setting is all about numbers, and it is this attention to detail which is the key to success.", "year": "2006", "author": "Richard Rutter", "author_slug": "richardrutter", "published": "2006-12-12T00:00:00+00:00", "url": "https://24ways.org/2006/compose-to-a-vertical-rhythm/", "topic": "design"} {"rowid": 142, "title": "Revealing Relationships Can Be Good Form", "contents": "A few days ago, a colleague of mine \u2013 someone I have known for several years, who has been doing web design for several years and harks back from the early days of ZDNet \u2013 was running through a prototype I had put together for some user testing. As with a lot of prototypes, there was an element of \u2018smoke and mirrors\u2019 to make things look like they were working. \n\nOne part of the form included a yes/no radio button, and selecting the Yes option would, in the real and final version of the form, reveal some extra content. Rather than put too much JavaScript in the prototype, I took a preverbial shortcut and created a link which I wrapped around the text next to the radio button \u2013 clicking on that link would cause the form to mimic a change event on the radio button. But it wasn\u2019t working for him. \n\nWhy was that? Because whereas I created the form using a I\u2019d placed around the text). Bah! There goes my time-saver.\n\nSo, what did I learn? That a web professional who has used the Internet for years had neither heard of the .net\n\tadvertising\n\tajax\n\t...\n
    \n\nUnfortunately, that is one of the worst examples of tag cloud markup I have ever seen. The page states that a tag cloud is a list of tags where size reflects popularity. However, despite describing it in this way to the human readers, the page\u2019s author hasn\u2019t described it that way in the markup. It isn\u2019t a list of tags, just a bunch of anchors in a
    . This is also inaccessible because a screenreader will not pause between adjacent links, and in some configurations will not announce the individual links, but rather all of the tags will be read as just one link containing a whole bunch of words. Markup crime number one. \n\nFlickr \n\nAh, Flickr. The darling photo sharing site of the internet, and the biggest blind spot in every standardista\u2019s vision. Forgive it for having atrocious markup and sometimes confusing UI because it\u2019s just so much damn fun to use. Let\u2019s see what they do. \n\n

    \n\t\u00a006\u00a0\n\t\u00a0africa\u00a0\n\t\u00a0amsterdam\u00a0\n\t...\n

    \n\nAgain we have a simple collection of anchors like del.icio.us, only this time in a paragraph. But rather than using a class to represent the size of the tag they use an inline style. An inline style using a pixel-based font size. That\u2019s so far away from the goal of separating style from content, they might as well use a tag. You could theoretically parse that to extract the information, but you have more work to guess what the pixel sizes represent. Markup crime number two (and extra jail time for using non-breaking spaces purely for visual spacing purposes.)\n\nTechnorati \n\nAh, now. Here, you\u2019d expect something decent. After all, the Overlord of microformats and King of Semantics Tantek \u00c7elik works there. Surely we\u2019ll see something decent here? \n\n
      \n\t
    1. Britney Spears
    2. \n\t
    3. Bush
    4. \n\t
    5. Christmas
    6. \n\t...\n\t
    7. SEO
    8. \n\t
    9. Shopping
    10. \n\t...\n
    \n\nUnfortunately it turns out not to be that decent, and stop calling me Shirley. It\u2019s not exactly terrible code. It does recognise that a tag cloud is a list of links. And, since they\u2019re in alphabetical order, that it\u2019s an ordered list of links. That\u2019s nice. However \u2026 fifteen nested tags? FIFTEEN? That\u2019s emphasis for you. Yes, it is parse-able, but it\u2019s also something of a strange way of looking at emphasis. The HTML spec states that is emphasis, and is for stronger emphasis. Nesting tags seems counter to the idea that different tags are used for different levels of emphasis. Plus, if you had a screen reader that stressed the voice for emphasis, what would it do? Shout at you? Markup crime number three. \n\nSo what should it be? \n\nAs del.icio.us tells us, a tag cloud is a list of tags where the size that they are rendered at contains extra information. However, by hiding the extra context purely within the CSS or the HTML tags used, you are denying that context to some users. The basic assumption being made is that all users will be able to see the difference between font sizes, and this is demonstrably false. \n\nA better way to code a tag cloud is to put the context of the cloud within the content, not the markup or CSS alone. As an example, I\u2019m going to take some of my favourite flickr tags and put them into a cloud which communicates the relative frequency of each tag. \n\nTo start with a tag cloud in its most basic form is just a list of links. I am going to present them in alphabetical order, so I\u2019ll use an ordered list. Into each list item I add the number of photos I have with that particular tag. The tag itself is linked to the page on flickr which contains those photos. So we end up with this first example. To display this as a traditional tag cloud, we need to alter it in a few ways: \n\n\n\tThe items need to be displayed next to each other, rather than one-per-line\n\tThe context information should be hidden from display (but not from screen readers)\n\tThe tag should link to the page of items with that tag\n\n\nDisplaying the items next to each other simply means setting the display of the list elements to inline. The context can be hidden by wrapping it in a and then using the off-left method to hide it. And the link just means adding an anchor (with rel=\"tag\" for some extra microformats bonus points). So, now we have a simple collection of links in our second example. \n\nThe last stage is to add the sizes. Since we already have context in our content, the size is purely for visual rendering, so we can just use classes to define the different sizes. For my example, I\u2019ll use a range of class names from not-popular through ultra-popular, in order of smallest to largest, and then use CSS to define different font sizes. If you preferred, you could always use less verbose class names such as size1 through size6. Anyway, adding some classes and CSS gives us our final example, a semantic and more accessible tag cloud.", "year": "2006", "author": "Mark Norman Francis", "author_slug": "marknormanfrancis", "published": "2006-12-09T00:00:00+00:00", "url": "https://24ways.org/2006/marking-up-a-tag-cloud/", "topic": "code"} {"rowid": 144, "title": "The Mobile Web, Simplified", "contents": "A note from the editors: although eye-opening in 2006, this article is no longer relevant to today\u2019s mobile web.\n \n \n \n Considering a foray into mobile web development? Following are four things you need to know before making the leap.\n\n1. 4 billion mobile subscribers expected by 2010\n\nFancy that. Coupled with the UN prediction of 6.8 billion humans by 2010, 4 billion mobile subscribers (source) is an astounding 59% of the planet. Just how many of those subscribers will have data plans and web-enabled phones is still in question, but inevitably this all means one thing for you and me: A ton of potential eyes to view our web content on a mobile device.\n\n2. Context is king\n\nYour content is of little value to users if it ignores the context in which it is viewed. Consider how you access data on your mobile device. You might be holding a bottle of water or gripping a handle on the subway/tube. You\u2019re probably seeking specific data such as directions or show times, rather than the plethora of data at your disposal via a desktop PC.\n\nThe mobile web, a phrase often used to indicate \u201caccessing the web on a mobile device\u201d, is very much a context-, content-, and component-specific environment. Expressed in terms of your potential target audience, access to web content on a mobile device is largely influenced by surrounding circumstances and conditions, information relevant to being mobile, and the feature set of the device being used. Ask yourself, What is relevant to my users and the tasks, problems, and needs they may encounter while being mobile? Answer that question and you\u2019ll be off to a great start.\n\n3. WAP 2.0 is an XHTML environment\n\nIn a nutshell, here are a few fundamental tenets of mobile internet technology:\n\n\n\tWireless Application Protocol (WAP) is the protocol for enabling mobile access to internet content.\n\tWireless Markup Language (WML) was the language of choice for WAP 1.0.\n\tNearly all devices sold today are WAP 2.0 devices.\n\tWith the introduction of WAP 2.0, XHTML Mobile Profile (XHTML-MP) became the preferred markup language.\n\tXHTML-MP will be familiar to anyone experienced with XHTML Transitional or Strict.\n\n\nSummary? The mobile web is rapidly becoming an XHTML environment, and thus you and I can apply our existing \u201cdesktop web\u201d skills to understand how to develop content for it. With WML on the decline, the learning curve is much smaller today than it was several years ago. I\u2019m generalizing things gratuitously, but the point remains: Get off yo\u2019 lazy butt and begin to take mobile seriously.\n\nI\u2019ll even pass you a few tips for getting started. First, the DOCTYPE for XHTML-MP is as follows:\n\n\n\nAs for MIME type, Open Mobile Alliance (OMA) specifies using the MIME type application/vnd.wap.xhtml+xml, but ultimately you need to ensure the server delivering your mobile content is configured properly for the MIME type you choose to use, as there are other options (see Setting up WAP Servers).\n\nOnce you\u2019ve made it to the body, the XHTML-MP markup is not unlike what you\u2019re already used to. A few resources worth skimming:\n\n\n\tDevelopers Home XHTML-MP Tutorial \u2013 An impressively replete resource for all things XHTML-MP\n\tXHTML-MP Tags List \u2013 A complete list of XHTML-MP elements and accompanying attributes\n\n\nAnd last but certainly not least, CSS. There exists WAP CSS, which is essentially a subset of CSS2 with WAP-specific extensions. For all intents and purposes, much of the CSS you\u2019re already comfortable using will be transferrable to mobile. As for including CSS in your pages, your options are the same as for desktop sites: external, embedded, and inline. Some experts will argue embedded or inline over external in favor of reducing the number of HTTP connections per page request, yet many popular mobilized sites and apps employ external linking without issue.\n\nStocking stuffers: Flickr Mobile, Fandango Mobile, and Popurls Mobile. A few sites with whom you can do the View Source song and dance for further study.\n\n4. \u201cCell phone\u201d is so DynaTAC\n\nIf you\u2019re a U.S. resident, listen up: You must rid your vocabulary of the term \u201ccell phone\u201d. We\u2019re one of the few economies on the planet to refer to a mobile phone accordingly. If you care to find yourself in any of the worthwhile mobile development circles, begin using terms more widely accepted: \u201cmobile\u201d or \u201cmobile phone\u201d or \u201chandset\u201d or \u201chandy\u201d. If you\u2019re not sure which, go for \u201cmobile\u201d. Such as, \u201cYo dog, check out my new mobile.\u201d\n\nMore importantly, however, is overcoming the mentality that access to the mobile web can be done only with a phone. Instead, \u201cdevice\u201d encourages us to think phone, handheld computer, watch, Nintendo DS, car, you name it.\n\nSimple enough?", "year": "2006", "author": "Cameron Moll", "author_slug": "cameronmoll", "published": "2006-12-19T00:00:00+00:00", "url": "https://24ways.org/2006/the-mobile-web-simplified/", "topic": "ux"} {"rowid": 145, "title": "The Neverending (Background Image) Story", "contents": "Everyone likes candy for Christmas, and there\u2019s none better than eye candy. Well, that, and just more of the stuff. Today we\u2019re going to combine both of those good points and look at how to create a beautiful background image that goes on and on\u2026 forever!\n\nOf course, each background image is different, so instead of agonising over each and every pixel, I\u2019m going to concentrate on five key steps that you can apply to any of your own repeating background images. In this example, we\u2019ll look at the Miami Beach background image used on the new FOWA site, which I\u2019m afraid is about as un-festive as you can get.\n\n1. Choose your image wisely\n\nI find there are three main criteria when judging photos you\u2019re considering for repetition manipulation (or \u2018repetulation\u2019, as I like to say)\u2026\n\n\n\tsimplicity (beware of complex patterns)\n\tangle and perspective (watch out for shadows and obvious vanishing points)\n\tconsistent elements (for easy cloning)\n\n\nYou might want to check out this annotated version of the image, where I\u2019ve highlighted elements of the photo that led me to choose it as the right one.\n\nThe original image purchased from iStockPhoto.\n\nThe Photoshopped version used on the FOWA site.\n\n2. The power of horizontal lines\n\nWith the image chosen and your cursor poised for some Photoshop magic, the most useful thing you can do is drag out the edge pixels from one side of the image to create a kind of rough colour \u2018template\u2019 on which to work over. It doesn\u2019t matter which side you choose, although you might find it beneficial to use the one with the simplest spread of colour and complex elements.\n\nClick and hold on the marquee tool in the toolbar and select the \u2018single column marquee tool\u2019, which will span the full height of your document but will only be one pixel wide. Make the selection right at the edge of your document, press ctrl-c / cmd-c to copy the selection you made, create a new layer, and hit ctrl-v / cmd-v to paste the selection onto your new layer. using free transform (ctrl-t / cmd-t), drag out your selection so that it becomes as wide as your entire canvas. \n\nA one-pixel-wide selection stretched out to the entire width of the canvas.\n\n3. Cloning\n\nIt goes without saying that the trusty clone tool is one of the most important in the process of creating a seamlessly repeating background image, but I think it\u2019s important to be fairly loose with it. Always clone on to a new layer so that you\u2019ve got the freedom to move it around, but above all else, use the eraser tool to tweak your cloned areas: let that handle the precision stuff and you won\u2019t have to worry about getting your clones right first time.\n\nIn the example below, you can see how I overcame the problem of the far-left tree shadow being chopped off by cloning the shadow from the tree on its right. \n\nThe edge of the shadow is cut off and needs to be \u2018made\u2019 from a pre-existing element.\n\nThe successful clone completes the missing shadow.\n\nThe two elements are obviously very similar but it doesn\u2019t look like a clone because the majority of the shape is \u2018genuine\u2019 and only a small part is a duplicate. Also, after cloning I transformed the duplicate, erased parts of it, used gradients, and \u2014 ooh, did someone mention gradients?\n\n4. Never underestimate a gradient\n\nFor this image, I used gradients in a similar way to a brush: covering large parts of the canvas with a colour that faded out to a desired point, before erasing certain parts for accuracy.\n\nSeveral of the gradients and brushes that make up the \u2018customised\u2019 part of the image, visible when the main photograph layer is hidden.\n\nThe full composite.\n\nGradients are also a bit of an easy fix: you can use a gradient on one side of the image, flip it horizontally, and then use it again on the opposite side to make a more seamless join.\n\nSpeaking of which\u2026\n\n5. Sewing the seams\n\nNo matter what kind of magic Photoshop dust you sprinkle over your image, there will still always be the area where the two edges meet: that scary \u2018loop\u2019 point. Fret ye not, however, for there\u2019s help at hand in the form of a nice little cheat. Even though the loop point might still be apparent, we can help hide it by doing something to throw viewers off the scent.\n\nThe seam is usually easy to spot because it\u2019s a blank area with not much detail or colour variation, so in order to disguise it, go against the rule: put something across it!\n\nThis isn\u2019t quite as challenging as it may sound, because if we intentionally make our own \u2018object\u2019 to span the join, we can accurately measure the exact halfway point where we need to split it across the two sides of the image. This is exactly what I did with the FOWA background image: I made some clouds!\n\nA sky with no clouds in an unhappy one.\n\nA simple soft white brush creates a cloud-like formation in the sky.\n\nAfter taking the cloud\u2019s opacity down to 20%, I used free transform to highlight the boundaries of the layer. I then moved it over to the right, so that the middle of the layer perfectly aligned with the right side of the canvas.\n\nFinally, I duplicated the layer and did the same in reverse: dragging the layer over to the left and making sure that the middle of the duplicate layer perfectly aligned with the left side of the canvas.\n\nAnd there you have it! Boom! Ta-da! Et Voila! To see the repeating background image in action, visit futureofwebapps.com on a large widescreen monitor or see a simulation of the effect.\n\nThanks for reading, folks. Have a great Christmas!", "year": "2007", "author": "Elliot Jay Stocks", "author_slug": "elliotjaystocks", "published": "2007-12-03T00:00:00+00:00", "url": "https://24ways.org/2007/the-neverending-background-image-story/", "topic": "code"} {"rowid": 146, "title": "Increase Your Font Stacks With Font Matrix", "contents": "Web pages built in plain old HTML and CSS are displayed using only the fonts installed on users\u2019 computers (@font-face implementations excepted). To enable this, CSS provides the font-family property for specifying fonts in order of preference (often known as a font stack). For example:\n\nh1 {font-family: 'Egyptienne F', Cambria, Georgia, serif}\n\nSo in the above rule, headings will be displayed in Egyptienne F. If Egyptienne F is not available then Cambria will be used, failing that Georgia or the final fallback default serif font. This everyday bit of CSS will be common knowledge among all 24 ways readers.\n\nIt is also a commonly held belief that the only fonts we can rely on being installed on users\u2019 computers are the core web fonts of Arial, Times New Roman, Verdana, Georgia and friends. But is that really true?\n\nIf you look in the fonts folder of your computer, or even your Mum\u2019s computer, then you are likely to find a whole load of fonts besides the core ones. This is because many software packages automatically install extra typefaces. For example, Office 2003 installs over 100 additional fonts. Admittedly not all of these fonts are particularly refined, and not all are suitable for the Web. However they still do increase your options. \n\nThe Matrix\n\nI have put together a matrix of (western) fonts showing which are installed with Mac and Windows operating systems, which are installed with various versions of Microsoft Office, and which are installed with Adobe Creative Suite.\n\n\n\nThe matrix is available for download as an Excel file and as a CSV. There are no readily available statistics regarding the penetration of Office or Creative Suite, but you can probably take an educated guess based on your knowledge of your readers.\n\nThe idea of the matrix is that use can use it to help construct your font stack. First of all pick the font you\u2019d really like for your text \u2013 this doesn\u2019t have to be in the matrix. Then pick the generic family (serif, sans-serif, cursive, fantasy or monospace) and a font from each of the operating systems. Then pick any suitable fonts from the Office and Creative Suite lists.\n\nFor example, you may decide your headings should be in the increasingly ubiquitous Clarendon. This is a serif type face. At OS-level the most similar is arguably Georgia. Adobe CS2 comes with Century Old Style which has a similar feel. Century Schoolbook is similar too, and is installed with all versions of Office. Based on this your font stack becomes:\n\nfont-family: 'Clarendon Std', 'Century Old Style Std', 'Century Schoolbook', Georgia, serif\n\n\n\n\n\n\nNote the \u2018Std\u2019 suffix indicating a \u2018standard\u2019 OpenType file, which will normally be your best bet for more esoteric fonts.\n\nI\u2019m not suggesting the process of choosing suitable fonts is an easy one. Firstly there are nearly two hundred fonts in the matrix, so learning what each font looks like is tricky and potentially time consuming (if you haven\u2019t got all the fonts installed on a machine to hand you\u2019ll be doing a lot of Googling for previews). And it\u2019s not just as simple as choosing fonts that look similar or have related typographic backgrounds, they need to have similar metrics as well, This is especially true in terms of x-height which gives an indication of how big or small a font looks.\n\nOver to You\n\nThe main point of all this is that there are potentially more fonts to consider than is generally accepted, so branch out a little (carefully and tastefully) and bring a little variety to sites out there. If you come up with any novel font stacks based on this approach, please do blog them (tagged as per the footer) and at some point they could all be combined in one place for everyone to consider.\n\nAppendix\n\nWhat about Linux?\n\nThe only operating systems in the matrix are those from Microsoft and Apple. For completeness, Linux operating systems should be included too, although these are many and varied and very much in a minority, so I omitted them for time being. For the record, some Linux distributions come packaged with Microsoft\u2019s core fonts. Others use the Vera family, and others use the Liberation family which comprises fonts metrically identical to Times New Roman and Arial.\n\nSources\n\nThe sources of font information for the matrix are as follows:\n\n\n\tWindows XP SP2\n\tWindows Vista\n\tOffice 2003\n\tOffice 2007\n\tMac OSX Tiger\n\tMac OSX Leopard (scroll down two thirds)\n\tOffice 2004 (Mac) by inspecting my Microsoft Office 2004/Office/Fonts folder\n\tOffice 2008 (Mac) is expected to be as Office 2004 with the addition of the Vista ClearType fonts\n\tCreative Suite 2 (see pdf link in first comment)\n\tCreative Suite 3", "year": "2007", "author": "Richard Rutter", "author_slug": "richardrutter", "published": "2007-12-17T00:00:00+00:00", "url": "https://24ways.org/2007/increase-your-font-stacks-with-font-matrix/", "topic": "design"} {"rowid": 147, "title": "Christmas Is In The AIR", "contents": "That\u2019s right, Christmas is coming up fast and there\u2019s plenty of things to do. Get the tree and lights up, get the turkey, buy presents and who know what else. And what about Santa? He\u2019s got a list. I\u2019m pretty sure he\u2019s checking it twice.\n\nSure, we could use an existing list making web site or even a desktop widget. But we\u2019re geeks! What\u2019s the fun in that? Let\u2019s build our own to-do list application and do it with Adobe AIR!\n\nWhat\u2019s Adobe AIR?\n\nAdobe AIR, formerly codenamed Apollo, is a runtime environment that runs on both Windows and OSX (with Linux support to follow). This runtime environment lets you build desktop applications using Adobe technologies like Flash and Flex. Oh, and HTML. That\u2019s right, you web standards lovin\u2019 maniac. You can build desktop applications that can run cross-platform using the trio of technologies, HTML, CSS and JavaScript.\n\nIf you\u2019ve tried developing with AIR before, you\u2019ll need to get re-familiarized with the latest beta release as many things have changed since the last one (such as the API and restrictions within the sandbox.)\n\nTo get started\n\nTo get started in building an AIR application, you\u2019ll need two basic things:\n\n\n\tThe AIR runtime. The runtime is needed to run any AIR-based application.\n\tThe SDK. The software development kit gives you all the pieces to test your application. Unzip the SDK into any folder you wish.\n\n\nYou\u2019ll also want to get your hands on the JavaScript API documentation which you\u2019ll no doubt find yourself getting into before too long. (You can download it, too.)\n\nAlso of interest, some development environments have support for AIR built right in. Aptana doesn\u2019t have support for beta 3 yet but I suspect it\u2019ll be available shortly.\n\nWithin the SDK, there are two main tools that we\u2019ll use: one to test the application (ADL) and another to build a distributable package of our application (ADT). I\u2019ll get into this some more when we get to that stage of development.\n\nBuilding our To-do list application\n\nThe first step to building an application within AIR is to create an XML file that defines our default application settings. I call mine application.xml, mostly because Aptana does that by default when creating a new AIR project. It makes sense though and I\u2019ve stuck with it. Included in the templates folder of the SDK is an example XML file that you can use.\n\nThe first key part to this after specifying things like the application ID, version, and filename, is to specify what the default content should be within the content tags. Enter in the name of the HTML file you wish to load. Within this HTML file will be our application.\n\nui.html\n\nCreate a new HTML document and name it ui.html and place it in the same directory as the application.xml file. The first thing you\u2019ll want to do is copy over the AIRAliases.js file from the frameworks folder of the SDK and add a link to it within your HTML document.\n\n\n\nThe aliases create shorthand links to all of the Flash-based APIs.\n\nNow is probably a good time to explain how to debug your application.\n\nDebugging our application\n\nSo, with our XML file created and HTML file started, let\u2019s try testing our \u2018application\u2019. We\u2019ll need the ADL application located in BIN folder of the SDK and tell it to run the application.xml file.\n\n/path/to/adl /path/to/application.xml\n\nYou can also just drag the XML file onto ADL and it\u2019ll accomplish the same thing. If you just did that and noticed that your blank application didn\u2019t load, you\u2019d be correct. It\u2019s running but isn\u2019t visible. Which at this point means you\u2019ll have to shut down the ADL process. Sorry about that!\n\nChanging the visibility\n\nYou have two ways to make your application visible. You can do it automatically by setting the placing true in the visible tag within the application.xml file.\n\ntrue\n\nThe other way is to do it programmatically from within your application. You\u2019d want to do it this way if you had other startup tasks to perform before showing the interface. To turn the UI on programmatically, simple set the visible property of nativeWindow to true.\n\n\n\nSandbox Security\n\nNow that we have an application that we can see when we start it, it\u2019s time to build the to-do list application. In doing so, you\u2019d probably think that using a JavaScript library is a really good idea \u2014 and it can be but there are some limitations within AIR that have to be considered.\n\nAn HTML document, by default, runs within the application sandbox. You have full access to the AIR APIs but once the onload event of the window has fired, you\u2019ll have a limited ability to make use of eval and other dynamic script injection approaches. This limits the ability of external sources from gaining access to everything the AIR API offers, such as database and local file system access. You\u2019ll still be able to make use of eval for evaluating JSON responses, which is probably the most important if you wish to consume JSON-based services.\n\nIf you wish to create a greater wall of security between AIR and your HTML document loading in external resources, you can create a child sandbox. We won\u2019t need to worry about it for our application so I won\u2019t go any further into it but definitely keep this in mind.\n\nFinally, our application\n\nGetting tired of all this preamble? Let\u2019s actually build our to-do list application. I\u2019ll use jQuery because it\u2019s small and should suit our needs nicely. Let\u2019s begin with some structure:\n\n\n\t\n\t\n\t
      \n\n\nNow we need to wire up that button to actually add a new item to our to-do list.\n\n\n\nAnd just like that, we\u2019ve got a to-do list! That\u2019s it! Just never close your application and you\u2019ll remember everything. Okay, that\u2019s not very practical. You need to have some way of storing your to-do items until the next time you open up the application.\n\nStoring Data\n\nYou\u2019ve essentially got 4 different ways that you can store data:\n\n\n\tUsing the local database. AIR comes with SQLLite built in. That means you can create tables and insert, update and select data from that database just like on a web server.\n\tUsing the file system. You can also create files on the local machine. You have access to a few folders on the local system such as the documents folder and the desktop.\n\tUsing EcryptedLocalStore. I like using the EcryptedLocalStore because it allows you to easily save key/value pairs and have that information encrypted. All this within just a couple lines of code.\n\tSending the data to a remote API. Our to-do list could sync up with Remember the Milk, for example.\n\n\nTo demonstrate some persistence, we\u2019ll use the file system to store our files. In addition, we\u2019ll let the user specify where the file should be saved. This way, we can create multiple to-do lists, keeping them separate and organized.\n\nThe application is now broken down into 4 basic tasks:\n\n\n\tLoad data from the file system.\n\tPerform any interface bindings.\n\tManage creating and deleting items from the list.\n\tSave any changes to the list back to the file system.\n\n\nLoading in data from the file system\n\nWhen the application starts up, we\u2019ll prompt the user to select a file or specify a new to-do list. Within AIR, there are 3 main file objects: File, FileMode, and FileStream. File handles file and path names, FileMode is used as a parameter for the FileStream to specify whether the file should be read-only or for write access. The FileStream object handles all the read/write activity.\n\nThe File object has a number of shortcuts to default paths like the documents folder, the desktop, or even the application store. In this case, we\u2019ll specify the documents folder as the default location and then use the browseForSave method to prompt the user to specify a new or existing file. If the user specifies an existing file, they\u2019ll be asked whether they want to overwrite it.\n\nvar store = air.File.documentsDirectory;\nvar fileStream = new air.FileStream();\nstore.browseForSave(\"Choose To-do List\");\n\nThen we add an event listener for when the user has selected a file. When the file is selected, we check to see if the file exists and if it does, read in the contents, splitting the file on new lines and creating our list items within the interface.\n\nstore.addEventListener(air.Event.SELECT, fileSelected);\nfunction fileSelected()\n{\n\tair.trace(store.nativePath);\n\t// load in any stored data\n\tvar byteData = new air.ByteArray();\n\tif(store.exists)\n\t{\n\t\tfileStream.open(store, air.FileMode.READ);\n\t\tfileStream.readBytes(byteData, 0, store.size);\n\t\tfileStream.close();\n\n\t\tif(byteData.length > 0)\n\t\t{\n\t\t\tvar s = byteData.readUTFBytes(byteData.length);\n\t\t\toldlist = s.split(\u201c\\r\\n\u201d);\n\n\t\t\t// create todolist items\n\t\t\tfor(var i=0; i < oldlist.length; i++)\n\t\t\t{\n\t\t\t\tcreateItem(oldlist[i], (new Date()).getTime() + i );\n\t\t\t}\n\t\t}\n\t}\n}\n\nPerform Interface Bindings\n\nThis is similar to before where we set the click event on the Add button but we\u2019ve moved the code to save the list into a separate function.\n\n$('#add').click(function(){\n\t\tvar t = $('#text').val();\n\t\tif(t){\n\t\t\t// create an ID using the time\n\t\t\tcreateItem(t, (new Date()).getTime() );\n\t\t}\n})\n\nManage creating and deleting items from the list\n\nThe list management is now in its own function, similar to before but with some extra information to identify list items and with calls to save our list after each change.\n\nfunction createItem(t, id)\n{\n\tif(t.length == 0) return;\n\t// add it to the todo list\n\ttodolist[id] = t;\n\t// use DOM methods to create the new list item\n\tvar li = document.createElement('li');\n\t// the extra space at the end creates a buffer between the text\n\t// and the delete link we're about to add\n\tli.appendChild(document.createTextNode(t + ' '));\n\t// create the delete link\n\tvar del = document.createElement('a');\n\t// this makes it a true link. I feel dirty doing this.\n\tdel.setAttribute('href', '#');\n\tdel.addEventListener('click', function(evt){\n\t\tvar id = this.id.substr(1);\n\t\tdelete todolist[id]; // remove the item from the list\n\t\tthis.parentNode.parentNode.removeChild(this.parentNode);\n\t\tsaveList();\n\t});\n\tdel.appendChild(document.createTextNode('[del]'));\n\tdel.id = 'd' + id;\n\tli.appendChild(del);\n\t// append everything to the list\n\t$('#list').append(li);\n\t//reset the text box\n\t$('#text').val('');\n\tsaveList();\n}\n\nSave changes to the file system\n\nAny time a change is made to the list, we update the file. The file will always reflect the current state of the list and we\u2019ll never have to click a save button. It just iterates through the list, adding a new line to each one.\n\nfunction saveList(){\n\tif(store.isDirectory) return;\n\tvar packet = '';\n\tfor(var i in todolist)\n\t{\n\t\tpacket += todolist[i] + '\\r\\n';\n\t}\n\tvar bytes = new air.ByteArray();\n\tbytes.writeUTFBytes(packet);\n\tfileStream.open(store, air.FileMode.WRITE);\n\tfileStream.writeBytes(bytes, 0, bytes.length);\n\tfileStream.close();\n}\n\nOne important thing to mention here is that we check if the store is a directory first. The reason we do this goes back to our browseForSave call. If the user cancels the dialog without selecting a file first, then the store points to the documentsDirectory that we set it to initially. Since we haven\u2019t specified a file, there\u2019s no place to save the list.\n\nHopefully by this point, you\u2019ve been thinking of some cool ways to pimp out your list. Now we need to package this up so that we can let other people use it, too.\n\nCreating a Package\n\nNow that we\u2019ve created our application, we need to package it up so that we can distribute it. This is a two step process. The first step is to create a code signing certificate (or you can pay for one from Thawte which will help authenticate you as an AIR application developer).\n\nTo create a self-signed certificate, run the following command. This will create a PFX file that you\u2019ll use to sign your application.\n\nadt -certificate -cn todo24ways 1024-RSA todo24ways.pfx mypassword\n\nAfter you\u2019ve done that, you\u2019ll need to create the package with the certificate\n\nadt -package -storetype pkcs12 -keystore todo24ways.pfx todo24ways.air application.xml .\n\nThe important part to mention here is the period at the end of the command. We\u2019re telling it to package up all files in the current directory.\n\nAfter that, just run the AIR file, which will install your application and run it.\n\nImportant things to remember about AIR\n\nWhen developing an HTML application, the rendering engine is Webkit. You\u2019ll thank your lucky stars that you aren\u2019t struggling with cross-browser issues. (My personal favourites are multiple backgrounds and border radius!)\n\nBe mindful of memory leaks. Things like Ajax calls and event binding can cause applications to slowly leak memory over time. Web pages are normally short lived but desktop applications are often open for hours, if not days, and you may find your little desktop application taking up more memory than anything else on your machine!\n\nThe WebKit runtime itself can also be a memory hog, usually taking about 15MB just for itself. If you create multiple HTML windows, it\u2019ll add another 15MB to your memory footprint. Our little to-do list application shouldn\u2019t be much of a concern, though.\n\nThe other important thing to remember is that you\u2019re still essentially running within a Flash environment. While you probably won\u2019t notice this working in small applications, the moment you need to move to multiple windows or need to accomplish stuff beyond what HTML and JavaScript can give you, the need to understand some of the Flash-based elements will become more important.\n\nLastly, the other thing to remember is that HTML links will load within the AIR application. If you want a link to open in the users web browser, you\u2019ll need to capture that event and handle it on your own. The following code takes the HREF from a clicked link and opens it in the default web browser.\n\nair.navigateToURL(new air.URLRequest(this.href));\n\nOnly the beginning\n\nOf course, this is only the beginning of what you can do with Adobe AIR. You don\u2019t have the same level of control as building a native desktop application, such as being able to launch other applications, but you do have more control than what you could have within a web application. Check out the Adobe AIR Developer Center for HTML and Ajax for tutorials and other resources.\n\nNow, go forth and create your desktop applications and hopefully you finish all your shopping before Christmas!\n\nDownload the example files.", "year": "2007", "author": "Jonathan Snook", "author_slug": "jonathansnook", "published": "2007-12-19T00:00:00+00:00", "url": "https://24ways.org/2007/christmas-is-in-the-air/", "topic": "code"} {"rowid": 148, "title": "Typesetting Tables", "contents": "Tables have suffered in recent years on the web. They were used for laying out web pages. Then, following the Web Standards movement, they\u2019ve been renamed by the populous as `data tables\u2019 to ensure that we all know what they\u2019re for. There have been some great tutorials for the designing tables using CSS for presentation and focussing on the semantics in the displaying of data in the correct way. However, typesetting tables is a subtle craft that has hardly had a mention.\n\nTable design can often end up being a technical exercise. What data do we need to display? Where is the data coming from and what form will it take? When was the last time your heard someone talk about lining numerals? Or designing to the reading direction?\n\nTables are not read like sentences\n\nWhen a reader looks at, and tries to understand, tabular data, they\u2019re doing a bunch of things at the same time.\n\n\n\tGenerally, they\u2019re task based; they\u2019re looking for something.\n\tThey are reading horizontally AND vertically\n\n\nReading a table is not like reading a paragraph in a novel, and therefore shouldn\u2019t be typeset in the same way. Designing tables is information design, it\u2019s functional typography\u2014it\u2019s not a time for eye candy.\n\nTypesetting tables\n\nTypesetting great looking tables is largely an exercise in restraint. Minimal interference with the legibility of the table should be in the forefront of any designers mind.\n\nWhen I\u2019m designing tables I apply some simple rules:\n\n\n\tPlenty of negative space\n\tUse the right typeface\n\tGo easy on the background tones, unless you\u2019re giving reading direction visual emphasis\n\tDesign to the reading direction\n\n\nBy way of explanation, here are those rules as applied to the following badly typeset table.\n\nYour default table\n\nThis table is a mess. There is no consideration for the person trying to read it. Everything is too tight. The typeface is wrong. It\u2019s flat. A grim table indeed.\n\n\n\nLet\u2019s see what we can do about that.\n\nPlenty of negative space\n\nThe badly typeset table has been set with default padding. There has been little consideration for the ascenders and descenders in the type interfering with the many horizontal rules.\n\nThe first thing we do is remove most of the lines, or rules. You don\u2019t need them \u2013 the data in the rows forms its own visual rules. Now, with most of the rules removed, the ones that remain mean something; they are indicating some kind of hierarchy to the help the reader understand what the different table elements mean \u2013 in this case the column headings.\n\n\n\nNow we need to give the columns and rows more negative space. Note the framing of the column headings. I\u2019m giving them more room at the bottom. This negative space is active\u2014it\u2019s empty for a reason. The extra air in here also gives more hierarchy to the column headings.\n\n\n\nUse the right typeface\n\nThe default table is set in a serif typeface. This isn\u2019t ideal for a couple of reasons. This serif typeface has a standard set of text numerals. These dip below the baseline and are designed for using figures within text, not on their own. What you need to use is a typeface with lining numerals. These align to the baseline and are more legible when used for tables.\n\n\n\nSans serif typefaces generally have lining numerals. They are also arguably more legible when used in tables.\n\nGo easy on the background tones, unless you\u2019re giving reading direction visual emphasis \n\nWe\u2019ve all seen background tones on tables. They have their use, but my feeling is that use should be functional and not decorative.\n\nIf you have a table that is long, but only a few columns wide, then alternate row shading isn\u2019t that useful for showing the different lines of data. It\u2019s a common misconception that alternate row shading is to increase legibility on long tables. That\u2019s not the case. Shaded rows are to aid horizontal reading across multiple table columns. On wide tables they are incredibly useful for helping the reader find what they want.\n\n\n\nBackground tone can also be used to give emphasis to the reading direction. If we want to emphasis a column, that can be given a background tone.\n\n\n\nHierarchy\n\nAs I said earlier, people may be reading a table vertically, and horizontally in order to find what they want. Sometimes, especially if the table is complex, we need to give them a helping hand.\n\nVisually emphasising the hierarchy in tables can help the reader scan the data. Column headings are particularly important. Column headings are often what a reader will go to first, so we need to help them understand that the column headings are different to the stuff beneath them, and we also need to give them more visual importance. We can do this by making them bold, giving them ample negative space, or by including a thick rule above them. We can also give the row titles the same level of emphasis.\n\n\n\nIn addition to background tones, you can give emphasis to reading direction by typesetting those elements in bold. You shouldn\u2019t use italics\u2014with sans serif typefaces the difference is too subtle.\n\nSo, there you have it. A couple of simple guidelines to make your tables cleaner and more readable.", "year": "2007", "author": "Mark Boulton", "author_slug": "markboulton", "published": "2007-12-07T00:00:00+00:00", "url": "https://24ways.org/2007/typesetting-tables/", "topic": "design"} {"rowid": 149, "title": "Underpants Over My Trousers", "contents": "With Christmas approaching faster than a speeding bullet, this is the perfect time for you to think about that last minute present to buy for the web geek in your life. If you\u2019re stuck for ideas for that special someone, forget about that svelte iPhone case carved from solid mahogany and head instead to your nearest comic-book shop and pick up a selection of comics or graphic novels. (I\u2019ll be using some of my personal favourite comic books as examples throughout). \n\nTrust me, whether your nearest and dearest has been reading comics for a while or has never peered inside this four-colour world, they\u2019ll thank-you for it.\n\nAside from indulging their superhero fantasies, comic books can provide web designers with a rich vein of inspiring ideas and material to help them create shirt button popping, trouser bursting work for the web. I know from my own personal experience, that looking at aspects of comic book design, layout and conventions and thinking about the ways that they can inform web design has taken my design work in often-unexpected directions. \n\nThere are far too many fascinating facets of comic book design that provide web designers with inspiration to cover in the time that it takes to pull your underpants over your trousers. So I\u2019m going to concentrate on one muscle bound aspect of comic design, one that will make you think differently about how you lay out the content of your pages in panels. \n\nA suitcase full of Kryptonite\n\nNow, to the uninitiated onlooker, the panels of a comic book may appear to perform a similar function to still frames from a movie. But inside the pages of a comic, panels must work harder to help the reader understand the timing of a story. It is this method for conveying narrative timing to a reader that I believe can be highly useful to designers who work on the web as timing, drama and suspense are as important in the web world as they are in worlds occupied by costumed crime fighters and superheroes.\n\nI\u2019d like you to start by closing your eyes and thinking about your own process for laying out panels of content on a page. OK, you\u2019ll actually be better off with your eyes open if you\u2019re going to carry on reading.\n\nI\u2019ll bet you a suitcase full of Kryptonite that you often, if not always, structure your page layouts, and decide on the dimensions of those panels according to either:\n\n\n\tThe base grid that you are working to\n\tThe Golden Ratio or another mathematical schema\n\n\nMore likely, I bet that you decide on the size and the number of your panels based on the amount of content that will be going into them. From today, I\u2019d like you to think about taking a different approach. This approach not only addresses horizontal and vertical space, but also adds the dimension of time to your designs.\n\nSlowing down the action\n\nA comic book panel not only acts as a container for its content but also indicates to a reader how much time passes within the panel and as a result, how much time the reader should focus their attention on that one panel. \n\nSmaller panels create swift eye movement and shorter bursts of attention. Larger panels give the perception of more time elapsing in the story and subconsciously demands that a reader devotes more time to focus on it. \n\nConcrete by Paul Chadwick (Dark Horse Comics)\n\nThis use of panel dimensions to control timing can also be useful for web designers in designing the reading/user experience. Imagine a page full of information about a product or service. You\u2019ll naturally want the reader to focus for longer on the key benefits of your offering rather than perhaps its technical specifications.\n\nNow take a look at this spread of pages from Watchmen by Alan Moore and Dave Gibbons.\n\nWatchmen by Alan Moore and Dave Gibbons (Diamond Comic Distributors 2004)\n\nThroughout this series of (originally) twelve editions, artist Dave Gibbons stuck rigidly to his 3\u00d73 panels per page design and deviated from it only for dramatic moments within the narrative. \n\nIn particular during the last few pages of chapter eleven, Gibbons adds weight to the impending doom by slowing down the action by using larger panels and forces the reader to think longer about what was coming next. The action then speeds up through twelve smaller panels until the final panel: nothing more than white space and yet one of the most iconic and thought provoking in the entire twelve book series.\n\nWatchmen by Alan Moore and Dave Gibbons (Diamond Comic Distributors 2004)\n\nOn the web it is common for clients to ask designers to fill every pixel of screen space with content, perhaps not understanding the drama that can be added by nothing more than white space.\n\nIn the final chapter, Gibbons emphasises the carnage that has taken place (unseen between chapters eleven and twelve) by presenting the reader with six full pages containing only single, large panels. \n\nWatchmen by Alan Moore and Dave Gibbons (Diamond Comic Distributors 2004)\n\nThis drama, created by the artist\u2019s use of panel dimensions to control timing, is a technique that web designers can also usefully employ when emphasising important areas of content.\n\nThink back for a moment to the home page of Apple Inc., during the launch of their iconic iPhone, where the page contained nothing more than a large image and the phrase \u201cSay hello to iPhone\u201d. Rather than fill the page with sales messages, Apple\u2019s designers allowed the space itself to tell the story and created a real sense of suspense and expectation among their readers.\n\nBorders\n\nWhereas on the web, panel borders are commonly used to add emphasis to particular areas of content, in comic books they take on a different and sometimes opposite role. \n\nIn the examples so far, borders have contained all of the action. Removing a border can have the opposite effect to what you might at first think. Rather than taking emphasis away from their content, in comics, borderless panels allow the reader\u2019s eyes to linger for longer on the content adding even stronger emphasis.\n\nConcrete by Paul Chadwick (Dark Horse Comics)\n\nThis effect is amplified when the borderless content is allowed to bleed to the edges of a page. Because the content is no longer confined, except by the edges of the page (both comic and web) the reader\u2019s eye is left to wander out into open space. \n\nConcrete by Paul Chadwick (Dark Horse Comics)\n\nThis type of open, borderless content panel can be highly useful in placing emphasis on the most important content on a page in exactly the very opposite way that we commonly employ on the web today. \n\nSo why is time an important dimension to think about when designing your web pages? On one level, we are often already concerned with the short attention spans of visitors to our pages and should work hard to allow them to quickly and easily find and read the content that both they and we think is important. Learning lessons from comic book timing can only help us improve that experience.\n\nOn another: timing, suspense and drama are already everyday parts of the web browsing experience. Will a reader see what they expect when they click from one page to the next? Or are they in for a surprise? \n\nMost importantly, I believe that the web, like comics, is about story telling: often the story of the experiences that a customer will have when they use our product or service or interact with our organisation. It is this element of story telling than can be greatly improved by learning from comics.\n\nIt is exactly this kind of learning and adapting from older, more established and at first glance unrelated media that you will find can make a real distinctive difference to the design work that you create.\n\nFill your stockings\n\nIf you\u2019re a visual designer or developer and are not a regular reader of comics, from the moment that you pick up your first title, I know that you will find them inspiring. \n\nI will be writing more, and speaking about comic design applied to the web at several (to be announced) events this coming year. I hope you\u2019ll be slipping your underpants over your trousers and joining me then. In the meantime, here is some further reading to pick up on your next visit to a comic book or regular bookshop and slip into your stockings:\n\n\n\tComics and Sequential Art by Will Eisner (Northern Light Books 2001)\n\tUnderstanding Comics: The Invisible Art by Scott McCloud (Harper Collins 1994)\n\n\nHave a happy superhero season.\n\n(I would like to thank all of the talented artists, writers and publishers whose work I have used as examples in this article and the hundreds more who inspire me every day with their tall tales and talent.)", "year": "2007", "author": "Andy Clarke", "author_slug": "andyclarke", "published": "2007-12-14T00:00:00+00:00", "url": "https://24ways.org/2007/underpants-over-my-trousers/", "topic": "design"} {"rowid": 150, "title": "A Gift Idea For Your Users: Respect, Yo", "contents": "If, indeed, it is the thought that counts, maybe we should pledge to make more thoughtful design decisions. In addition to wowing people who use the Web sites we build with novel features, nuanced aesthetics and the new new thing, maybe we should also thread some subtle things throughout our work that let folks know: hey, I\u2019m feeling ya. We\u2019re simpatico. I hear you loud and clear.\n\nIt\u2019s not just holiday spirit that moves me to talk this way. As good as people are, we need more than the horizon of karma to overcome that invisible demon, inertia. Makers of the Web, respectful design practices aren\u2019t just the right thing, they are good for business. Even if your site is the one and only place to get experience x, y or zed, you don\u2019t rub someone\u2019s face in it. You keep it free flowing, you honor the possible back and forth of a healthy transaction, you are Johnny Appleseed with the humane design cues. You make it clear that you are in it for the long haul.\n\nA peek back:\n\n\n\nThink back to what search (and strategy) was like before Google launched a super clean page with \u201cI\u2019m Feeling Lucky\u201d button. Aggregation was the order of the day (just go back and review all the \u2018strategic alliances\u2019 that were announced daily.) Yet the GOOG comes along with this zen layout (nope, we\u2019re not going to try to make you look at one of our media properties) and a bold, brash, teleport-me-straight-to-the-first-search-result button. It could have been titled \u201cWe\u2019re Feeling Cocky\u201d. These were radical design decisions that reset how people thought about search services. Oh, you mean I can just find what I want and get on with it?\n\nIt\u2019s maybe even more impressive today, after the GOOG has figured out how to monetize attention better than anyone. \u201cI\u2019m Feeling Lucky\u201d is still there. No doubt, it costs the company millions. But by leaving a little money on the table, they keep the basic bargain they started to strike in 1997. We\u2019re going to get you where you want to go as quickly as possible.\n\nWhere are the places we might make the same kind of impact in our work? Here are a few ideas:\n\nRespect People\u2019s Time\n\nAs more services become more integrated with our lives, this will only become more important. How can you make it clear that you respect the time a user has granted you?\n\nUser-Oriented Defaults\n\nDefault design may be the psionic tool in your belt. Unseen, yet pow-er-ful. Look at your defaults. Who are they set up to benefit? Are you depending on users not checking off boxes so you can feel ok about sending them email they really don\u2019t want? Are you depending on users not checking off boxes so you tilt privacy values in ways most beneficial for your SERPs? Are you making it a little too easy for 3rd party applications to run buckwild through your system?\n\nThere\u2019s being right and then there\u2019s being awesome. Design to the spirit of the agreement and not the letter.\n\nSee this?\n\n\n\nMake sure that\u2019s really the experience you think people want. Whenever I see a service that defaults to not opting me in their newsletter just because I bought a t shirt from them, you can be sure that I trust them that much more. And they are likely to see me again.\n\nReduce, Reuse\n\nIt\u2019s likely that people using your service will have data and profile credentials elsewhere. You should really think hard about how you can let them repurpose some of that work within your system. Can you let them reduce the number of logins/passwords they have to manage by supporting OpenID? Can you let them reuse profile information from another service by slurping in (or even subscribing) to hCards? Can you give them a leg up by reusing a friends list they make available to you? (Note: please avoid the anti-pattern of inviting your user to upload all her credential data from 3rd party sites into your system.)\n\nThis is a much larger issue, and if you\u2019d like to get involved, have a look at the wiki, and dive in.\n\nMake it simple to leave\n\nOh, this drives me bonkers. Again, the more simple you make it to increase or decrease involvement in your site, or to just opt-out altogether, the better. This example from Basecamp is instructive:\n\n\n\nAt a glance, I can see what the implications are of choosing a different type of account. I can also move between account levels with one click. Finally, I can cancel the service easily. No hoop jumping. Also, it should be simple for users to take data with them or delete it.\n\nLet Them Have Fun\n\nDon\u2019t overlook opportunities for pleasure. Even the most mundane tasks can be made more enjoyable. Check out one of my favorite pieces of interaction design from this past year:\n\n\n\nHoly knob fiddling, Batman! What a great way to get people to play with preference settings: an equalizer metaphor. Those of a certain age will recall how fun it was to make patterns with your uncle\u2019s stereo EQ. I think this is a delightful way to encourage people to optimize their own experience of the news feed feature. Given the killer nature of this feature, it was important for Facebook to make it easy to fine tune.\n\nI\u2019d also point you to Flickr\u2019s Talk Like A Pirate Day Easter egg as another example of design that delights. What a huge amount of work for a one-off, totally optional way to experience the site. And what fun. And how true to its brand persona. Brill.\n\nAnti-hype\n\nDon\u2019t talk so much. Rather, ship and sample. Release code, tell the right users. See what happens. Make changes. Extend the circle a bit by showing some other folks. Repeat.\n\nThe more you hype coming features, the more you talk about what isn\u2019t yet, the more you build unrealistic expectations. Your genius can\u2019t possibly match our collective dreaming. Disappointment is inevitable. Yet, if you craft the right melody and make it simple for people to hum your tune, it will spread. Give it time. Listen.\n\nSpeak the Language of the Tribe\n\nIt\u2019s respectful to speak in a human way. Not that you have to get all zOMGWTFBBQ!!1 in your messaging. People respond when you speak to them in a way that sounds natural. Natural will, of course, vary according to context. Again, listen in and people will signal the speech that works in that group for those tasks. Reveal those cues in your interface work and you\u2019ll have powerful proof that actual people are working on your Web site.\n\nThis example of Pownce\u2018s gender selector is the kind of thing I\u2019m talking about:\n\n\n\nNow, this doesn\u2019t mean you should mimic the lingo on some cool kidz site. Your service doesn\u2019t need to have a massage when it\u2019s down. Think about what works for you and your tribe. Excellent advice here from Feedburner\u2019s Dick Costolo on finding a voice for your service. Also, Mule Design\u2019s Erika Hall has an excellent talk on improving your word fu.\n\nPass the mic, yo\n\nHere is a crazy idea: you could ask your users what they want. Maybe you could even use this input to figure out what they really want. Tools abound. Comments, wikis, forums, surveys. Embed the sexy new Get Satisfaction widget and have a dynamic FAQ running.\n\nThe point is that you make it clear to people that they have a means of shaping the service with you. And you must showcase in some way that you are listening, evaluating and taking action against some of that user input.\n\nYou get my drift. There are any number of ways we can show respect to those who gift us with their time, data, feedback, attention, evangelism, money. Big things are in the offing. I can feel the love already.", "year": "2007", "author": "Brian Oberkirch", "author_slug": "brianoberkirch", "published": "2007-12-23T00:00:00+00:00", "url": "https://24ways.org/2007/a-gift-idea-for-your-users-respect-yo/", "topic": "ux"} {"rowid": 151, "title": "Get In Shape", "contents": "Pop quiz: what\u2019s wrong with the following navigation?\n\n\n\nMaybe nothing. But then again, maybe there\u2019s something bugging you about the way it comes together, something you can\u2019t quite put your finger on. It seems well-designed, but it also seems a little\u2026 off.\n\nThe design decisions that led to this eventual form were no doubt well-considered:\n\n\n\tClient: The top level needs to have a \u201ccurrent page\u201d status indicator of some sort.\n\tDesigner: How about a white tab?\n\tClient: Great! The second level needs to show up underneath the first level though\u2026\n\tDesigner: Okay, but that white tab I just added makes it hard to visually connect the bottom nav to the top.\n\tClient: Too late, we\u2019ve seen the white tab and we love it. Try and make it work.\n\tDesigner: Right. So I placed the second level in its own box.\n\tClient: Hmm. They seem too separated. I can\u2019t tell that the yellow nav is the second level of the first.\n\tDesigner: How about an indicator arrow?\n\tClient: Brilliant!\n\n\nThe problem is that the end result feels awkward and forced. During the design process, little decisions were made that ultimately affect the overall shape of the navigation. What started out as a neatly contained rounded rectangle ended up as an ambiguous double shape that looks funny, though it\u2019s often hard to pinpoint precisely why.\n\nThe Shape of Things\n\nWell the why in this case is because seemingly unrelated elements in a design still end up visually interacting. Adding a new item to a page impacts everything surrounding it. In this navigation example, we\u2019re looking at two individual objects that are close enough to each other that they form a relationship; if we reduce them to strictly their outlines, it\u2019s a little easier to see that this particular combination registers oddly.\n\n\n\nThe two shapes float with nothing really grounding them. If they were connected, perhaps it would be a different story. The white tab divides the top shape in half, leaving a gap in the middle of it. There\u2019s very little balance in this pairing because the overall shape of the navigation wasn\u2019t considered during the design process.\n\nHere\u2019s another example: Gmail. Great email client, but did you ever closely look at what\u2019s going on in that left hand navigation? The continuous blue bar around the message area spills out into the navigation. If we remove all text, we\u2019re left with this odd configuration:\n\n\n\nThough the reasoning for anchoring the navigation highlight against the message area might be sound, the result is an irregular shape that doesn\u2019t correspond with anything in reality. You may never consciously notice it, but once you do it\u2019s hard to miss. One other example courtesy of last.fm:\n\n\n\nThe two header areas are the same shade of pink so they appear to be closely connected. When reduced to their outlines it\u2019s easy to see that this combination is off-balance: the edges don\u2019t align, the sharp corners of the top shape aren\u2019t consistent with the rounded corners of the bottom, and the part jutting out on the right of the bottom one seems fairly random. The result is a duo of oddly mis-matched shapes.\n\nDesign Strategies\n\nOur minds tend to pick out familiar patterns. A clever designer can exploit this by creating references in his or her work to shapes and combinations with which viewers are already familiar. There are a few simple ideas that can be employed to help you achieve this: consistency, balance, and completion.\n\nConsistency\n\nA fairly simple way to unify the various disparate shapes on a page is by designing them with a certain amount of internal consistency. You don\u2019t need to apply an identical size, colour, border, or corner treatment to every single shape; devolving a design into boring repetition isn\u2019t what we\u2019re after here. But it certainly doesn\u2019t hurt to apply a set of common rules to most shapes within your work.\n\n\n\nConsider purevolume and its multiple rounded-corner panels. From the bottom of the site\u2019s main navigation to the grey \u201cExtras\u201d panels halfway down the page (shown above), multiple shapes use a common border radius for unity. Different colours, different sizes, different content, but the consistent outlines create a strong sense of similarity. Not that every shape on the site follows this rule; they break the pattern right at the top with a darker sharp-cornered header, and again with the thumbnails below. But the design remains unified, nonetheless.\n\nBalance\n\nArguably the biggest problem with the last.fm example earlier is one of balance. The area poking out of the bottom shape created a fairly obvious imbalance for no apparent reason. The right hand side is visually emphasized due to the greater area of pink coverage, but with the white gap left beside it, the emphasis seems unwarranted. It\u2019s possible to create tension in your design by mismatching shapes and throwing off the balance, but when that happens unintentionally it can look like a mistake.\n\n\n\nAbove are a few examples of design elements in balanced and unbalanced configurations. The examples in the top row are undeniably more pleasing to the eye than those in the bottom row. If these were fleshed out into full designs, those derived from the templates in the top row would naturally result in stronger work.\n\nTake a look at the header on 9Rules for a study in well-considered balance. On the left you\u2019ll see a couple of paragraphs of text, on the right you have floating navigational items, and both flank the site\u2019s logo. This unusual layout combines multiple design elements that look nothing alike, and places them together in a way that anchors each so that no one weighs down the header.\n\nCompletion\n\nAnd finally we come to the idea of completion. Shapes don\u2019t necessarily need hard outlines to be read visually as shapes, which can be exploited for various purposes. Notice how Zend\u2019s mid-page \u201cBusiness Topics\u201d and \u201cNews\u201d items (below) fade out to the right and bottom, but the placement of two of these side-by-side creates an impression of two panels rather than three disparate floating columns. By allowing the viewer\u2019s eye to complete the shapes, they\u2019ve lightened up the design of the page and removed inessential lines. In a busy design this technique could prove quite handy.\n\n\n\nAlong the same lines, the individual shapes within your design may also be combined visually to form outlines of larger shapes. The differently-coloured header and main content/sidebar shapes on Veerle\u2019s blog come together to form a single central panel, further emphasized by the slight drop shadow to the right.\n\nImplementation\n\nStudying how shape can be used effectively in design is simply a starting point. As with all things design-related, there are no hard and fast rules here; ultimately you may choose to bring these principles into your work more often, or break them for effect. But understanding how shapes interact within a page, and how that effect is ultimately perceived by viewers, is a key design principle you can use to impress your friends.", "year": "2007", "author": "Dave Shea", "author_slug": "daveshea", "published": "2007-12-16T00:00:00+00:00", "url": "https://24ways.org/2007/get-in-shape/", "topic": "design"} {"rowid": 152, "title": "CSS for Accessibility", "contents": "CSS is magical stuff. In the right hands, it can transform the plainest of (well-structured) documents into a visual feast. But it\u2019s not all fur coat and nae knickers (as my granny used to say). Here are some simple ways you can use CSS to improve the usability and accessibility of your site. \n\nEven better, no sexy visuals will be harmed by the use of these techniques. Promise.\n\nNae knickers\n\nThis is less of an accessibility tip, and more of a reminder to check that you\u2019ve got your body background colour specified.\n\nIf you\u2019re sitting there wondering why I\u2019m mentioning this, because it\u2019s a really basic thing, then you might be as surprised as I was to discover that from a sample of over 200 sites checked last year, 35% of UK local authority websites were missing their body background colour.\n\nForgetting to specify your body background colour can lead to embarrassing gaps in coverage, which are not only unsightly, but can prevent your users reading the text on your site if they use a different operating system colour scheme.\n\nAll it needs is the following line to be added to your CSS file:\n\nbody {background-color: #fff;}\n\nIf you pair it with \n\ncolor: #000;\n\n\u2026 you\u2019ll be assured of maintaining contrast for any areas you inadvertently forget to specify, no matter what colour scheme your user needs or prefers.\n\nEven better, if you\u2019ve got standard reset CSS you use, make sure that default colours for background and text are specified in it, so you\u2019ll never be caught with your pants down. At the very least, you\u2019ll have a white background and black text that\u2019ll prompt you to change them to your chosen colours.\n\nElbow room\n\nPaying attention to your typography is important, but it\u2019s not just about making it look nice. \n\nCareful use of the line-height property can make your text more readable, which helps everyone, but is particularly helpful for those with dyslexia, who use screen magnification or simply find it uncomfortable to read lots of text online. \n\nWhen lines of text are too close together, it can cause the eye to skip down lines when reading, making it difficult to keep track of what you\u2019re reading across. \n\nSo, a bit of room is good.\n\nThat said, when lines of text are too far apart, it can be just as bad, because the eye has to jump to find the next line. That not only breaks up the reading rhythm, but can make it much more difficult for those using Screen Magnification (especially at high levels of magnification) to find the beginning of the next line which follows on from the end of the line they\u2019ve just read.\n\nUsing a line height of between 1.2 and 1.6 times normal can improve readability, and using unit-less line heights help take care of any pesky browser calculation problems.\n\nFor example: \n\np {\n\tfont-family: \"Lucida Grande\", Lucida, Verdana, Helvetica, sans-serif;\n\tfont-size: 1em;\n\tline-height: 1.3;\n}\n\nor if you want to use the shorthand version:\n\np {\n\tfont: 1em/1.3 \"Lucida Grande\", Lucida, Verdana, Helvetica, sans-serif;\n}\n\nView some examples of different line-heights, based on default text size of 100%/1em.\n\nFurther reading on Unitless line-heights from Eric Meyer.\n\nTransformers: Initial case in disguise\n\nNobody wants to shout at their users, but there are some occasions when you might legitimately want to use uppercase on your site.\n\nAvoid screen-reader pronunciation weirdness (where, for example, CONTACT US would be read out as Contact U S, which is not the same thing \u2013 unless you really are offering your users the chance to contact the United States) caused by using uppercase by using title case for your text and using the often neglected text-transform property to fake uppercase.\n\nFor example:\n\n.uppercase {\n\ttext-transform: uppercase\n} \n\nDon\u2019t overdo it though, as uppercase text is harder to read than normal text, not to mention the whole SHOUTING thing.\n\nLinky love\n\nWhen it comes to accessibility, keyboard only users (which includes those who use voice recognition software) who can see just fine are often forgotten about in favour of screen reader users.\n\nThis Christmas, share the accessibility love and light up those links so all of your users can easily find their way around your site.\n\nThe link outline\n\nAKA: the focus ring, or that dotted box that goes around links to show users where they are on the site.\n\nThe techniques below are intended to supplement this, not take the place of it. You may think it\u2019s ugly and want to get rid of it, especially since you\u2019re going to the effort of tarting up your links.\n\nDon\u2019t. \n\nJust don\u2019t.\n\nThe non-underlined underline\n\nIf you listen to Jacob Nielsen, every link on your site should be underlined so users know it\u2019s a link.\n\nYou might disagree with him on this (I know I do), but if you are choosing to go with underlined links, in whatever state, then remove the default underline and replacing it with a border that\u2019s a couple of pixels away from the text. \n\nThe underline is still there, but it\u2019s no longer cutting off the bottom of letters with descenders (e.g., g and y) which makes it easier to read.\n\nThis is illustrated in Examples 1 and 2.\n\nYou can modify the three lines of code below to suit your own colour and border style preferences, and add it to whichever link state you like.\n\ntext-decoration: none;\nborder-bottom: 1px #000 solid;\npadding-bottom: 2px;\n\nStanding out from the crowd\n\nWhatever way you choose to do it, you should be making sure your links stand out from the crowd of normal text which surrounds them when in their default state, and especially in their hover or focus states.\n\nA good way of doing this is to reverse the colours when on hover or focus.\n\nWell-focused\n\nEveryone knows that you can use the :hover pseudo class to change the look of a link when you mouse over it, but, somewhat ironically, people who can see and use a mouse are the group who least need this extra visual clue, since the cursor handily (sorry) changes from an arrow to a hand.\n\nSo spare a thought for the non-pointing device users that visit your site and take the time to duplicate that hover look by using the :focus pseudo class.\n\nOf course, the internets being what they are, it\u2019s not quite that simple, and predictably, Internet Explorer is the culprit once more with it\u2019s frustrating lack of support for :focus. Instead it applies the :active pseudo class whenever an anchor has focus.\n\nWhat this means in practice is that if you want to make your links change on focus as well as on hover, you need to specify focus, hover and active.\n\nEven better, since the look and feel necessarily has to be the same for the last three states, you can combine them into one rule.\n\nSo if you wanted to do a simple reverse of colours for a link, and put it together with the non-underline underlines from before, the code might look like this:\n\na:link {\n\tbackground: #fff;\n\tcolor: #000;\n\tfont-weight: bold;\n\ttext-decoration: none; \n\tborder-bottom: 1px #000 solid; \n\tpadding-bottom: 2px;\n}\na:visited {\n\tbackground: #fff;\n\tcolor: #800080;\n\tfont-weight: bold;\n\ttext-decoration: none; \n\tborder-bottom: 1px #000 solid; \n\tpadding-bottom: 2px;\n}\na:focus, a:hover, a:active {\n\tbackground: #000;\n\tcolor: #fff;\n\tfont-weight: bold;\n\ttext-decoration: none; \n\tborder-bottom: 1px #000 solid; \n\tpadding-bottom: 2px;\n}\n\nExample 3 shows what this looks like in practice.\n\nLocation, Location, Location\n\nTo take this example to it\u2019s natural conclusion, you can add an id of current (or something similar) in appropriate places in your navigation, specify a full set of link styles for current, and have a navigation which, at a glance, lets users know which page or section they\u2019re currently in.\n\nExample navigation using location indicators.\n\nand the source code\n\nConclusion\n\nAll the examples here are intended to illustrate the concepts, and should not be taken as the absolute best way to format links or style navigation bars \u2013 that\u2019s up to you and whatever visual design you\u2019re using at the time.\n\nThey\u2019re also not the only things you should be doing to make your site accessible. \n\nAbove all, remember that accessibility is for life, not just for Christmas.", "year": "2007", "author": "Ann McMeekin", "author_slug": "annmcmeekin", "published": "2007-12-13T00:00:00+00:00", "url": "https://24ways.org/2007/css-for-accessibility/", "topic": "design"} {"rowid": 153, "title": "JavaScript Internationalisation", "contents": "or: Why Rudolph Is More Than Just a Shiny Nose\n\nDunder sat, glumly staring at the computer screen.\n\n\u201cWhat\u2019s up, Dunder?\u201d asked Rudolph, entering the stable and shaking off the snow from his antlers.\n\n\u201cWell,\u201d Dunder replied, \u201cI\u2019ve just finished coding the new reindeer intranet Santa Claus asked me to do. You know how he likes to appear to be at the cutting edge, talking incessantly about Web 2.0, AJAX, rounded corners; he even spooked Comet recently by talking about him as if he were some pushy web server.\n\n\u201cI\u2019ve managed to keep him happy, whilst also keeping it usable, accessible, and gleaming \u2014 and I\u2019m still on the back row of the sleigh! But anyway, given the elves will be the ones using the site, and they come from all over the world, the site is in multiple languages. Which is great, except when it comes to the preview JavaScript I\u2019ve written for the reindeer order form. Here, have a look\u2026\u201d\n\nAs he said that, he brought up the textileRef:8234272265470b85d91702:linkStartMarker:\u201corder\n form in French\u201d:/examples/javascript-internationalisation/initial.fr.html on the screen. (Same in English).\n\n\u201cLooks good,\u201d said Rudolph.\n\n\u201cBut if I add some items,\u201d said Dunder, \u201cthe preview appears in English, as it\u2019s hard-coded in the JavaScript. I don\u2019t want separate code for each language, as that\u2019s just silly \u2014 I thought about just having if statements, but that doesn\u2019t scale at all\u2026\u201d\n\n\u201cAnd there\u2019s more, you aren\u2019t displaying large numbers in French properly, either,\u201d added Rudolph, who had been playing and looking at part of the source code:\n\nfunction update_text() {\n\tvar hay = getValue('hay');\n\tvar carrots = getValue('carrots');\n\tvar bells = getValue('bells');\n\tvar total = 50 * bells + 30 * hay + 10 * carrots;\n\tvar out = 'You are ordering '\n\t\t+ pretty_num(hay) + ' bushel' + pluralise(hay) + ' of hay, '\n\t\t+ pretty_num(carrots) + ' carrot' + pluralise(carrots)\n\t\t+ ', and ' + pretty_num(bells) + ' shiny bell' + pluralise(bells)\n\t\t+ ', at a total cost of ' + pretty_num(total)\n\t\t+ ' gold pieces. Thank you.';\n\tdocument.getElementById('preview').innerHTML = out;\n}\nfunction pretty_num(n) {\n\tn += '';\n\tvar o = '';\n\tfor (i=n.length; i>3; i-=3) {\n\t\to = ',' + n.slice(i-3, i) + o;\n\t}\n\to = n.slice(0, i) + o;\n\treturn o;\n}\nfunction pluralise(n) {\n\tif (n!=1) return 's';\n\treturn '';\n}\n\n\u201cOh, botheration!\u201d cried Dunder. \u201cThis is just so complicated.\u201d\n\n\u201cIt doesn\u2019t have to be,\u201d said Rudolph, \u201cyou just have to think about things in a slightly different way from what you\u2019re used to. As we\u2019re only a simple example, we won\u2019t be able to cover all possibilities, but for starters, we need some way of providing different information to the script dependent on the language. We\u2019ll create a global i18n object, say, and fill it with the correct language information. The first variable we\u2019ll need will be a thousands separator, and then we can change the pretty_num function to use that instead:\n\nfunction pretty_num(n) {\n\tn += '';\n\tvar o = '';\n\tfor (i=n.length; i>3; i-=3) {\n\t\to = i18n.thousands_sep + n.slice(i-3, i) + o;\n\t}\n\to = n.slice(0, i) + o;\n\treturn o;\n}\n\n\u201cThe i18n object will also contain our translations, which we will access through a function called _() \u2014 that\u2019s just an underscore. Other languages have a function of the same name doing the same thing. It\u2019s very simple:\n\nfunction _(s) {\n\tif (typeof(i18n)!='undefined' && i18n[s]) {\n\t\treturn i18n[s];\n\t}\n\treturn s;\n}\n\n\u201cSo if a translation is available and provided, we\u2019ll use that; otherwise we\u2019ll default to the string provided \u2014 which is helpful if the translation begins to lag behind the site\u2019s text at all, as at least something will be output.\u201d\n\n\u201cGot it,\u201d said Dunder. \u201c _('Hello Dunder') will print the translation of that string, if one exists, \u2018Hello Dunder\u2019 if not.\u201d\n\n\u201cExactly. Moving on, your plural function breaks even in English if we have a word where the plural doesn\u2019t add an s \u2014 like \u2018children\u2019.\u201d\n\n\u201cYou\u2019re right,\u201d said Dunder. \u201cHow did I miss that?\u201d\n\n\u201cNo harm done. Better to provide both singular and plural words to the function and let it decide which to use, performing any translation as well:\n\nfunction pluralise(s, p, n) {\n\tif (n != 1) return _(p);\n\treturn _(s);\n}\n\n\u201cWe\u2019d have to provide different functions for different languages as we employed more elves and got more complicated \u2014 for example, in Polish, the word \u2018file\u2019 pluralises like this: 1 plik, 2-4 pliki, 5-21 plik\u00f3w, 22-24 pliki, 25-31 plik\u00f3w, and so on.\u201d (More information on plural forms)\n\n\u201cGosh!\u201d\n\n\u201cNext, as different languages have different word orders, we must stop using concatenation to construct sentences, as it would be impossible for other languages to fit in; we have to keep coherent strings together. Let\u2019s rewrite your update function, and then go through it:\n\nfunction update_text() {\n\tvar hay = getValue('hay');\n\tvar carrots = getValue('carrots');\n\tvar bells = getValue('bells');\n\tvar total = 50 * bells + 30 * hay + 10 * carrots;\n\thay = sprintf(pluralise('%s bushel of hay', '%s bushels of hay', hay), pretty_num(hay));\n\tcarrots = sprintf(pluralise('%s carrot', '%s carrots', carrots), pretty_num(carrots));\n\tbells = sprintf(pluralise('%s shiny bell', '%s shiny bells', bells), pretty_num(bells));\n\tvar list = sprintf(_('%s, %s, and %s'), hay, carrots, bells);\n\tvar out = sprintf(_('You are ordering %s, at a total cost of %s gold pieces.'),\n\t\tlist, pretty_num(total));\n\tout += ' ';\n\tout += _('Thank you.');\n\tdocument.getElementById('preview').innerHTML = out;\n}\n\n\u201c sprintf is a function in many other languages that, given a format string and some variables, slots the variables into place within the string. JavaScript doesn\u2019t have such a function, so we\u2019ll write our own. Again, keep it simple for now, only integers and strings; I\u2019m sure more complete ones can be found on the internet.\n\nfunction sprintf(s) {\n\tvar bits = s.split('%');\n\tvar out = bits[0];\n\tvar re = /^([ds])(.*)$/;\n\tfor (var i=1; i%s
      gold pieces.\": '',\n\t\"Thank you.\": ''\n};\n\n\u201cIf you implement this across the intranet, you\u2019ll want to investigate the xgettext program, which can automatically extract all strings that need translating from all sorts of code files into a standard .po file (I think Python mode works best for JavaScript). You can then use a different program to take the translated .po file and automatically create the language-specific JavaScript files for us.\u201d (e.g. German .po file for PledgeBank, mySociety\u2019s .po-.js script, example output)\n\nWith a flourish, Rudolph finished editing. \u201cAnd there we go, localised JavaScript in English, French, or German, all using the same main code.\u201d\n\n\u201cThanks so much, Rudolph!\u201d said Dunder.\n\n\u201cI\u2019m not just a pretty nose!\u201d Rudolph quipped. \u201cOh, and one last thing \u2014 please comment liberally explaining the context of strings you use. Your translator will thank you, probably at the same time as they point out the four hundred places you\u2019ve done something in code that only works in your language and no-one else\u2019s\u2026\u201d\n\nThanks to Tim Morley and Edmund Grimley Evans for the French and German translations respectively.", "year": "2007", "author": "Matthew Somerville", "author_slug": "matthewsomerville", "published": "2007-12-08T00:00:00+00:00", "url": "https://24ways.org/2007/javascript-internationalisation/", "topic": "code"} {"rowid": 154, "title": "Diagnostic Styling", "contents": "We\u2019re all used to using CSS to make our designs live and breathe, but there\u2019s another way to use CSS: to find out where our markup might be choking on missing accessibility features, targetless links, and just plain missing content. \n\nNote: the techniques discussed here mostly work in Firefox, Safari, and Opera, but not Internet Explorer. I\u2019ll explain why that\u2019s not really a problem near the end of the article \u2014 and no, the reason is not \u201ceveryone should just ignore IE anyway\u201d.\n\nBasic Diagnostics\n\nTo pick a simple example, suppose you want to call out all holdover font and center elements in a site. Simple: you just add the following to your styles.\n\nfont, center {outline: 5px solid red;}\n\nYou could take it further and add in a nice lime background or some such, but big thick red outlines should suffice. Now you\u2019ll be able to see the offenders wherever as you move through the site. (Of course, if you do this on your public server, everyone else will see the outlines too. So this is probably best done on a development server or local copy of the site.)\n\nNot everyone may be familiar with outlines, which were introduced in CSS2, so a word on those before we move on. Outlines are much like borders, except outlines don\u2019t affect layout. Eh? Here\u2019s a comparison.\n\n\n\nOn the left, you have a border. On the right, an outline. The border takes up layout space, pushing other content around and generally being a nuisance. The outline, on the other hand, just draws into quietly into place. In most current browsers, it will overdraw any content already onscreen, and will be overdrawn by any content placed later \u2014 which is why it overlaps the images above it, and is overlapped by those below it.\n\nOkay, so we can outline deprecated elements like font and center. Is that all? Oh no.\n\nAttribution\n\nLet\u2019s suppose you also want to find any instances of inline style \u2014 that is, use of the style attribute on elements in the markup. This is generally discouraged (outside of HTML e-mails, which I\u2019m not going to get anywhere near), as it\u2019s just another side of the same coin of using font: baking the presentation into the document structure instead of putting it somewhere more manageable. So:\n\n*[style], font, center {outline: 5px solid red;}\n\nAdding that attribute selector to the rule\u2019s grouped selector means that we\u2019ll now be outlining any element with a style attribute.\n\nThere\u2019s a lot more that attribute selectors will let use diagnose. For example, we can highlight any images that have empty alt or title text.\n\nimg[alt=\"\"] {border: 3px dotted red;}\nimg[title=\"\"] {outline: 3px dotted fuchsia;}\n\nNow, you may wonder why one of these rules calls for a border, and the other for an outline. That\u2019s because I want them to \u201cadd together\u201d \u2014 that is, if I have an image which possesses both alt and title, and the values of both are empty, then I want it to be doubly marked.\n\n\n\nSee how the middle image there has both red and fuchsia dots running around it? (And am I the only one who sorely misses the actual circular dots drawn by IE5/Mac?) That\u2019s due to its markup, which we can see here in a fragment showing the whole table row.\n\n\nempty title\n\n\"\"\n\"comical\"\n\n\nRight, that\u2019s all well and good, but it misses a rather more serious situation: the selector img[alt=\"\"] won\u2019t match an img element that doesn\u2019t even have an alt attribute. How to tackle this problem?\n\nNot a Problem\n\nWell, if you want to select something based on a negative, you need a negative selector.\n\nimg:not([alt]) {border: 5px solid red;}\n\nThis is really quite a break from the rest of CSS selection, which is all positive: \u201cselect anything that has these characteristics\u201d. With :not(), we have the ability to say (in supporting browsers) \u201cselect anything that hasn\u2019t these characteristics\u201d. In the above example, only img elements that do not have an alt attribute will be selected. So we expand our list of image-related rules to read:\n\nimg[alt=\"\"] {border: 3px dotted red;}\nimg[title=\"\"] {outline: 3px dotted fuchsia;}\nimg:not([alt]) {border: 5px solid red;}\nimg:not([title]) {outline: 5px solid fuchsia;}\n\nWith the following results:\n\n\n\nWe could expand this general idea to pick up tables who lack a summary, or have an empty summary attribute.\n\ntable[summary=\"\"] {outline: 3px dotted red;}\ntable:not([summary]) {outline: 5px solid red;}\n\nWhen it comes to selecting header cells that lack the proper scope, however, we have a trickier situation. Finding headers with no scope attribute is easy enough, but what about those that have a scope attribute with an incorrect value?\n\nIn this case, we actually need to pull an on-off maneuver. This has us setting all th elements to have a highlight style, and then turn it off for the elements that meet our criteria.\n\nth {border: 2px solid red;}\nth[scope=\"col\"], th[scope=\"row\"] {border: none;}\n\nThis was necessary because of the way CSS selectors work. For example, consider this:\n\nth:not([scope=\"col\"]), th:not([scope=\"row\"]) {border: 2px solid red;}\n\nThat would select\u2026all th elements, regardless of their attrributes. That\u2019s because every th element doesn\u2019t have a scope of col, doesn\u2019t have a scope of row, or doesn\u2019t have either. There\u2019s no escaping this selector o\u2019 doom!\n\nThis limitation arises because :not() is limited to containing a single \u201cthing\u201d within its parentheses. You can\u2019t, for example, say \u201cselect all elements except those that are images which descend from list items\u201d. Reportedly, this limitation was imposed to make browser implementation of :not() easier.\n\nStill, we can make good use of :not() in the service of further diagnosing. Calling out links in trouble is a breeze:\n\na[href]:not([title]) {border: 5px solid red;}\na[title=\"\"] {outline: 3px dotted red;}\na[href=\"#\"] {background: lime;}\na[href=\"\"] {background: fuchsia;}\n\n\n\nHere we have a set that will call our attention to links missing title information, as well as links that have no valid target, whether through a missing URL or a JavaScript-driven page where there are no link fallbacks in the case of missing or disabled JavaScript (href=\"#\").\n\nAnd What About IE?\n\nAs I said at the beginning, much of what I covered here doesn\u2019t work in Internet Explorer, most particularly :not() and outline. (Oh, so basically everything? -Ed.)\n\nI can\u2019t do much about the latter. For the former, however, it\u2019s possible to hack your way around the problem by doing some layered on-off stuff. For example, for images, you replace the previously-shown rules with the following:\n\nimg {border: 5px solid red;}\nimg[alt][title] {border-width: 0;}\nimg[alt] {border-color: fuchsia;}\nimg[alt], img[title] {border-style: double;}\nimg[alt=\"\"][title],\nimg[alt][title=\"\"] {border-width: 3px;}\nimg[alt=\"\"][title=\"\"] {border-style: dotted;}\n\nIt won\u2019t have exactly the same set of effects, given the inability to use both borders and outlines, but will still highlight troublesome images.\n\n\n\nIt\u2019s also the case that IE6 and earlier lack support for even attribute selectors, whereas IE7 added pretty much all the attribute selector types there are, so the previous code block won\u2019t have any effect previous to IE7.\n\nIn a broader sense, though, these kinds of styles probably aren\u2019t going to be used in the wild, as it were. Diagnostic styles are something only you see as you work on a site, so you can make sure to use a browser that supports outlines and :not() when you\u2019re diagnosing. The fact that IE users won\u2019t see these styles is irrelevant since users of any browser probably won\u2019t be seeing these styles.\n\nPersonally, I always develop in Firefox anyway, thanks to its ability to become a full-featured IDE through the addition of extensions like Firebug and the Web Developer Toolbar.\n\n\nYeah, About That\u2026\n\nIt\u2019s true that much of what I describe in this article is available in the WDT. I feel there are two advantages to writing your own set of diagnostic styles.\n\n\n\tWhen you write your own styles, you can define exactly what the visual results will be, and how they will interact. The WDT doesn\u2019t let you make its outlines thicker or change their colors.\n\tYou can combine a bunch of diagnostics into a single set of rules and add it to your site\u2019s style sheet during the diagnostic portion, thus ensuring they persist as you surf around. This can be done in the WDT, but it isn\u2019t as easy (and, at least for me, not as reliable).\n\n\nIt\u2019s also true that a markup validator will catch many of the errors I mentioned, such as missing alt and summary attributes. For some, that\u2019s sufficient. But it won\u2019t catch everything diagnostic styles can, like empty alt values or untargeted links, which are perfectly valid, syntactically speaking.\n\n\nDiagnosis Complete?\n\nI hope this has been a fun look at the concept of diagnostic styling as well as a quick introduction into possibly new concepts like :not() and outlines. This isn\u2019t all there is to say, of course: there is plenty more that could be added to a diagnostic style sheet. And everyone\u2019s diagnostics will be different, tuned to meet each person\u2019s unique situation.\n\nMostly, though, I hope this small exploration triggers some creative thinking about the use of CSS to do more than just lay out pages and colorize text. Given the familiarity we acquire with CSS, it only makes sense to use it wherever it might be useful, and setting up visible diagnostic flags is just one more place for it to help us.", "year": "2007", "author": "Eric Meyer", "author_slug": "ericmeyer", "published": "2007-12-20T00:00:00+00:00", "url": "https://24ways.org/2007/diagnostic-styling/", "topic": "process"} {"rowid": 155, "title": "Minification: A Christmas Diet", "contents": "The festive season is generally more about gorging ourselves than staying thin but we\u2019re going to change all that with a quick introduction to minification.\n\nPerformance has been a hot topic this last year. We\u2019re building more complex sites and applications but at the same time trying to make then load faster and behave more responsively. What is a discerning web developer to do?\n\nMinification is the process of make something smaller, in the case of web site performance we\u2019re talking about reducing the size of files we send to the browser. The primary front-end components of any website are HTML, CSS, Javascript and a sprinkling of images. Let\u2019s find some tools to trim the fat and speed up our sites.\n\nFor those that want to play along at home you can download the various utilities for Mac or Windows. You\u2019ll want to be familiar with running apps on the command line too.\n\nHTMLTidy\n\nHTMLTidy optimises and strips white space from HTML documents. It also has a pretty good go at correcting any invalid markup while it\u2019s at it.\n\ntidy -m page.html\n\nCSSTidy\n\nCSSTidy takes your CSS file, optimises individual rules (for instance transforming padding-top: 10px; padding-bottom: 10px; to padding: 10px 0;) and strips unneeded white space.\n\ncsstidy style.css style-min.css\n\nJSMin\n\nJSMin takes your javascript and makes it more compact. With more and more websites using javascript to power (progressive) enhancements this can be a real bandwidth hog. Look out for pre-minified versions of libraries and frameworks too.\n\njsmin script-min.js\n\nRemember to run JSLint before you run JSMin to catch some common problems.\n\nOptiPNG\n\nImages can be a real bandwidth hog and making all of them smaller with OptiPNG should speed up your site.\n\noptipng image.png\n\nAll of these tools have an often bewildering array of options and generally good documentation included as part of the package. A little experimentation will get you even more bang for your buck.\n\nFor larger projects you likely won\u2019t want to be manually minifying all your files. The best approach here is to integrate these tools into your build process and have your live website come out the other side smaller than it went in.\n\nYou can also do things on the server to speed things up; GZIP compression for instance or compilation of resources to reduce the number of HTTP requests. If you\u2019re interested in performance a good starting point is the Exceptional Performance section on the Yahoo Developer Network and remember to install the YSlow Firebug extension while you\u2019re at it.", "year": "2007", "author": "Gareth Rushgrove", "author_slug": "garethrushgrove", "published": "2007-12-06T00:00:00+00:00", "url": "https://24ways.org/2007/minification-a-christmas-diet/", "topic": "process"} {"rowid": 156, "title": "Mobile 2.0", "contents": "Thinking 2.0\n\nAs web geeks, we have a thick skin towards jargon. We all know that \u201cWeb 2.0\u201d has been done to death. At Blue Flavor we even have a jargon bucket to penalize those who utter such painfully overused jargon with a cash deposit. But Web 2.0 is a term that has lodged itself into the conscience of the masses. This is actually a good thing.\n\nThe 2.0 suffix was able to succinctly summarize all that was wrong with the Web during the dot-com era as well as the next evolution of an evolving media. While the core technologies actually stayed basically the same, the principles, concepts, interactions and contexts were radically different.\n\nWith that in mind, this Christmas I want to introduce to you the concept of Mobile 2.0. While not exactly a new concept in the mobile community, it is relatively unknown in the web community. And since the foundation of Mobile 2.0 is the web, I figured it was about time for you to get to know each other.\n\nIt\u2019s the Carriers\u2019 world. We just live in it.\n\nBefore getting into Mobile 2.0, I thought first I should introduce you to its older brother. You know the kind, the kid with emotional problems that likes to beat up on you and your friends for absolutely no reason. That is the mobile of today.\n\nThe mobile ecosystem is a very complicated space often and incorrectly compared to the Web. If the Web was a freewheeling hippie \u2014 believing in freedom of information and the unity of man through communities \u2014 then Mobile is the cutthroat capitalist \u2014 out to pillage and plunder for the sake of the almighty dollar. Where the Web is relatively easy to publish to and ultimately make a buck, Mobile is wrought with layers of complexity, politics and obstacles. \n\nI can think of no better way to summarize these challenges than the testimony of Jason Devitt to the United States Congress in what is now being referred to as the \u201ciPhone Hearing.\u201d Jason is the co-founder and CEO of SkyDeck a new wireless startup and former CEO of Vindigo an early pioneer in mobile content.\n\n\n\nAs Jason points out, the mobile ecosystem is a closed door environment controlled by the carriers, forcing the independent publisher to compete or succumb to the will of corporate behemoths.\n\nBut that is all about to change.\n\nIntroducing Mobile 2.0\n\nMobile 2.0 is term used by the mobile community to describe the current revolution happening in mobile. It describes the convergence of mobile and web services, adding portability, ubiquitous connectivity and location-aware services to add physical context to information found on the Web.\n\nIt\u2019s an important term that looks toward the future. Allowing us to imagine the possibilities that mobile technology has long promised but has yet to deliver. It imagines a world where developers can publish mobile content without the current constraints of the mobile ecosystem.\n\nLike the transition from Web 1.0 to 2.0, it signifies the shift away from corporate or brand-centered experiences to user-centered experiences. A focus on richer interactions, driven by user goals. Moving away from proprietary technologies to more open and standard ones, more akin to the Web. And most importantly (from our perspective as web geeks) a shift away from kludgy one-off mobile applications toward using the Web as a platform for content and services.\n\nThis means the world of the Web and the world of Mobile are coming together faster than you can say ARPU (Average Revenue Per User, a staple mobile term to you webbies). And this couldn\u2019t come at a better time. The importance of understanding and addressing user context is quickly becoming a crucial consideration to every interactive experience as the number of ways we access information on the Web increases.\n\nMobile enables the power of the Web, the collective information of millions of people, inherit payment channels and access to just about every other mass media to literally be overlaid on top of the physical world, in context to the person viewing it. \n\nAnyone who can\u2019t imagine how the influence of mobile technology can\u2019t transform how we perform even the simplest of daily tasks needs to get away from their desktop and see the new evolution of information.\n\nThe Instigators\n\nBut what will make Mobile 2.0 move from idillic concept to a hardened market reality in 2008 will be four key technologies. Its my guess that you know each them already.\n\n1. Opera\n\nOpera is like the little train that could. They have been a driving force on moving the Web as we know it on to mobile handsets. Opera technology has proven itself to be highly adaptable, finding itself preloaded on over 40 million handsets, available on televisions sets through Nintendo Wii or via the Nintendo DS.\n\n2. WebKit\n\nMany were surprised when Apple chose to use KHTML instead of Gecko (the guts of Firefox) to power their Safari rendering engine. But WebKit has quickly evolved to be a powerful and flexible browser in the mobile context. WebKit has been in Nokia smartphones for a few years now, is the technology behind Mobile Safari in the iPhone and the iPod Touch and is the default web technology in Google\u2019s open mobile platform effort, Android.\n\n3. The iPhone\n\nThe iPhone has finally brought the concepts and principles of Mobile 2.0 into the forefront of consumers minds and therefore developers\u2019 minds as well. Over 500 web applications have been written specifically for the iPhone since its launch. It\u2019s completely unheard of to see so many applications built for the mobile context in such a short period of time.\n\n4. CSS & Javascript\n\nWeb 2.0 could not exist without the rich interactions offered by CSS and Javascript, and Mobile 2.0 is no different. CSS and Javascript support across multiple phones historically has been, well\u2026 to put it positively\u2026 utter crap.\n\nJavascript finally allows developers to create interesting interactions that support user goals and the mobile context. Specially, AJAX allows us to finally shed the days of bloated Java applications and focus on portable and flexible web applications. While CSS \u2014 namely CSS3 \u2014 allows us to create designs that are as beautiful as they are economical with bandwidth and load times.\n\nWith Leaflets, a collection of iPhone optimized web apps we created, we heavily relied on CSS3 to cache and reuse design elements over and over, minimizing download times while providing an elegant and user-centered design.\n\n\n\nIn Conclusion\n\nIt is the combination of all these instigators that is significantly decreasing the bar to mobile publishing. The market as Jason Devitt describes it, will begin to fade into the background. And maybe the world of mobile will finally start looking more like the Web that we all know and love.\n\nSo after the merriment and celebration of the holiday is over and you look toward the new year to refresh and renew, I hope that you take a seriously consider the mobile medium. \n\nBy this time next year, it is predicted that one-third of humanity will be using mobile devices to access the Web.", "year": "2007", "author": "Brian Fling", "author_slug": "brianfling", "published": "2007-12-21T00:00:00+00:00", "url": "https://24ways.org/2007/mobile-2-0/", "topic": "business"} {"rowid": 157, "title": "Capturing Caps Lock", "contents": "One of the more annoying aspects of having to remember passwords (along with having to remember loads of them) is that if you\u2019ve got Caps Lock turned on accidentally when you type one in, it won\u2019t work, and you won\u2019t know why. Most desktop computers alert you in some way if you\u2019re trying to enter your password to log on and you\u2019ve enabled Caps Lock; there\u2019s no reason why the web can\u2019t do the same. What we want is a warning \u2013 maybe the user wants Caps Lock on, because maybe their password is in capitals \u2013 rather than something that interrupts what they\u2019re doing. Something subtle.\n\nBut that doesn\u2019t answer the question of how to do it. Sadly, there\u2019s no way of actually detecting whether Caps Lock is on directly. However, there\u2019s a simple work-around; if the user presses a key, and it\u2019s a capital letter, and they don\u2019t have the Shift key depressed, why then they must have Caps Lock on! Simple. \n\nDOM scripting allows your code to be notified when a key is pressed in an element; when the key is pressed, you get the ASCII code for that key. Capital letters, A to Z, have ASCII codes 65 to 90. So, the code would look something like:\n\non a key press\n\tif the ASCII code for the key is between 65 and 90 *and* if shift is pressed\n\t\twarn the user that they have Caps Lock on, but let them carry on\n\tend if\nend keypress\n\nThe actual JavaScript for this is more complicated, because both event handling and keypress information differ across browsers. Your event handling functions are passed an event object, except in Internet Explorer where you use the global event object; the event object has a which parameter containing the ASCII code for the key pressed, except in Internet Explorer where the event object has a keyCode parameter; some browsers store whether the shift key is pressed in a shiftKey parameter and some in a modifiers parameter. All this boils down to code that looks something like this:\n\nkeypress: function(e) {\n\tvar ev = e ? e : window.event;\n\tif (!ev) {\n\t\treturn;\n\t}\n\tvar targ = ev.target ? ev.target : ev.srcElement;\n\t// get key pressed\n\tvar which = -1;\n\tif (ev.which) {\n\t\twhich = ev.which;\n\t} else if (ev.keyCode) {\n\t\twhich = ev.keyCode;\n\t}\n\t// get shift status\n\tvar shift_status = false;\n\tif (ev.shiftKey) {\n\t\tshift_status = ev.shiftKey;\n\t} else if (ev.modifiers) {\n\t\tshift_status = !!(ev.modifiers & 4);\n\t}\n\n\t// At this point, you have the ASCII code in \u201cwhich\u201d, \n\t// and shift_status is true if the shift key is pressed\n}\n\nThen it\u2019s just a check to see if the ASCII code is between 65 and 90 and the shift key is pressed. (You also need to do the same work if the ASCII code is between 97 (a) and 122 (z) and the shift key is not pressed, because shifted letters are lower-case if Caps Lock is on.)\n\nif (((which >= 65 && which <= 90) && !shift_status) || \n\t((which >= 97 && which <= 122) && shift_status)) {\n\t// uppercase, no shift key\n\t/* SHOW THE WARNING HERE */\n} else {\n\t/* HIDE THE WARNING HERE */\n}\n\nThe warning can be implemented in many different ways: highlight the password field that the user is typing into, show a tooltip, display text next to the field. For simplicity, this code shows the warning as a previously created image, with appropriate alt text. Showing the warning means creating a new tag with DOM scripting, dropping it into the page, and positioning it so that it\u2019s next to the appropriate field. The image looks like this:\n\n\n\nYou know the position of the field the user is typing into (from its offsetTop and offsetLeft properties) and how wide it is (from its offsetWidth properties), so use createElement to make the new img element, and then absolutely position it with style properties so that it appears in the appropriate place (near to the text field). \n\nThe image is a transparent PNG with an alpha channel, so that the drop shadow appears nicely over whatever else is on the page. Because Internet Explorer version 6 and below doesn\u2019t handle transparent PNGs correctly, you need to use the AlphaImageLoader technique to make the image appear correctly.\n\nnewimage = document.createElement('img');\nnewimage.src = \"http://farm3.static.flickr.com/2145/2067574980_3ddd405905_o_d.png\";\nnewimage.style.position = \"absolute\";\nnewimage.style.top = (targ.offsetTop - 73) + \"px\";\nnewimage.style.left = (targ.offsetLeft + targ.offsetWidth - 5) + \"px\";\nnewimage.style.zIndex = \"999\";\nnewimage.setAttribute(\"alt\", \"Warning: Caps Lock is on\");\nif (newimage.runtimeStyle) {\n\t// PNG transparency for IE\n\tnewimage.runtimeStyle.filter += \"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://farm3.static.flickr.com/2145/2067574980_3ddd405905_o_d.png',sizingMethod='scale')\";\n}\ndocument.body.appendChild(newimage);\n\nNote that the alt text on the image is also correctly set. Next, all these parts need to be pulled together. On page load, identify all the password fields on the page, and attach a keypress handler to each. (This only needs to be done for password fields because the user can see if Caps Lock is on in ordinary text fields.)\n\nvar inps = document.getElementsByTagName(\"input\");\nfor (var i=0, l=inps.length; i\n\nThe \u201ccreate an image\u201d code from above should only be run if the image is not already showing, so instead of creating a newimage object, create the image and attach it to the password field so that it can be checked for later (and not shown if it\u2019s already showing). For safety, all the code should be wrapped up in its own object, so that its functions don\u2019t collide with anyone else\u2019s functions. So, create a single object called capslock and make all the functions be named methods of the object:\n\nvar capslock = {\n\t... \n\tkeypress: function(e) {\n\t}\n\t...\n}\n\nAlso, the \u201ccreate an image\u201d code is saved into its own named function, show_warning(), and the converse \u201cremove the image\u201d code into hide_warning(). This has the advantage that developers can include the JavaScript library that has been written here, but override what actually happens with their own code, using something like:\n\n\n\n\nAnd that\u2019s all. Simply include the JavaScript library in your pages, override what happens on a warning if that\u2019s more appropriate for what you\u2019re doing, and that\u2019s all you need.\n\n See the script in action.", "year": "2007", "author": "Stuart Langridge", "author_slug": "stuartlangridge", "published": "2007-12-04T00:00:00+00:00", "url": "https://24ways.org/2007/capturing-caps-lock/", "topic": "code"} {"rowid": 158, "title": "10 Ways To Get Design Approval", "contents": "One of the most challenging parts of the web design process is getting design sign off. It can prove time consuming, demoralizing and if you are not careful can lead to a dissatisfied client. What is more you can end up with a design that you are ashamed to include in your portfolio.\n\nHow then can you ensure that the design you produce is the one that gets built? How can you get the client to sign off on your design? Below are 10 tips learnt from years of bitter experience.\n\n1. Define the role of the client and designer\n\nMany of the clients you work with will not have been involved in a web project before. Even if they have they may have worked in a very different way to what you would expect. Take the time at the beginning of the project to explain their role in the design of the site.\n\nThe best approach is to emphasis that their job is to focus on the needs of their users and business. They should concentrate on the broad issues, while you worry about the details of layout, typography and colour scheme.\n\nBy clarifying what you expect from the client, you help them to provide the right kind of input throughout the process.\n\n2. Understand the business\n\nBefore you open up Photoshop or put pen to paper, take the time to make sure you properly understand not only the brief but the organization behind the site. By understanding their business objectives, organizational structure and marketing strategy your design decisions will be better informed.\n\nYou cannot rely upon the brief to provide all of the information you need. It is important to dig deeper and get as good an understanding of their business as possible. This information will prove invaluable when justifying your design decisions.\n\n3. Understand the users\n\nWe all like to think of ourselves as user centric designers, but exactly how much effort do you put into knowing your users before beginning the design process?\n\nTake the time to really understand them the best you can. Try to meet with some real prospective users and get to know their needs. Failing that work with the client to produce user personas to help picture exactly what kind of people they are. \n\nUnderstanding your users not only improves the quality of your work, but also helps move the discussion away from the personal preferences of the client, to the people who\u2019s opinion really matters.\n\n4. Avoid multiple concepts\n\nMany clients like the idea of having the option to choose between multiple design concepts. However, although on the surface this might appear to be a good idea it can ultimately be counterproductive for design sign off.\n\nIn a world of limited budgets it is unwise to waste money on producing designs that are ultimately going to be thrown away. The resources would be better spent refining a single design through multiple iterations.\n\nWhat is more, multiple concepts often cause confusion rather than clarity. It is common for a client to request one element from one design and another from the second. As any designer knows this seldom works.\n\n5. Use mood boards\n\nClients are often better at expressing what they don\u2019t like than what they do. This is one of the reasons why they favour producing multiple design concepts. An alternative less costly approach is to create a series of mood boards. These boards contain a collection of colours, typography and imagery which represent different \u201cmoods\u201d or directions, which the design could take. \n\nMood boards are quick and easy to produce allowing you to try out various design approaches with the client without investing the time needed to produce complete design concepts. This means that by the time you develop a concept the client and designer have already established an understanding about the direction of the design.\n\n6. Say what you like\n\nIt is not uncommon for a client to ask for a design that looks similar to another site they like. The problem is that it can often be hard to establish exactly what it is about the site that attracts them. Also in many cases the sites they like are not something you are keen to emulate!\n\nA better approach that was suggested to me by Andy Budd is to show them sites that you think the design should emulate. Keep a collection of screen captures from well designed sites and pick out a few that are relevant to that particular client. Explain why you feel these designs might suit their project and ask for their feedback. If they don\u2019t like your choices then expose them to more of your collection and see what they pick out.\n\n7. Wireframe the homepage\n\nOften clients find it hard to distinguish between design and content and so sometimes reject a design on the basis that the content is not right. This is particularly true when signing off the homepage.\n\nYou may therefore find it useful to establish the homepage content before producing the design. That way once they see the design they will not be distracted by the content. One of the best ways to do this is by producing a basic wireframe consisting of a series of content boxes. Once this has been approved you will find the sign off of design much easier.\n\n8. Present your designs\n\nAlthough it is true that a good design should speak for itself it still needs presenting to the client. The client needs to understand why you have made the design decisions you have, otherwise they will judge the design purely on personal preference. \n\nTalk them through the design explaining how it meets the needs of their users and business objectives. Refer to the mood boards and preferred sites the client approved and explain how the design is a continuation of those. Never simply email the design through and hope the client interprets your work correctly!\n\n9. Provide written supporting material\n\nUnfortunately, no matter how well you justify the design to the client he is almost certain to want to show it to others. He may need his bosses approval or require internal buy in. At the very least he is going to want to get a second opinion from a friend or colleague.\n\nThe problem with this is that you are not going to be there to present to these people in the same way you did for the client. You cannot expect the client to present your ideas as well as you did. The reality is that you have lost control of how the design is perceived.\n\nOne way to minimize this problem is to provide written documentation supporting the design. This can be a summary of the presentation you gave to the client and allows him to distribute this along with the design. By putting a written explanation with the design you ensure that everybody who sees it gets the same message.\n\n10. Control the feedback\n\nMy final piece of advice for managing design sign off is to control the way you receive feedback. A clients natural inclination will be to give you his personal opinion on the design. This is reinforced because you ask them what they think of the design. Instead ask them what their users will think of the design. Encourage them to think from the users perspective.\n\nAlso encourage them to keep that overarching focus I talked about in my first tip. Their tendency will be to try to improve the design, however that should be your problem not theirs. The role of a client should be to defend the needs of their users and business not do the design. Encourage the client to make comments such as \u201cI am not sure that my female users will like the masculine colours\u201d rather than \u201ccan we make the whole design pink.\u201d It is down to them to identify the problems and for you as the designer to find the most appropriate solution.\n\nSo there you have it. My 10 tips to improve design sign off. Will this ensure design approval every time? Unfortunately not. However it should certainly help smooth the way.", "year": "2007", "author": "Paul Boag", "author_slug": "paulboag", "published": "2007-12-10T00:00:00+00:00", "url": "https://24ways.org/2007/10-ways-to-get-design-approval/", "topic": "business"} {"rowid": 159, "title": "How Media Studies Can Massage Your Message", "contents": "A young web designer once told his teacher \u2018just get to the meat already.\u2019 He was frustrated with what he called the \u2018history lessons and name-dropping\u2019 aspects of his formal college course. He just wanted to learn how to build Web sites, not examine the reasons why.\n\nTechnique and theory are both integrated and necessary portions of a strong education. The student\u2019s perspective has direct value, but also holds a distinct sorrow: Knowing the how without the why creates a serious problem. Without these surrounding insights we cannot tap into the influence of the history and evolved knowledge that came before. We cannot properly analyze, criticize, evaluate and innovate beyond the scope of technique.\n\nHistory holds the key to transcending former mistakes. Philosophy encourages us to look at different points of view. Studying media and social history empowers us as Web workers by bringing together myriad aspects of humanity in direct relation to the environment of society and technology. Having an understanding of media, communities, communication arts as well as logic, language and computer savvy are all core skills of the best of web designers in today\u2019s medium.\n\nControlling the Message\n\n\n\t\u2018The computer can\u2019t tell you the emotional story. It can give you the exact mathematical design, but what\u2019s missing is the eyebrows.\u2019 \u2013 Frank Zappa\n\n\nMedia is meant to express an idea. The great media theorist Marshall McLuhan suggests that not only is media interesting because it\u2019s about the expression of ideas, but that the media itself actually shapes the way a given idea is perceived. This is what McLuhan meant when he uttered those famous words: \u2018The medium is the message.\u2019\n\nIf instead of actually serving a steak to a vegetarian friend, what might a painting of the steak mean instead? Or a sculpture of a cow? Depending upon the form of media in question, the message is altered.\n\nFigure 1\n\nMust we know the history of cows to appreciate the steak on our plate? Perhaps not, but if we begin to examine how that meat came to be on the plate, the social, cultural and ideological associations of that cow, we begin to understand the complexity of both medium and message. A piece of steak on my plate makes me happy. A vegetarian friend from India might disagree and even find that that serving her a steak was very insensitive.\n\nTakeaway: Getting the message right involves understanding that message in order to direct it to your audience accordingly.\n\nA Separate Piece\n\nIf we revisit the student who only wants technique, while he might become extremely adept at the rendering of an idea, without an understanding of the medium, how is he to have greater control over how that idea is perceived? Ultimately, his creativity is limited and his perspective narrowed, and the teacher has done her student a disservice without challenging him, particularly in a scholastic environment, to think in liberal, creative and ultimately innovative terms.\n\nFor many years, web pundits including myself have promoted the idea of separation as a core concept within creating effective front-end media for the Web. By this, we\u2019ve meant literal separation of the technologies and documents: Markup for content; CSS for presentation; DOM Scripting for behavior. While the message of separation was an important part of understanding and teaching best practices for manageable, scalable sites, that separation is really just a separation of pieces, not of entire disciplines.\n\nFor in fact, the medium of the Web is an integrated one. That means each part of the desired message must be supported by the media silos within a given site. The visual designer must study the color, space, shape and placement of visual objects (including type) into a meaningful expression. The underlying markup is ideally written as semantically as possible, promote the meaning of the content it describes. Any interaction and functionality must make the process of the medium support, not take away from, the meaning of the site or Web application. \n\nExamination: The Glass Bead Game\n\nFigure 2\n\nFigure 2 shows two screenshots of CoreWave\u2019s historic \u2018Glass Bead Game.\u2019 Fashioned after Herman Hesse\u2019s novel of the same name, the game was an exploration of how ideas are connected to other ideas via multiple forms of media. It was created for the Web in 1996 using server-side randomization with .htmlx files in order to allow players to see how random associations are in fact not random at all.\n\nTakeaway: We can use the medium itself to explore creative ideas, to link us from one idea to the next, and to help us better express those ideas to our audiences.\n\nComputers and Human Interaction\n\nSince our medium involves computers and human interaction, it does us well to look to foundations of computers and reason. Not long ago I was chatting with Jared Spool on IM about this and that, and he asked me \u2018So how do you feel about that?\u2019 This caused me no end of laughter and I instantly quipped back \u2018It\u2019s okay by me ELIZA.\u2019 We both enjoyed the joke, but then I tried to share it with another dare I say younger colleague, and the reference was lost.\n\nRaise your hand if you got the reference! Some of you will, but many people who come to the Web medium do not get the benefit of such historical references because we are not formally educated in them. Joseph Weizenbaum created the ELIZA program, which emulates a Rogerian Therapist, in 1966. It was an early study of computers and natural human language. I was a little over 2 years old, how about you?\n\nConversation with Eliza\n\nThere are fortunately a number of ELIZA emulators on the Web. I found one at http://www.chayden.net/eliza/Eliza.html that actually contains the source code (in Java) that makes up the ELIZA script.\n\nFigure 3 shows a screen shot of the interaction. ELIZA first welcomes me, says \u2018Hello, How do you do. Please state your problem\u2019 and we continue in a short loop of conversation, the computer using cues from my answers to create new questions and leading fragments of conversation.\n\nFigure 3\n\nAlbeit a very limited demonstration of how humans could interact with a computer in 1966, it\u2019s amusing to play with now and compare it to something as richly interactive as the Microsoft Surface (Figure 4). Here, we see clear Lucite blocks that display projected video. Each side of the block has a different view of the video, so not only does one have to match up the images as they are moving, but do so in the proper directionality.\n\nFigure 4\n\nTakeway: the better we know our environment, the more we can alter it to emulate, expand and even supersede our message.\n\nLeveraging Holiday Cheer\n\nSince most of us at least have a few days off for the holidays now that Christmas is upon us, now\u2019s a perfect time to reflect on ones\u2019 environment and examine the messages within it. Convince your spouse to find you a few audio books for stocking stuffers. Find interactive games to play with your kids and observe them, and yourself, during the interaction. Pour a nice egg-nog and sit down with a copy of Marshall McLuhan\u2019s \u2018The Medium is the Massage.\u2019 Leverage that holiday cheer and here\u2019s to a prosperous, interactive new year.", "year": "2007", "author": "Molly Holzschlag", "author_slug": "mollyholzschlag", "published": "2007-12-22T00:00:00+00:00", "url": "https://24ways.org/2007/how-media-studies-can-massage-your-message/", "topic": "ux"} {"rowid": 160, "title": "Tracking Christmas Cheer with Google Charts", "contents": "A note from the editors: Since this article was written Google has retired the Charts API.\n \n \n \n Let\u2019s get something out in the open: I love statistics. As an informatician I can\u2019t get enough graphs, charts, and numbers. So you can imagine when Google released their Charts API I thought Christmas had come early. I immediately began to draw up graphs for the holiday season using the new API; and using my new found chart-making skills I\u2019ll show you what you can and can\u2019t do with Google Charts.\n\nMummy, it\u2019s my first chart\n\nThe Google Charts API allows you to send data to Google; in return they give you back a nicely-rendered graph. All the hard work is done on Google\u2019s servers \u2014 you need only reference an image in your HTML. You pass along the data \u2014 the numbers for the charts, axis labels, and so on \u2014 in the query string of the image\u2019s URL. If you want to add charts to your blog or web site, there\u2019s probably no quicker way to get started.\n\nHere\u2019s a simple example: if we add the following line to an HTML page:\n\n\n\nThen we\u2019ll see the line graph in Figure 1 appear in our page. That graph is hosted on Google\u2019s own server1: http://chart.apis.google.com/.\n\nFigure 1: A simple example of a line graph created with Google Charts.\n\nIf you look at the URL used in the example you\u2019ll notice we\u2019re passing some parameters along in the query string (the bit after the question mark). The query string looks like this:\n\ncht=lc&chs=200x125&chd=s:ZreelPuevfgznf2008\n\nIt\u2019s contains everything Google Charts needs to draw the graph. There are three parameters in the query string:\n\n\n\tcht; this specifies the type of chart Google Charts will generate (in this case, lc is a line chart).\n\tchs, the value of which is 200x125; this defines the chart\u2019s size (200 pixels wide by 125 pixels high).\n\tchd, the value of which is s:ZreelPuevfgznf2008; this is the actual chart data, which we\u2019ll discuss in more detail later.\n\n\nThese three parameters are the minimum you need to send to Google Charts in order to create a chart. There are lots more parameters you can send too (giving you more choice over how a chart is displayed), but you have to include at least these three before a chart can be created. Using these three parameters you can create pie charts, scatter plots, Venn diagrams, bar charts (and more) up to 1,000 pixels wide or 1,000 pixels high (but no more than 300,000 pixels in total).\n\nChristmas pie\n\nAfter I discovered the option to create a pie chart I instantly thought of graphing all the types of food and beverages that I\u2019ll consume at this year\u2019s Christmas feast. I can represent each item as a percentage of all the food on a pie chart (just thinking about that makes me hungry).\n\nBy changing the value of the cht parameter in the image\u2019s query string I can change the chart type from a line chart to a pie chart. Google Charts offers two different types of pie chart: a fancy three-dimensional version and a two-dimensional overhead version. I want to stick with the latter, so I need to change cht=lc to cht=p (the p telling Google Charts to create a pie chart; if you want the three-dimensional version, use cht=p3). As a pie chart is circular I also need to adjust the size of the chart to make it square. Finally, it would be nice to add a title to the graph. I can do this by adding the optional parameter, chtt, to the end of the image URL. I end up with the chart you see in Figure 2.\n\nFigure 2: Pie chart with a title.\n\nTo add this chart to your own page, you include the following (notice that you can\u2019t include spaces in URLs, so you need to encode them as plus-signs.):\n\n\n\nOk, that\u2019s great, but there are still two things I want to do before I can call this pie chart complete. First I want to label each slice of the pie. And second I want to include the proper data (at the moment the slices are meaningless). If 2007 is anything like 2006, the break down will be roughly as follows:\n\n\n\t\t\n\t\t\tEgg nog\n\t\t\t10%\n\t\t\n\t\t\n\t\t\tChristmas Ham\n\t\t\t20%\n\t\t\n\t\t\n\t\t\tMilk (not including egg nog)\n\t\t\t8%\n\t\t\n\t\t\n\t\t\tCookies\n\t\t\t25%\n\t\t\n\t\t\n\t\t\tRoasted Chestnuts\n\t\t\t5%\n\t\t\n\t\t\n\t\t\tChocolate\n\t\t\t3%\n\t\t\n\t\t\n\t\t\tVarious Other Beverages\n\t\t\t15%\n\t\t\n\t\t\n\t\t\tVarious Other Foods\n\t\t\t9%\n\t\t\n\t\t\n\t\t\tSnacks\n\t\t\t5%\n\t\t\n\n\nI have nine categories of food and drink to be tracked, so I need nine slice labels. To add these to the chart, I use the chl parameter. All nine labels are sent in one value; I use the vertical-pipe character, |, to separate them. So I need to append the following to the query string:\n\nchl=Egg+nog|Christmas+Ham|Milk+(not+including+egg+nog)|Cookies|Roast+Chestnuts|Chocolate|Various+Other+Beverages|Various+Other+Foods|Snacks\n\nNext I need to add the corresponding percentage values to the chart labels. Encoding the chart data is the trickiest part of the Google Charts API \u2014 but by no means complicated. There are three different ways to encode your data on a chart. As I\u2019m only dealing with small numbers, I\u2019m going to use what Google calls simple encoding.\n\nSimple encoding offers a sixty-two value spectrum in which to represent data. Remember the mandatory option, chd, from the first example? The value for this is split into two parts: the type of encoding and the graph data itself. These two parts are separated with a colon. To use simple encoding, the first character of the chd option must be a lower case s. Follow this with a colon and everything after it is considered data for the graph.\n\nIn simple encoding, you have sixty-two values to represent your data. These values are lowercase and uppercase letters from the Latin alphabet (fifty-two characters in total) and the digits 0 to 9. Each letter of the alphabet represents a single number: A equals 0, B equals 1, and so on up to Z, which equals 25; a equals 26, b equals 27, and so on up to z, which equals 51. The ten digits represent the numbers 52 to 61: 0 equals 52, 1 equals 53, and 9 equals 61.\n\nIn the previous two examples we used the string ZreelPuevfgznf2008 as our chart data; the Z is equal to 25, the r is equal to 42, the e is equal to 30, and so on. I want to encode the percentage values 10, 20, 8, 25, 5, 3, 15, 9 and 5, so in simple encoding I would use the string KUIZFDPJF.\n\nIf you think figuring this out for each chart may make your head explode, don\u2019t worry: help is out there.\n\nDo you remember I said I needed to change the image dimensions to be square, to accommodate the pie chart? Well now I\u2019m including labels I need even more room. And as I\u2019m in a Christmassy mood I\u2019m going to add some festive colours too.\n\nThe optional chco parameter is used to change the chart color. You set this using the same hexadecimal (\u201chex\u201d) notation found in CSS. So let\u2019s make our pie chart green by adding chco=00AF33 (don\u2019t start it with a hash character as in CSS) to the image URL. If we only specify one hex colour for the pie chart Google Charts will use shades of that colour for each of the slices. To choose your own colours, pass a comma separated list of colours. The \u201cMilk\u201d and \u201cCookies\u201d slices were consumed together, so we can make those two slices more of a redish colour. I\u2019ll use shades of green for the other slices. My chco parameter now looks like this:\n\nchco=00AF33,4BB74C,EE2C2C,CC3232,33FF33,66FF66,9AFF9A,C1FFC1,CCFFCC.\n\nAfter all this, I\u2019m left with the following URL:\n\nhttp://chart.apis.google.com/chart?chco=00AF33,4BB74C,EE2C2C,CC3232,33FF33,66FF66,9AFF9A,C1FFC1,CCFFCC&chl=Egg+nog|Christmas+Ham|Milk+(not+including+egg+nog)|Cookies|Roast+Chestnuts|Chocolate|Various+Other+Beverages|Various+Other+Foods|Snacks&chtt=Food+and+Drink+Consumed+Christmas+2007&cht=p&chs=600x300&chd=s:KUIZFDPJF\n\nWhat does that give us? I\u2019m glad you asked. I have the rather beautiful 600-pixel wide pie chart you see in Figure 3.\n\nFigure 3: A Christmassy pie chart with labels.\n\nBut I don\u2019t like pie charts\n\nThe pie chart was invented by the Scottish polymath William Playfair in 1801. But not everyone is as excited by pie charts as wee Billy, so if you\u2019re an anti-pie-chartist, what can you do?\n\nYou can easily reuse the same data but display it as a bar graph in a snap. The first thing we need to do is change the value of the cht parameter from p to bhg. This creates a horizontal bar graph (you can request a vertical bar graph using bvg). The data and labels all remain the same, but we need to decide where the labels will appear. I\u2019ll talk more about how to do all this in the next section. \n\nIn Figure 4 you\u2019ll see the newly-converted bar graph. The URL for the graph is:\n\nhttp://chart.apis.google.com/chart?cht=bhg&chs=600x300&chd=s:KUIZFDPJF&chxt=x,y&chtt=Food+and+Drink+Consumed+Christmas+2007&chxl=1:|Egg+nog|Christmas+Ham|Milk+(not+including+egg+nog)|Cookies|Roast+Chestnuts|Chocolate|Various+Other+Beverages|Various+Other+Foods|Snacks&chco=00AF33\n\nFigure 4: The pie chart from Figure 3 represented as a bar chart.\n\nTwo lines, one graph\n\nPie charts and bar charts are interesting, but what if I want to compare last year\u2019s Christmas cheer with this year\u2019s? That sounds like I\u2019ll need two lines on one graph.\n\nThe code is much the same as the previous examples; the most obvious difference is I need to set up the chart as a line graph. Creating some dummy values for the required parameters, I end up with:\n\n\n\nThe chs=800x300 sets the dimensions of the new chart, while cht=lxy describes the type of chart we are using (in this case a line chart with x and y co-ordinates). For the chart data I\u2019m going to demostrate a different encoding, text encoding. To use this I start the value of the chd parameter with \u201ct:\u201d instead of \u201cs:\u201d, and follow it with a list of x coordinates, a vertical pipe, |, and a list of y coordinates. Given the URL above, Google Charts will render the chart shown in Figure 5.\n\nFigure 5: A simple line graph with x and y co-ordinates.\n\nTo make this graph a little more pleasing to the eye, I can add much the same as I did to the pie chart. I\u2019ll add a chart title. Maybe something like \u201cProjected Christmas Cheer for 2007\u201d. Just as before I would add a chtt parameter to the image URL:\n\n&chtt=Projected+Christmas+Cheer+for+2007\n\nNext, let\u2019s add some labels on the y axis to represent a scale from 0 to 100. On the x axis let\u2019s label for the most important days of December. To do this I need to use the chart axis type parameter, chxt. This allows us to specify the axes and associate some labels with them. As I\u2019m only interested in the y-axis (to the left of the chart) and the x-axis (below the chart), we add chxt=x,y to our image URL.\n\nNow I need my label data. This is slightly more tricky because I want the data evenly spaced without labelling every item. The parameter for labels is chxl, the chart axis label. You match a label to an axis by using a number. So 0:Label1 is the zero index of chxt \u2014 in this case the x-axis. 1:Label2 is the first index of chxt \u2014 the y-axis. The order of these parameters or labels doesn\u2019t matter as long as you associate them to their chxt correctly.\n\nThe next thing to know about chxl is that you can add an empty label. Labels are separated by vertical pipe; if you don\u2019t put any text in a label, you just leave the two vertical pipes empty (\u201c||\u201d) and Google Charts will allocate space but no label.\n\nFor our vertical y axis, we want to label only 50% and 100% on the graph and plot them in their respective places. Since the y-axis is the second item, 1: (remember to start counting at zero), we add ten spaces to our image URL, chxl=1:||||||50|||||100 This will output the 50 halfway and the 100 at the top; all the other spaces will be empty.\n\nWe can do the same thing to get specific dates along the x-axis as well. Let\u2019s add the 1st of December, St. Nick\u2019s Day (the 6th), Christmas Day, Boxing Day (a holiday common in the UK and the Commonwealth, on the 26th), and the final day of the month, the 31st. Since this is the x-axis I\u2019ll use 0: as a reference in the chxt parameter tell Google Charts which axis to label. In full, the chxl parameter now looks like:\n\nchxl=1:||||||50|||||100|0:|Dec+1st|||||6th||||10th|||||15th|||||20th|||||25th|26th|||||Dec+31st\n\nThat\u2019s pretty.\n\nBefore we begin to graph our data, I\u2019ll do one last thing: add some grid lines to the chart so to better connect the data to the labels. The parameter for this is chg, short for chart grid lines. The parameter takes four comma-separated arguments. The first is the x-axis spacing for the grid. I have thirty-one days, so I need thirty vertical lines. The chart is 100% wide, so 3.33 (100 divided by 30) is the required spacing.\n\nAs for the y-axis: the axis goes up to 100% but we probably only need to have a horizontal line every 10%, so the required spacing is 10 (100 divided by 10). That is the second argument.\n\nThe last two arguments control the dash-style of the grid-lines. The first number is the length of the line dash and the second is the space between the dashes. So 6,3 would mean a six-unit dash with a three-unit space. I like a ratio of 1,3 but you can change this as you wish. Now that I have the four arguments, the chg parameter looks like:\n\nchg=3.333,10,1,3\n\nIf I add that to the chart URL I end up with:\n\nhttp://chart.apis.google.com/chart?chs=800x300&cht=lxy&chd=t:0,100|0,100&chtt=Projected+Christmas+Cheer+for+2007&chxt=x,y&chxl=0:|Dec+1st|||||6th|||||||||||||||||||25th|26th|||||Dec+31st|1:||||||50|||||100&chg=3.3333,10,1,3\n\nWhich results in the chart shown in Figure 6.\n\nFigure 6: Chart ready to receive the Christmas cheer values.\n\nReal data\n\nNow the chart is ready I can add historical data from 2006 and current data from 2007.\n\nHaving a look at last year\u2019s cheer levels we find some highs and lows through-out the month:\n\n\n\t\t\n\t\t\tDec 1st\n\t\t\tAdvent starts; life is good\n\t\t\t30%\n\t\t\n\t\t\n\t\t\tDec 6th\n\t\t\tSt. Nick\u2019s Day, awake to find good things in my shoes\n\t\t\t45%\n\t\t\n\t\t\n\t\t\tDec 8th\n\t\t\tWent Christmas carolling, nearly froze\n\t\t\t20%\n\t\t\n\t\t\n\t\t\tDec 10th\n\t\t\tChristmas party at work, very nice dinner\n\t\t\t50%\n\t\t\n\t\t\n\t\t\tDec 18th\n\t\t\tPanic Christmas shopping, hate rude people\n\t\t\t15%\n\t\t\n\t\t\n\t\t\tDec 23rd\n\t\t\tOff Work, home eating holiday food\n\t\t\t80%\n\t\t\n\t\t\n\t\t\tDec 25th\n\t\t\tOpened presents, good year, but got socks again from Grandma\n\t\t\t60%\n\t\t\n\t\t\n\t\t\tDec 26th\n\t\t\tBoxing Day; we\u2019re off and no one knows why\n\t\t\t70%\n\t\t\n\t\t\n\t\t\tDec 28th\n\t\t\tThird day of left overs\n\t\t\t40%\n\t\t\n\t\t\n\t\t\tDec 29th\n\t\t\tProcured some fireworks for new years\n\t\t\t55%\n\t\t\n\t\t\n\t\t\tDec 31st\n\t\t\tNew Year\u2019s Eve\n\t\t\t80%\n\t\t\n\n\nSince I\u2019m plotting data for 2006 and 2007 on the same graph I\u2019ll need two different colours \u2014 one for each year\u2019s line \u2014 and a key to denote what each colour represents. The key is controlled by the chdl (chart data legend) parameter. Again, each part of the parameter is separated by a vertical pipe, so for two labels I\u2019ll use chdl=2006|2007. I also want to colour-code them, so I\u2019ll need to add the chco as I did for the pie chart. I want a red line and a green line, so I\u2019ll use chco=458B00,CD2626 and add this to the image URL.\n\nLet\u2019s begin to plot the 2006 data on the Chart, replacing our dummy data of chd=t:0,100|0,100 with the correct information. The chd works by first listing all the x coordinates (each separated by a comma), then a vertical pipe, and then all the y coordinates (also comma-separated). The chart is 100% wide, so I need to convert the days into a percentage of the month.\n\nThe 1st of December is 0 and the 31st is 100. Everything else is somewhere in between. Our formula is:\n\n(d \u2013 1) \u00d7 100 \u00f7 (31 \u2013 1)\n\nWhere d is the day of the month. The formula states that each day will be printed every 3.333 units; so the 6th of December will be printed at 16.665 units. I can repeat the process for the other dates listed to get the following x coordinates: 0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7. The y axis coordinates are easy because our scale is 100%, just like our rating, so we can simply copy them across as 30,45,20,50,15,80,60,70,40,55,80. This gives us a final chd value of:\n\nchd=t:0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7,100|30,45,20,50,15,80,60,70,40,55,80\n\nOnto 2007: I can put the data for the month so far to see how we are trending.\n\n\n\t\t\n\t\t\tDec 1st\n\t\t\tChristmas shopping finished already\n\t\t\t50%\n\t\t\n\t\t\n\t\t\tDec 4th\n\t\t\tComputer hard disk drive crashed (not Christmas related accident, but put me in a bad mood)\n\t\t\t10%\n\t\t\n\t\t\n\t\t\tDec 6th\n\t\t\tMissed St. Nick\u2019s Day completely due to travelling\n\t\t\t30%\n\t\t\n\t\t\n\t\t\tDec 9th\n\t\t\tDinner with friends before they travel\n\t\t\t55%\n\t\t\n\t\t\n\t\t\tDec 11th\n\t\t\t24ways article goes live\n\t\t\t60%\n\t\t\n\n\nUsing the same system we did for 2006, I can take the five data points and plot them on the chart. The new x axis values will be 0,10,16.7,26.7 and the new y axis 50,10,30,65. We incorporate those into the image URL by appending these values onto the chd parameter we already have, which then becomes:\n\nchd=t:0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7,100|30,45,20,50,15,80,60,70,40,55,80|0,10,16.7,26.7,33.3|50,10,30,55,60\n\nPassing this to Google Charts results in Figure 7.\n\nhttp://chart.apis.google.com/chart?chs=800x300&cht=lxy&chd=t:0,100|0,100&chtt=Projected+Christmas+Cheer+for+2007&chxt=x,y&chxl=0:|Dec+1st|||||6th|||||||||||||||||||25th|26th|||||Dec+31st|1:||||||50|||||100&chg=3.3333,10,1,3&chd=t:0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7,100|30,45,20,50,15,80,60,70,40,55,80|0,10,16.7,26.7,33.3|50,10,30,55,60&chco=458B00,CD2626&chdl=2006|2007\n\nFigure 7: Projected Christmas cheer for 2006 and 2007.\n\nDid someone mention Edward Tufte?\n\nGoogle Charts are a robust set of chart types that you can create easily and freely using their API. As you can see, you can graph just about anything you want using the line graph, bar charts, scatter plots, venn diagrams and pie charts. One type of chart conspicuously missing from the API is sparklines. Sparklines were proposed by Edward Tufte as \u201csmall, high resolution graphics embedded in a context of words, numbers, images\u201d. They can be extremely useful, but can you create them in Google Charts?\n\nThe answer is: \u201cYes, but it\u2019s an undocumented feature\u201d. (The usual disclaimer about undocumented features applies.)\n\nIf we take our original line graph example, and change the value of the cht parameter from lc (line chart) to lfi (financial line chart) the axis-lines are removed. This allows you to make a chart \u2014 a sparkline \u2014 small enough to fit into a sentence. Google uses the lfi type all throughout the their financial site, but it\u2019s not yet part of the official API.\n\n\n\t\t\n\t\t\tMerryChristmas\n\t\t\t\n\t\t\thttp://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:MerryChristmas\n\t\t\n\t\t\n\t\t\t24ways\n\t\t\t\n\t\t\thttp://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:24ways&chco=999999\n\t\t\n\t\t\n\t\t\tHappyHolidays\n\t\t\t\n\t\t\thttp://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:HappyHolidays&chco=ff0000\n\t\t\n\t\t\n\t\t\tHappyNewYear\n\t\t\t\n\t\t\thttp://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:HappyNewYear&chco=0000ff\n\t\t\n\n\nSummary\n\nThe new Google Charts API is a powerful method for creating charts and graphs of all types. If you apply a little bit of technical skill you can create pie charts, bar graphs, and even sparklines as and when you need them. Now you\u2019ve finished ready the article I hope you waste no more time: go forth and chart!\n\nFurther reading\n\n\n\tGoogle Charts API\n\tMore on Google Charts\n\tHow to handle negative numbers\n\t12 Days of Christmas Pie Chart\n\n\n1 In order to remain within the 50,000 requests a day limit the Google Charts API imposes, chart images on this page have been cached and are being served from our own servers. But the URLs work \u2013 try them!", "year": "2007", "author": "Brian Suda", "author_slug": "briansuda", "published": "2007-12-11T00:00:00+00:00", "url": "https://24ways.org/2007/tracking-christmas-cheer-with-google-charts/", "topic": "ux"} {"rowid": 161, "title": "Keeping JavaScript Dependencies At Bay", "contents": "As we are writing more and more complex JavaScript applications we run into issues that have hitherto (god I love that word) not been an issue. The first decision we have to make is what to do when planning our app: one big massive JS file or a lot of smaller, specialised files separated by task. \n\nPersonally, I tend to favour the latter, mainly because it allows you to work on components in parallel with other developers without lots of clashes in your version control. It also means that your application will be more lightweight as you only include components on demand.\n\nStarting with a global object\n\nThis is why it is a good plan to start your app with one single object that also becomes the namespace for the whole application, say for example myAwesomeApp:\n\nvar myAwesomeApp = {};\n\nYou can nest any necessary components into this one and also make sure that you check for dependencies like DOM support right up front.\n\nAdding the components\n\nThe other thing to add to this main object is a components object, which defines all the components that are there and their file names.\n\nvar myAwesomeApp = {\n\tcomponents :{\n\t\tformcheck:{\n\t\t\turl:'formcheck.js',\n\t\t\tloaded:false\n\t\t},\n\t\tdynamicnav:{\n\t\t\turl:'dynamicnav.js',\n\t\t\tloaded:false\n\t\t},\n\t\tgallery:{\n\t\t\turl:'gallery.js',\n\t\t\tloaded:false\n\t\t},\n\t\tlightbox:{\n\t\t\turl:'lightbox.js',\n\t\t\tloaded:false\n\t\t}\n\t}\n};\n\nTechnically you can also omit the loaded properties, but it is cleaner this way. The next thing to add is an addComponent function that can load your components on demand by adding new SCRIPT elements to the head of the documents when they are needed.\n\nvar myAwesomeApp = {\n\tcomponents :{\n\t\tformcheck:{\n\t\t\turl:'formcheck.js',\n\t\t\tloaded:false\n\t\t},\n\t\tdynamicnav:{\n\t\t\turl:'dynamicnav.js',\n\t\t\tloaded:false\n\t\t},\n\t\tgallery:{\n\t\t\turl:'gallery.js',\n\t\t\tloaded:false\n\t\t},\n\t\tlightbox:{\n\t\t\turl:'lightbox.js',\n\t\t\tloaded:false\n\t\t}\n\t},\n\taddComponent:function(component){\n\t\tvar c = this.components[component];\n\t\tif(c && c.loaded === false){\n\t\t\tvar s = document.createElement('script');\n\t\t\ts.setAttribute('type', 'text/javascript');\n\t\t\ts.setAttribute('src',c.url);\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(s);\n\t\t}\n\t}\n};\n\nThis allows you to add new components on the fly when they are not defined:\n\nif(!myAwesomeApp.components.gallery.loaded){\n\tmyAwesomeApp.addComponent('gallery');\n};\n\nVerifying that components have been loaded\n\nHowever, this is not safe as the file might not be available. To make the dynamic adding of components safer each of the components should have a callback at the end of them that notifies the main object that they indeed have been loaded:\n\nvar myAwesomeApp = {\n\tcomponents :{\n\t\tformcheck:{\n\t\t\turl:'formcheck.js',\n\t\t\tloaded:false\n\t\t},\n\t\tdynamicnav:{\n\t\t\turl:'dynamicnav.js',\n\t\t\tloaded:false\n\t\t},\n\t\tgallery:{\n\t\t\turl:'gallery.js',\n\t\t\tloaded:false\n\t\t},\n\t\tlightbox:{\n\t\t\turl:'lightbox.js',\n\t\t\tloaded:false\n\t\t}\n\t},\n\taddComponent:function(component){\n\t\tvar c = this.components[component];\n\t\tif(c && c.loaded === false){\n\t\t\tvar s = document.createElement('script');\n\t\t\ts.setAttribute('type', 'text/javascript');\n\t\t\ts.setAttribute('src',c.url);\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(s);\n\t\t}\n\t},\n\tcomponentAvailable:function(component){\n\t\tthis.components[component].loaded = true;\n\t}\n}\n\nFor example the gallery.js file should call this notification as a last line:\n\nmyAwesomeApp.gallery = function(){\n\t// [... other code ...]\n}();\nmyAwesomeApp.componentAvailable('gallery');\n\nTelling the implementers when components are available\n\nThe last thing to add (actually as a courtesy measure for debugging and implementers) is to offer a listener function that gets notified when the component has been loaded:\n\nvar myAwesomeApp = {\n\tcomponents :{\n\t\tformcheck:{\n\t\t\turl:'formcheck.js',\n\t\t\tloaded:false\n\t\t},\n\t\tdynamicnav:{\n\t\t\turl:'dynamicnav.js',\n\t\t\tloaded:false\n\t\t},\n\t\tgallery:{\n\t\t\turl:'gallery.js',\n\t\t\tloaded:false\n\t\t},\n\t\tlightbox:{\n\t\t\turl:'lightbox.js',\n\t\t\tloaded:false\n\t\t}\n\t},\n\taddComponent:function(component){\n\t\tvar c = this.components[component];\n\t\tif(c && c.loaded === false){\n\t\t\tvar s = document.createElement('script');\n\t\t\ts.setAttribute('type', 'text/javascript');\n\t\t\ts.setAttribute('src',c.url);\n\t\t\tdocument.getElementsByTagName('head')[0].appendChild(s);\n\t\t}\n\t},\n\tcomponentAvailable:function(component){\n\t\tthis.components[component].loaded = true;\n\t\tif(this.listener){\n\t\t\tthis.listener(component);\n\t\t};\n\t}\n};\n\nThis allows you to write a main listener function that acts when certain components have been loaded, for example:\n\nmyAwesomeApp.listener = function(component){\n\tif(component === 'gallery'){\n\t showGallery();\n\t}\n};\n\nExtending with other components\n\nAs the main object is public, other developers can extend the components object with own components and use the listener function to load dependent components. Say you have a bespoke component with data and labels in extra files:\n\nmyAwesomeApp.listener = function(component){\n\tif(component === 'bespokecomponent'){\n\t\tmyAwesomeApp.addComponent('bespokelabels');\n\t};\n\tif(component === 'bespokelabels'){\n\t\tmyAwesomeApp.addComponent('bespokedata');\n\t};\n\tif(component === 'bespokedata'){\n\t\tmyAwesomeApp,bespokecomponent.init();\n\t};\n};\nmyAwesomeApp.components.bespokecomponent = {\n\turl:'bespoke.js',\n\tloaded:false\n};\nmyAwesomeApp.components.bespokelabels = {\n\turl:'bespokelabels.js',\n\tloaded:false\n};\nmyAwesomeApp.components.bespokedata = {\n\turl:'bespokedata.js',\n\tloaded:false\n};\nmyAwesomeApp.addComponent('bespokecomponent');\n\nFollowing this practice you can write pretty complex apps and still have full control over what is available when. You can also extend this to allow for CSS files to be added on demand.\n\nInfluences\n\nIf you like this idea and wondered if someone already uses it, take a look at the Yahoo! User Interface library, and especially at the YAHOO_config option of the global YAHOO.js object.", "year": "2007", "author": "Christian Heilmann", "author_slug": "chrisheilmann", "published": "2007-12-18T00:00:00+00:00", "url": "https://24ways.org/2007/keeping-javascript-dependencies-at-bay/", "topic": "code"} {"rowid": 162, "title": "Conditional Love", "contents": "\u201cBrowser.\u201d The four-letter word of web design.\n\nI mean, let\u2019s face it: on the good days, when things just work in your target browsers, it\u2019s marvelous. The air smells sweeter, birds\u2019 songs sound more melodious, and both your design and your code are looking sharp.\n\nBut on the less-than-good days (which is, frankly, most of them), you\u2019re compelled to tie up all your browsers in a sack, heave them into the nearest river, and start designing all-imagemap websites. We all play favorites, after all: some will swear by Firefox, Opera fans are allegedly legion, and others still will frown upon anything less than the latest WebKit nightly.\n\nThankfully, we do have an out for those little inconsistencies that crop up when dealing with cross-browser testing: CSS patches.\n\nSpare the Rod, Hack the Browser\n\nBefore committing browsercide over some rendering bug, a designer will typically reach for a snippet of CSS fix the faulty browser. Historically referred to as \u201chacks,\u201d I prefer Dan Cederholm\u2019s more client-friendly alternative, \u201cpatches\u201d.\n\nBut whatever you call them, CSS patches all work along the same principle: supply the proper property value to the good browsers, while giving higher maintenance other browsers an incorrect value that their frustrating idiosyncratic rendering engine can understand.\n\nTraditionally, this has been done either by exploiting incomplete CSS support:\n\n#content {\n\theight: 1%;\t // Let's force hasLayout for old versions of IE.\n\tline-height: 1.6;\n\tpadding: 1em;\n}\nhtml>body #content {\n\theight: auto; // Modern browsers get a proper height value.\n}\n\nor by exploiting bugs in their rendering engine to deliver alternate style rules:\n\n#content p {\n\tfont-size: .8em;\n\t/* Hide from Mac IE5 \\*/\n\tfont-size: .9em;\n\t/* End hiding from Mac IE5 */\n}\n\nWe\u2019ve even used these exploits to serve up whole stylesheets altogether:\n\n@import url(\"core.css\");\n@media tty {\n\ti{content:\"\\\";/*\" \"*/}} @import 'windows-ie5.css'; /*\";}\n}/* */\n\nThe list goes on, and on, and on. For every browser, for every bug, there\u2019s a patch available to fix some rendering bug.\n\nBut after some time working with standards-based layouts, I\u2019ve found that CSS patches, as we\u2019ve traditionally used them, become increasingly difficult to maintain. As stylesheets are modified over the course of a site\u2019s lifetime, inline fixes we\u2019ve written may become obsolete, making them difficult to find, update, or prune out of our CSS. A good patch requires a constant gardener to ensure that it adds more than just bloat to a stylesheet, and inline patches can be very hard to weed out of a decently sized CSS file.\n\nGiving the Kids Separate Rooms\n\nSince I joined Airbag Industries earlier this year, every project we\u2019ve worked on has this in the head of its templates:\n\n\n\n\n\nThe first element is, simply enough, a link element that points to the project\u2019s main CSS file. No patches, no hacks: just pure, modern browser-friendly style rules. Which, nine times out of ten, will net you a design that looks like spilled eggnog in various versions of Internet Explorer.\n\nBut don\u2019t reach for the mulled wine quite yet. Immediately after, we\u2019ve got a brace of conditional comments wrapped around two other link elements. These odd-looking comments allow us to selectively serve up additional stylesheets just to the version of IE that needs them. We\u2019ve got one for IE 6 and below:\n\n\n\nAnd another for IE7 and above:\n\n\n\nMicrosoft\u2019s conditional comments aren\u2019t exactly new, but they can be a valuable alternative to cooking CSS patches directly into a master stylesheet. And though they\u2019re not a W3C-approved markup structure, I think they\u2019re just brilliant because they innovate within the spec: non-IE devices will assume that the comments are just that, and ignore the markup altogether.\n\nThis does, of course, mean that there\u2019s a little extra markup in the head of our documents. But this approach can seriously cut down on the unnecessary patches served up to the browsers that don\u2019t need them. Namely, we no longer have to write rules like this in our main stylesheet:\n\n#content {\n\theight: 1%;\t// Let's force hasLayout for old versions of IE.\n\tline-height: 1.6;\n\tpadding: 1em;\n}\nhtml>body #content {\n\theight: auto;\t// Modern browsers get a proper height value.\n}\n\nRather, we can simply write an un-patched rule in our core stylesheet:\n\n#content {\n\tline-height: 1.6;\n\tpadding: 1em;\n}\n\nAnd now, our patch for older versions of IE goes in\u2014you guessed it\u2014the stylesheet for older versions of IE:\n\n#content {\n\theight: 1%;\n}\n\nThe hasLayout patch is applied, our design\u2019s repaired, and\u2014most importantly\u2014the patch is only seen by the browser that needs it. The \u201cgood\u201d browsers don\u2019t have to incur any added stylesheet weight from our IE patches, and Internet Explorer gets the conditional love it deserves.\n\nMost importantly, this \u201ccompartmentalized\u201d approach to CSS patching makes it much easier for me to patch and maintain the fixes applied to a particular browser. If I need to track down a bug for IE7, I don\u2019t need to scroll through dozens or hundreds of rules in my core stylesheet: instead, I just open the considerably slimmer IE7-specific patch file, make my edits, and move right along.\n\nEven Good Children Misbehave\n\nWhile IE may occupy the bulk of our debugging time, there\u2019s no denying that other popular, modern browsers will occasionally disagree on how certain bits of CSS should be rendered. But without something as, well, pimp as conditional comments at our disposal, how do we bring the so-called \u201cgood browsers\u201d back in line with our design?\n\nAssuming you\u2019re loving the \u201cone patch file per browser\u201d model as much as I do, there\u2019s just one alternative: JavaScript.\n\nfunction isSaf() {\n\tvar isSaf = (document.childNodes && !document.all && !navigator.taintEnabled && !navigator.accentColorName) ? true : false;\n\treturn isSaf;\n}\nfunction isOp() {\n\tvar isOp = (window.opera) ? true : false;\n\treturn isOp;\n}\n\nInstead of relying on dotcom-era tactics of parsing the browser\u2019s user-agent string, we\u2019re testing here for support for various DOM objects, whose presence or absence we can use to reasonably infer the browser we\u2019re looking at. So running the isOp() function, for example, will test for Opera\u2019s proprietary window.opera object, and thereby accurately tell you if your user\u2019s running Norway\u2019s finest browser.\n\nWith scripts such as isOp() and isSaf() in place, you can then reasonably test which browser\u2019s viewing your content, and insert additional link elements as needed.\n\nfunction loadPatches(dir) {\n\tif (document.getElementsByTagName() && document.createElement()) {\n\t\tvar head = document.getElementsByTagName(\"head\")[0];\n\t\tif (head) {\n\t\t\tvar css = new Array();\n\t\t\tif (isSaf()) {\n\t\t\t\tcss.push(\"saf.css\");\n\t\t\t} else if (isOp()) {\n\t\t\t\tcss.push(\"opera.css\");\n\t\t\t}\n\t\t\tif (css.length) {\n\t\t\t\tvar link = document.createElement(\"link\");\n\t\t\t\tlink.setAttribute(\"rel\", \"stylesheet\");\n\t\t\t\tlink.setAttribute(\"type\", \"text/css\");\n\t\t\t\tlink.setAttribute(\"media\", \"screen, projection\");\n\t\t\t\tfor (var i = 0; i < css.length; i++) {\n\t\t\t\t\tvar tag = link.cloneNode(true);\n\t\t\t\t\ttag.setAttribute(\"href\", dir + css[0]);\n\t\t\t\t\thead.appendChild(tag);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nHere, we\u2019re testing the results of isSaf() and isOp(), one after the other. For each function that returns true, then the name of a new stylesheet is added to the oh-so-cleverly named css array. Then, for each entry in css, we create a new link element, point it at our patch file, and insert it into the head of our template.\n\nFire it up using your favorite onload or DOMContentLoaded function, and you\u2019re good to go.\n\nScripteat Emptor\n\nAt this point, some of the audience\u2019s more conscientious \u2018scripters may be preparing to lob figgy pudding at this author\u2019s head. And that\u2019s perfectly understandable; relying on JavaScript to patch CSS chafes a bit against the normally clean separation we have between our pages\u2019 content, presentation, and behavior layers.\n\nAnd beyond the philosophical concerns, this approach comes with a few technical caveats attached:\n\nBrowser detection? So un-133t.\n\nBrowser detection is not something I\u2019d typically recommend. Whenever possible, a proper DOM script should check for the support of a given object or method, rather than the device with which your users view your content.\n\nIt\u2019s JavaScript, so don\u2019t count on it being available.\n\nAccording to one site, roughly four percent of Internet users don\u2019t have JavaScript enabled. Your site\u2019s stats might be higher or lower than this number, but still: don\u2019t expect that every member of your audience will see these additional stylesheets, and ensure that your content\u2019s still accessible with JS turned off.\n\nBe a constant gardener.\n\nThe sample isSaf() and isOp() functions I\u2019ve written will tell you if the user\u2019s browser is Safari or Opera. As a result, stylesheets written to patch issues in an old browser may break when later releases repair the relevant CSS bugs.\n\nYou can, of course, add logic to these simple little scripts to serve up version-specific stylesheets, but that way madness may lie. In any event, test your work vigorously, and keep testing it when new versions of the targeted browsers come out. Make sure that a patch written today doesn\u2019t become a bug tomorrow.\n\nPatching Firefox, Opera, and Safari isn\u2019t something I\u2019ve had to do frequently: still, there have been occasions where the above script\u2019s come in handy. Between conditional comments, careful CSS auditing, and some judicious JavaScript, browser-based bugs can be handled with near-surgical precision.\n\nSo pass the \u2018nog. It\u2019s patchin\u2019 time.", "year": "2007", "author": "Ethan Marcotte", "author_slug": "ethanmarcotte", "published": "2007-12-15T00:00:00+00:00", "url": "https://24ways.org/2007/conditional-love/", "topic": "code"} {"rowid": 163, "title": "Get To Grips with Slippy Maps", "contents": "Online mapping has definitely hit mainstream. Google Maps made \u2018slippy maps\u2019 popular and made it easy for any developer to quickly add a dynamic map to his or her website. You can now find maps for store locations, friends nearby, upcoming events, and embedded in blogs. \n\nIn this tutorial we\u2019ll show you how to easily add a map to your site using the Mapstraction mapping library. There are many map providers available to choose from, each with slightly different functionality, design, and terms of service. Mapstraction makes deciding which provider to use easy by allowing you to write your mapping code once, and then easily switch providers.\n\nAssemble the pieces\n\nUtilizing any of the mapping library typically consists of similar overall steps:\n\n\n\tCreate an HTML div to hold the map\n\tInclude the Javascript libraries\n\tCreate the Javascript Map element\n\tSet the initial map center and zoom level\n\tAdd markers, lines, overlays and more\n\n\nCreate the Map Div\n\nThe HTML div is where the map will actually show up on your page. It needs to have a unique id, because we\u2019ll refer to that later to actually put the map here. This also lets you have multiple maps on a page, by creating individual divs and Javascript map elements. The size of the div also sets the height and width of the map. You set the size using CSS, either inline with the element, or via a CSS reference to the element id or class. For this example, we\u2019ll use inline styling.\n\n
      \n\nInclude Javascript libraries\n\nA mapping library is like any Javascript library. You need to include the library in your page before you use the methods of that library. For our tutorial, we\u2019ll need to include at least two libraries: Mapstraction, and the mapping API(s) we want to display. Our first example we\u2019ll use the ubiquitous Google Maps library. However, you can just as easily include Yahoo, MapQuest, or any of the other supported libraries.\n\nAnother important aspect of the mapping libraries is that many of them require an API key. You will need to agree to the terms of service, and get an API key these.\n\n\n\n\nCreate the Map\n\nGreat, we\u2019ve now put in all the pieces we need to start actually creating our map. This is as simple as creating a new Mapstraction object with the id of the HTML div we created earlier, and the name of the mapping provider we want to use for this map. \n\nWith several of the mapping libraries you will need to set the map center and zoom level before the map will appear. The map centering actually triggers the initialization of the map. \n\nvar mapstraction = new Mapstraction('map','google');\nvar myPoint = new LatLonPoint(37.404,-122.008);\nmapstraction.setCenterAndZoom(myPoint, 10);\n\nA note about zoom levels. The setCenterAndZoom function takes two parameters, the center as a LatLonPoint, and a zoom level that has been defined by mapping libraries. The current usage is for zoom level 1 to be \u201czoomed out\u201d, or view the entire earth \u2013 and increasing the zoom level as you zoom in. Typically 17 is the maximum zoom, which is about the size of a house. \n\nDifferent mapping providers have different quality of zoomed in maps over different parts of the world. This is a perfect reason why using a library like Mapstraction is very useful, because you can quickly change mapping providers to accommodate users in areas that have bad coverage with some maps. \n\nTo switch providers, you just need to include the Javascript library, and then change the second parameter in the Mapstraction creation. Or, you can call the switch method to dynamically switch the provider.\n\nSo for Yahoo Maps (demo):\n\nvar mapstraction = new Mapstraction('map','yahoo');\n\nor Microsoft Maps (demo):\n\nvar mapstraction = new Mapstraction('map','microsoft');\n\nwant a 3D globe in your browser? try FreeEarth (demo):\n\nvar mapstraction = new Mapstraction('map','freeearth');\n\nor even OpenStreetMap (free your data!) (demo):\n\nvar mapstraction = new Mapstraction('map','openstreetmap');\n\nVisit the Mapstraction multiple map demo page for an example of how easy it is to have many maps on your page, each with a different provider. \n\nAdding Markers\n\nWhile adding your first map is fun, and you can probably spend hours just sliding around, the point of adding a map to your site is usually to show the location of something. So now you want to add some markers. There are a couple of ways to add to your map.\n\nThe simplest is directly creating markers. You could either hard code this into a rather static page, or dynamically generate these using whatever tools your site is built on.\n\nvar marker = new Marker( new LatLonPoint(37.404,-122.008) );\nmarker.setInfoBubble(\"It's easy to add maps to your site\");\nmapstraction.addMarker( marker );\n\nThere is a lot more you can do with markers, including changing the icon, adding timestamps, automatically opening the bubble, or making them draggable. \n\nWhile it is straight-forward to create markers one by one, there is a much easier way to create a large set of markers. And chances are, you can make it very easy by extending some data you already are sharing: RSS. \n\nSpecifically, using GeoRSS you can easily add a large set of markers directly to a map. GeoRSS is a community built standard (like Microformats) that added geographic markup to RSS and Atom entries. It\u2019s as simple as adding 42 -83 to your feeds to share items via GeoRSS. Once you\u2019ve done that, you can add that feed as an \u2018overlay\u2019 to your map using the function:\n\nmapstraction.addOverlay(\"http://api.flickr.com/services/feeds/groups_pool.gne?id=322338@N20&format=rss_200&georss=1\");\n\nMapstraction also supports KML for many of the mapping providers. So it\u2019s easy to add various data sources together with your own data. Check out Mapufacture for a growing index of available GeoRSS feeds and KML documents. \n\nPlay with your new toys\n\nMapstraction offers a lot more functionality you can utilize for demonstrating a lot of geographic data on your website. It also includes geocoding and routing abstraction layers for making sure your users know where to go. You can see more on the Mapstraction website: http://mapstraction.com.", "year": "2007", "author": "Andrew Turner", "author_slug": "andrewturner", "published": "2007-12-02T00:00:00+00:00", "url": "https://24ways.org/2007/get-to-grips-with-slippy-maps/", "topic": "code"} {"rowid": 164, "title": "My Other Christmas Present Is a Definition List", "contents": "A note from the editors: readers should note that the HTML5 redefinition of definition lists has come to pass and is now \u00e0 la mode.\n \n \n \n Last year, I looked at how the markup for tag clouds was generally terrible. I thought this year I would look not at a method of marking up a common module, but instead just at a simple part of HTML and how it generally gets abused.\n\nNo, not tables. Definition lists. Ah, definition lists. Often used but rarely understood.\n\nExamining the definition of definitions\n\nTo start with, let\u2019s see what the HTML spec has to say about them.\n\n\n\tDefinition lists vary only slightly from other types of lists in that list items consist of two parts: a term and a description.\n\n\nThe canonical example of a definition list is a dictionary. Words can have multiple descriptions (even the word definition has at least five). Also, many terms can share a single definition (for example, the word colour can also be spelt color, but they have the same definition).\n\nExcellent, we can all grasp that. But it very quickly starts to fall apart. Even in the HTML specification the definition list is mis-used.\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\nWrong. Completely and utterly wrong. This is the biggest flaw in the HTML spec, along with dropping support for the start attribute on ordered lists. \u201cWhy?\u201d, you may ask. Let me give you an example from Romeo and Juliet, act 2, scene 2.\n\n
      Juliet
      \n\t
      Romeo!
      \n
      Romeo
      \n\t
      My niesse?
      \n
      Juliet
      \n\t
      At what o'clock tomorrow shall I send to thee?
      \n
      Romeo
      \n\t
      At the hour of nine.
      \n\nNow, the problem here is that a given definition can have multiple descriptions (the DD). Really the dialog \u201cdescriptions\u201d should be rolled up under the terms, like so:\n\n
      Juliet
      \n\t
      Romeo!
      \n\t
      At what o'clock tomorrow shall I send to thee?
      \n
      Romeo
      \n\t
      My niesse?
      \n\t
      At the hour of nine.
      \n\nSuddenly the play won\u2019t make anywhere near as much sense. (If it\u2019s anything, the correct markup for a play is an ordered list of CITE and BLOCKQUOTE elements.)\n\nThis is the first part of the problem. That simple example has turned definition lists in everyone\u2019s mind from pure definitions to more along the lines of a list with pre-configured heading(s) and text(s).\n\nScreen reader, enter stage left.\n\nIn many screen readers, a simple definition list would be read out as \u201cdefinition term equals definition description\u201d. So in our play excerpt, Juliet equals Romeo! That\u2019s not right, either. But this also leads a lot of people astray with definition lists to believing that they are useful for key/value pairs.\n\nBehaviour and convention\n\nThe WHAT-WG have noticed the common mis-use of the DL, and have codified it into the new spec. In the HTML5 draft, a definition list is no longer a definition list.\n\n\n\tThe dl element introduces an unordered association list consisting of zero or more name-value groups (a description list). Each group must consist of one or more names (dt elements) followed by one or more values (dd elements).\n\n\nThey also note that the \u201cdl element is inappropriate for marking up dialogue, since dialogue is ordered\u201d. So for that example they have created a DIALOG (sic) element.\n\nStrange, then, that they keep DL as-is but instead refer to it an \u201cassociation list\u201d. They have not created a new AL element, and kept DL for the original purpose. They have chosen not to correct the usage or to create a new opportunity for increased specificity in our HTML, but to \u201cpave the cowpath\u201d of convention.\n\nHow to use a definition list\n\nGiven that everyone else is using a DL incorrectly, should we? Well, if they all jumped off a bridge, would you too? No, of course you wouldn\u2019t. We don\u2019t have HTML5 yet, so we\u2019re stuck with the existing semantics of HTML4 and XHTML1. Which means that:\n\n\n\tListing dialogue is not defining anything.\n\tListing the attributes of a piece of hardware (resolution = 1600\u00d71200) is illustrating sample values, not defining anything (however, stating what \u2018resolution\u2019 actually means in this context would be a definition).\n\tListing the cast and crew of a given movie is not defining the people involved in making movies. (Stuart Gordon may have been the director of Space Truckers, but that by no means makes him the true definition of a director.)\n\tA menu of navigation items is simply a nested ordered or unordered list of links, not a definition list.\n\tApplying styling handles to form labels and elements is not a good use for a definition list.\n\n\nAnd so on.\n\nLiving by the specification, a definition list should be used for term definitions \u2013 glossaries, lexicons and dictionaries \u2013 only.\n\nAnything else is a crime against markup.", "year": "2007", "author": "Mark Norman Francis", "author_slug": "marknormanfrancis", "published": "2007-12-05T00:00:00+00:00", "url": "https://24ways.org/2007/my-other-christmas-present-is-a-definition-list/", "topic": "code"} {"rowid": 165, "title": "Transparent PNGs in Internet Explorer 6", "contents": "Newer breeds of browser such as Firefox and Safari have offered support for PNG images with full alpha channel transparency for a few years. With the use of hacks, support has been available in Internet Explorer 5.5 and 6, but the hacks are non-ideal and have been tricky to use. With IE7 winning masses of users from earlier versions over the last year, full PNG alpha-channel transparency is becoming more of a reality for day-to-day use.\n\nHowever, there are still numbers of IE6 users out there who we can\u2019t leave out in the cold this Christmas, so in this article I\u2019m going to look what we can do to support IE6 users whilst taking full advantage of transparency for the majority of a site\u2019s visitors.\n\nSo what\u2019s alpha channel transparency?\n\nCast your minds back to the Ghost of Christmas Past, the humble GIF. Images in GIF format offer transparency, but that transparency is either on or off for any given pixel. Each pixel\u2019s either fully transparent, or a solid colour. In GIF, transparency is effectively just a special colour you can chose for a pixel.\n\nThe PNG format tackles the problem rather differently. As well as having any colour you chose, each pixel also carries a separate channel of information detailing how transparent it is. This alpha channel enables a pixel to be fully transparent, fully opaque, or critically, any step in between.\n\nThis enables designers to produce images that can have, for example, soft edges without any of the \u2018halo effect\u2019 traditionally associated with GIF transparency. If you\u2019ve ever worked on a site that has different colour schemes and therefore requires multiple versions of each graphic against a different colour, you\u2019ll immediately see the benefit. \n\nWhat\u2019s perhaps more interesting than that, however, is the extra creative freedom this gives designers in creating beautiful sites that can remain web-like in their ability to adjust, scale and reflow.\n\nThe Internet Explorer problem\n\nUp until IE7, there has been no fully native support for PNG alpha channel transparency in Internet Explorer. However, since IE5.5 there has been some support in the form of proprietary filter called the AlphaImageLoader. Internet Explorer filters can be applied directly in your CSS (for both inline and background images), or by setting the same CSS property with JavaScript. \n\nCSS:\n\nimg {\n\tfilter: progid:DXImageTransform.Microsoft.AlphaImageLoader(...);\n}\n\nJavaScript:\n\nimg.style.filter = \"progid:DXImageTransform.Microsoft.AlphaImageLoader(...)\";\n\nThat may sound like a problem solved, but all is not as it may appear. Firstly, as you may realise, there\u2019s no CSS property called filter in the W3C CSS spec. It\u2019s a proprietary extension added by Microsoft that could potentially cause other browsers to reject your entire CSS rule. \n\nSecondly, AlphaImageLoader does not magically add full PNG transparency support so that a PNG in the page will just start working. Instead, when applied to an element in the page, it draws a new rendering surface in the same space that element occupies and loads a PNG into it. If that sounds weird, it\u2019s because that\u2019s precisely what it is. However, by and large the result is that PNGs with an alpha channel can be accommodated.\n\nThe pitfalls\n\nSo, whilst support for PNG transparency in IE5.5 and 6 is possible, it\u2019s not without its problems.\n\nBackground images cannot be positioned or repeated\n\nThe AlphaImageLoader does work for background images, but only for the simplest of cases. If your design requires the image to be tiled (background-repeat) or positioned (background-position) you\u2019re out of luck. The AlphaImageLoader allows you to set a sizingMethod to either crop the image (if necessary) or to scale it to fit. Not massively useful, but something at least.\n\nDelayed loading and resource use\n\nThe AlphaImageLoader can be quite slow to load, and appears to consume more resources than a standard image when applied. Typically, you\u2019d need to add thousands of GIFs or JPEGs to a page before you saw any noticeable impact on the browser, but with the AlphaImageLoader filter applied Internet Explorer can become sluggish after just a handful of alpha channel PNGs.\n\nThe other noticeable effect is that as more instances of the AlphaImageLoader are applied, the longer it takes to render the PNGs with their transparency. The user sees the PNG load in its original non-supported state (with black or grey areas where transparency should be) before one by one the filter kicks in and makes them properly transparent.\n\nBoth the issue of sluggish behaviour and delayed load only really manifest themselves with volume and size of image. Use just a couple of instances and it\u2019s fine, but be careful adding more than five or six. As ever, test, test, test.\n\nLinks become unclickable, forms unfocusable \n\nThis is a big one. There\u2019s a bug/weirdness with AlphaImageLoader that sometimes prevents interaction with links and forms when a PNG background image is used. This is sometimes reported as a z-index issue, but I don\u2019t believe it is. Rather, it\u2019s an artefact of that weird way the filter gets applied to the document almost outside of the normal render process. \n\nOften this can be solved by giving the links or form elements hasLayout using position: relative; where possible. However, this doesn\u2019t always work and the non-interaction problem cannot always be solved. You may find yourself having to go back to the drawing board.\n\nSidestepping the danger zones\n\nFrankly, it\u2019s pretty bad news if you design a site, have that design signed off by your client, build it and then find out only at the end (because you don\u2019t know what might trigger a problem) that your search field can\u2019t be focused in IE6. That\u2019s an absolute nightmare, and whilst it\u2019s not likely to happen, it\u2019s possible that it might. It\u2019s happened to me. So what can you do?\n\nThe best approach I\u2019ve found to this scenario is\n\n\n\tIsolate the PNG or PNGs that are causing the problem. Step through the PNGs in your page, commenting them out one by one and retesting. Typically it\u2019ll be the nearest PNG to the problem, so try there first. Keep going until you can click your links or focus your form fields.\n\tThis is where you really need luck on your side, because you\u2019re going to have to fake it. This will depend on the design of the site, but some way or other create a replacement GIF or JPEG image that will give you an acceptable result. Then use conditional comments to serve that image to only users of IE older than version 7.\n\n\nA hack, you say? Well, you started it chum.\n\nApplying AlphaImageLoader\n\nBecause the filter property is invalid CSS, the safest pragmatic approach is to apply it selectively with JavaScript for only Internet Explorer versions 5.5 and 6. This helps ensure that by default you\u2019re serving standard CSS to browsers that support both the CSS and PNG standards correct, and then selectively patching up only the browsers that need it. \n\nSeveral years ago, Aaron Boodman wrote and released a script called sleight for doing just that. However, sleight dealt only with images in the page, and not background images applied with CSS. Building on top of Aaron\u2019s work, I hacked sleight and came up with bgsleight for applying the filter to background images instead. That was in 2003, and over the years I\u2019ve made a couple of improvements here and there to keep it ticking over and to resolve conflicts between sleight and bgsleight when used together. However, with alpha channel PNGs becoming much more widespread, it\u2019s time for a new version.\n\nIntroducing SuperSleight\n\nSuperSleight adds a number of new and useful features that have come from the day-to-day needs of working with PNGs.\n\n\n\tWorks with both inline and background images, replacing the need for both sleight and bgsleight\n\tWill automatically apply position: relative to links and form fields if they don\u2019t already have position set. (Can be disabled.)\n\tCan be run on the entire document, or just a selected part where you know the PNGs are. This is better for performance.\n\tDetects background images set to no-repeat and sets the scaleMode to crop rather than scale.\n\tCan be re-applied by any other JavaScript in the page \u2013 useful if new content has been loaded by an Ajax request.\n\n\n Download SuperSleight \n\nImplementation\n\nGetting SuperSleight running on a page is quite straightforward, you just need to link the supplied JavaScript file (or the minified version if you prefer) into your document inside conditional comments so that it is delivered to only Internet Explorer 6 or older.\n\n\n\nSupplied with the JavaScript is a simple transparent GIF file. The script replaces the existing PNG with this before re-layering the PNG over the top using AlphaImageLoaded. You can change the name or path of the image in the top of the JavaScript file, where you\u2019ll also find the option to turn off the adding of position: relative to links and fields if you don\u2019t want that.\n\nThe script is kicked off with a call to supersleight.init() at the bottom. The scope of the script can be limited to just one part of the page by passing an ID of an element to supersleight.limitTo(). And that\u2019s all there is to it.\n\nUpdate March 2008: a version of this script as a jQuery plugin is also now available.", "year": "2007", "author": "Drew McLellan", "author_slug": "drewmclellan", "published": "2007-12-01T00:00:00+00:00", "url": "https://24ways.org/2007/supersleight-transparent-png-in-ie6/", "topic": "code"} {"rowid": 166, "title": "Performance On A Shoe String", "contents": "Back in the summer, I happened to notice the official Wimbledon All England Tennis Club site had jumped to the top of Alexa\u2019s Movers & Shakers list \u2014 a list that tracks sites that have had the biggest upturn or downturn in traffic. The lawn tennis championships were underway, and so traffic had leapt from almost nothing to crazy-busy in a no time at all. \n\nMany sites have similar peaks in traffic, especially when they\u2019re based around scheduled events. No one cares about the site for most of the year, and then all of a sudden \u2013 wham! \u2013 things start getting warm in the data centre. Whilst the thought of chestnuts roasting on an open server has a certain appeal, it\u2019s less attractive if you care about your site being available to visitors. Take a look at this Alexa traffic graph showing traffic patterns for superbowl.com at the beginning of each year, and wimbledon.org in the month of July.\n\nTraffic graph from Alexa.com \n\nWhilst not on the same scale or with such dramatic peaks, we have a similar pattern of traffic here at 24ways.org. Over the last three years we\u2019ve seen a dramatic pick up in traffic over the month of December (as would be expected) and then a much lower, although steady load throughout the year. What we do have, however, is the luxury of knowing when the peaks will be. For a normal site, be that a blog, small scale web app, or even a small corporate site, you often just cannot predict when you might get slashdotted, end up on the front page of Digg or linked to from a similarly high-profile site. You just don\u2019t know when the peaks will be.\n\nIf you\u2019re a big commercial enterprise like the Super Bowl, scaling up for that traffic is simply a cost of doing business. But for most of us, we can\u2019t afford to have massive capacity sat there unused for 90% of the year. What you have to do instead is work out how to deal with as much traffic as possible with the modest resources you have.\n\nIn this article I\u2019m going to talk about some of the things we\u2019ve learned about keeping 24 ways running throughout December, whilst not spending a fortune on hosting we don\u2019t need for 11 months of each year. We\u2019ve not always got it right, but we\u2019ve learned a lot along the way.\n\nThe Problem\n\nTo know how to deal with high traffic, you need to have a basic idea of what happens when a request comes into a web server. 24 ways is hosted on a single small virtual dedicated server with a great little hosting company in the UK. We run Apache with PHP and MySQL all on that one server. When a request comes in a new Apache process is started to deal with the request (or assigned if there\u2019s one available not doing anything). Each process takes a bunch of memory, so there\u2019s a finite number of processes that you can run, and therefore a finite number of pages you can serve at once before your server runs out of memory.\n\nWith our budget based on whatever is left over after beer, we need to get best performance we can out of the resources available. As the goal is to serve as many pages as quickly as possible, there are several approaches we can take:\n\n\n\tReducing the amount of memory needed by each Apache process\n\tReducing the amount of time each process is needed\n\tReducing the number of requests made to the server\n\n\nYahoo! have published some information on what they call Exceptional Performance, which is well worth reading, and compliments many of my examples here. The Yahoo! guidelines very much look at things from a user perspective, which is always important.\n\nServer tweaking\n\nIf you\u2019re in the position of being able to change your server configuration (our set-up gives us root access to what is effectively a virtual machine) there are some basic steps you can take to maximise the available memory and reduce the memory footprint. Without getting too boring and technical (whole books have been written on this) there are a couple of things to watch out for.\n\nFirstly, check what processes you have running that you might not need. Every megabyte of memory that you free up might equate to several thousand extra requests being served each day, so take a look at top and see what\u2019s using up your resources. Quite often a machine configured as a web server will have some kind of mail server running by default. If your site doesn\u2019t use mail (ours doesn\u2019t) make sure it\u2019s shut down and not using resources.\n\nSecondly, have a look at your Apache configuration and particularly what modules are loaded. The method for doing this varies between versions of Apache, but again, every module loaded increases the amount of memory that each Apache process requires and therefore limits the number of simultaneous requests you can deal with.\n\nThe final thing to check is that Apache isn\u2019t configured to start more servers than you have memory for. This is usually done by setting the MaxClients directive. When that limit is reached, your site is going to stop responding to further requests. However, if all else goes well that threshold won\u2019t be reached, and if it does it will at least stop the weight of the traffic taking the entire server down to a point where you can\u2019t even log in to sort it out.\n\nThose are the main tidbits I\u2019ve found useful for this site, although it\u2019s worth repeating that entire books have been written on this subject alone.\n\nCaching\n\nAlthough the site is generated with PHP and MySQL, the majority of pages served don\u2019t come from the database. The process of compiling a page on-the-fly involves quite a few trips to the database for content, templates, configuration settings and so on, and so can be slow and require a lot of CPU. Unless a new article or comment is published, the site doesn\u2019t actually change between requests and so it makes sense to generate each page once, save it to a file and then just serve all following requests from that file.\n\nWe use QuickCache (or rather a plugin based on it) for this. The plugin integrates with our publishing system (Textpattern) to make sure the cache is cleared when something on the site changes. A similar plugin called WP-Cache is available for WordPress, but of course this could be done any number of ways, and with any back-end technology.\n\nThe important principal here is to reduce the time it takes to serve a page by compiling the page once and serving that cached result to subsequent visitors. Keep away from your database if you can.\n\nOutsource your feeds\n\nWe get around 36,000 requests for our feed each day. That really only works out at about 7,000 subscribers averaging five-and-a-bit requests a day, but it\u2019s still 36,000 requests we could easily do without. Each request uses resources and particularly during December, all those requests can add up. \n\nThe simple solution here was to switch our feed over to using FeedBurner. We publish the address of the FeedBurner version of our feed here, so those 36,000 requests a day hit FeedBurner\u2019s servers rather than ours. In addition, we get pretty graphs showing how the subscriber-base is building.\n\n\n\nOff-load big files\n\nLarger files like images or downloads pose a problem not in bandwidth, but in the time it takes them to transfer. A typical page request is very quick, a few seconds at the most, resulting in the connection being freed up promptly. Anything that keeps a connection open for a long time is going to start killing performance very quickly.\n\nThis year, we started serving most of the images for articles from a subdomain \u2013 media.24ways.org. Rather than pointing to our own server, this subdomain points to an Amazon S3 account where the files are held. It\u2019s easy to pigeon-hole S3 as merely an online backup solution, and whilst not a fully fledged CDN, S3 works very nicely for serving larger media files. The roughly 20GB of files served this month have cost around $5 in Amazon S3 charges. That\u2019s so affordable it may not be worth even taking the files back off S3 once December has passed.\n\nI found this article on Scalable Media Hosting with Amazon S3 to be really useful in getting started. I upload the files via a Firefox plugin (mentioned in the article) and then edit the ACL to allow public access to the files. The way S3 enables you to point DNS directly at it means that you\u2019re not tied to always using the service, and that it can be transparent to your users.\n\nIf your site uses photographs, consider uploading them to a service like Flickr and serving them directly from there. Many photo sharing sites are happy for you to link to images in this way, but do check the acceptable use policies in case you need to provide a credit or link back.\n\nOff-load small files\n\nYou\u2019ll have noticed the pattern by now \u2013 get rid of as much traffic as possible. When an article has a lot of comments and each of those comments has an avatar along with it, a great many requests are needed to fetch each of those images. In 2006 we started using Gravatar for avatars, but their servers were slow and were holding up page loads. To get around this we started caching the images on our server, but along with that came the burden of furnishing all the image requests.\n\nEarlier this year Gravatar changed hands and is now run by the same team behind WordPress.com. Those guys clearly know what they\u2019re doing when it comes to high performance, so this year we went back to serving avatars directly from them.\n\nIf your site uses avatars, it really makes sense to use a service like Gravatar where your users probably already have an account, and where the image requests are going to be dealt with for you. \n\nKnow what you\u2019re paying for\n\nThe server account we use for 24 ways was opened in November 2005. When we first hit the front page of Digg in December of that year, we upgraded the server with a bit more memory, but other than that we were still running on that 2005 spec for two years. Of course, the world of technology has moved on in those years, prices have dropped and specs have improved. For the same amount we were paying for that 2005 spec server, we could have an account with twice the CPU, memory and disk space.\n\nSo in November of this year I took out a new account and transferred the site from the old server to the new. In that single step we were prepared for dealing with twice the amount of traffic, and because of a special offer at the time I didn\u2019t even have to pay the setup cost on the new server. So it really pays to know what you\u2019re paying for and keep an eye out of ways you can make improvements without needing to spend more money.\n\nFurther steps\n\nThere\u2019s nearly always more that can be done. For example, there are some media files (particularly for older articles) that are not on S3. We also serve our CSS directly and it\u2019s not minified or compressed. But by tackling the big problems first we\u2019ve managed to reduce load on the server and at the same time make sure that the load being placed on the server can be dealt with in the most frugal way.\n\nOver the last 24 days we\u2019ve served up articles to more than 350,000 visitors without breaking a sweat. On a busy day, that\u2019s been nearly 20,000 visitors in just 24 hours. While in the grand scheme of things that\u2019s not a huge amount of traffic, it can be a lot if you\u2019re not prepared for it. However, with a little planning for the peaks you can help ensure that when the traffic arrives you\u2019re ready to capitalise on it.\n\nOf course, people only visit 24 ways for the wealth of knowledge and experience that\u2019s tied up in the articles here. Therefore I\u2019d like to take the opportunity to thank all our authors this year who have given their time as a gift to the community, and to wish you all a very happy Christmas.", "year": "2007", "author": "Drew McLellan", "author_slug": "drewmclellan", "published": "2007-12-24T00:00:00+00:00", "url": "https://24ways.org/2007/performance-on-a-shoe-string/", "topic": "ux"} {"rowid": 167, "title": "Back To The Future of Print", "contents": "By now we have weathered the storm that was the early days of web development, a dangerous time when we used tables, inline CSS and separate pages for print only versions. We can reflect in a haggard old sea-dog manner (\u201cyarrr\u2026 I remember back in the browser wars\u2026\u201d) on the bad practices of the time. We no longer need convincing that print stylesheets are the way to go1, though some of the documentation for them is a little outdated now.\n\nI am going to briefly cover 8 tips and 4 main gotchas when creating print stylesheets in our more enlightened era.\n\nGetting started\n\nAs with regular stylesheets, print CSS can be included in a number of ways2, for our purposes we are going to be using the link\nelement.\n\n\n\nThis is still my favourite way of linking to CSS files, its easy to see what files are being included and to what media they are being applied to. Without the media attribute specified the link element defaults to the media type \u2018all\u2019 which means that the styles within then apply to print and screen alike. The media type \u2018screen\u2019 only applies to the screen and wont be picked up by print, this is the best way of hiding styles from print.\n\nMake sure you include your print styles after all your other CSS, because you will need to override certain rules and this is a lot easier if you are flowing with the cascade than against it!\n\nAnother thing you should be thinking is \u2018does it need to be printed\u2019. Consider the context3, if it is not a page that is likely to be printed, such as a landing page or a section index then the print styles should resemble the way the page looks on the screen.\n\nContext is really important for the design of your print stylesheet, all the tips and tricks that follow should be taken in the context of the page. If for example you are designing a print stylesheet for an item in a shopping cart, it is irrelevant for the user to know the exact url of the link that takes them to your checkout.\n\nTips and tricks\n\nDuring these tip\u2019s we are going to build up print styles for a textileRef:11112857385470b854b8411:linkStartMarker:\u201csimple\nexample\u201d:/examples/back-to-the-future-of-print/demo-1.html\n\n1. Remove the cruft\n\nFirst things first, navigation, headers and most page furniture are pretty much useless and dead space in print so they will need to be removed, using display:none;.\n\n2. Linearise your content\n\nContent doesn\u2019t work so well in columns in print, especially if the content columns are long and intend to stretch over multiple columns (as mentioned in the gotcha section below). You might want to consider Lineariseing the content to flow down the page. If you have your source order in correct priority this will make things a lot easier4.\n\n3. Improve your type\n\nOnce you have removed all the useless cruft and jiggled things about a bit, you can concentrate more on the typography of the page.\n\nTypography is a complex topic5, but simply put serif-ed fonts such as Georgia work better on print and sans serif-ed fonts such as Verdana are more appropriate for screen use. You will probably want to increase font size and line height and change from px to pt (which is specifically a print measurement).\n\n4. Go wild on links\n\nThere are some incredibly fun things you can do with links in print using CSS. There are two schools of thought, one that consider it is best to disguise inline links as body text because they are not click-able on paper. Personally I believe it is useful to know for reference that the document did link to somewhere originally.\n\nWhen deciding which approach to take, consider the context of your document, do people need to know where they would have gone to? will it help or hinder them to know this information? Also for an alternative to the below, take a look at Aaron Gustafson\u2019s article on generating footnotes for print6.\n\nUsing some clever selector trickery and CSS generated content you can have the location of the link generated after the link itself.\n\nHTML:\n\n

      I wish Google could find my keys

      \n\nCSS:\n\na:link:after,\na:visited:after,\na:hover:after,\na:active:after {\n\tcontent: \" <\" attr(href) \"> \";\n}\n\nBut this is not perfect, in the above example the content of the href is just naively plonked after the link text:\n\nI wish Google would find my keys \n\nAs looking back over this printout the user is not immediately aware of the location of the link, a better solution is to use even more crazy selectors to deal with relative links. We can also add a style to the generated content so it is distinguishable from the link text itself.\n\nCSS:\n\na:link:after,\na:visited:after,\na:hover:after,\na:active:after {\n\tcontent: \" <\" attr(href) \"> \";\n\tcolor: grey;\n\tfont-style: italic;\n\tfont-weight: normal;\n}\na[href^=\"/\"]:after {\n\tcontent: \" \";\n}\n\nThe output is now what we were looking for (you will need to replace example.com with your own root URL):\n\nI wish Google would find my keys \n\nUsing regular expressions on the attribute selectors, one final thing you can do is to suppress the generated content on mailto: links, if for example you know the link text always reflects the email address. Eg:\n\nHTML:\n\nme@example.com\n\nCSS:\n\na[href^=\"mailto\"]:after {\n\tcontent: \"\";\n}\n\nThis example shows the above in action.\n\nOf course with this clever technique, there are the usual browser support issues. While it won\u2019t look as intended in browsers such as Internet Explorer 6 and 7 (IE6 and IE7) it will not break either and will just degrade gracefully because IE cannot do generated content. To the best of my knowledge Safari 2+ and Opera 9.X support a colour set on generated content whereas Firefox 2 & Camino display this in black regardless of the link or inherited text colour.\n\n5. Jazz your headers for print\n\nThis is more of a design consideration, don\u2019t go too nuts though; there are a lot more limitations in print media than on screen. For this example we are going to go for is having a bottom border on h2\u2019s and styling other headings with graduating colors or font sizes.\n\nAnd here is the example complete with jazzy headers.\n\n6. Build in general hooks\n\nIf you are building a large site with many different types of page, you may find it useful to build into your CSS structure, classes that control what is printed (e.g. noprint and printonly). This may not be semantically ideal, but in the past I have found it really useful for maintainability of code across large and varied sites\n\n7. For that extra touch of class\n\nWhen printing pages from a long URL, even if the option is turned on to show the location of the page in the header, browsers may still display a truncated (and thus useless) version.\n\nUsing the above tip (or just simply setting to display:none in screen and display:block in print) you can insert the URL of the page you are currently on for print only, using JavaScript\u2019s window.location.href variable.\n\nfunction addPrintFooter() {\n\tvar p = document.createElement('p');\n\tp.className = 'print-footer';\n\tp.innerHTML = window.location.href;\n\tdocument.body.appendChild(p);\n}\n\nYou can then call this function using whichever onload or ondomready handler suits your fancy. Here is our familiar demo to show all the above in action\n\n8. Tabular data across pages\n\nIf you are using tabled data in your document there are a number of things you can do to increase usability of long tables over several pages. If you use the element this should repeat your table headers on the next page should your table be split. You will need to set thead {display: table-header-group;} explicitly for IE even though this should be the default value.\n\nAlso if you use tr {page-break-inside: avoid;} this should (browser support depending) stop your table row from breaking across two pages. For more information on styling tables for print please see the CSS discuss wiki7.\n\nGotchas\n\n1. Where did all my content go?\n\nAbsolutely the most common mistake I see with print styles is the truncated content bug. The symptom of this is that only the first page of a div\u2019s content will be printed, the rest will look truncated after this.\n\nFloating long columns may still have this affect, as mentioned in Eric Meyer\u2019s article on \u2018A List Apart\u2019 article from 20028; though in testing I am no longer able to replicate this. Using overflow:hidden on long content in Firefox however still causes this truncation. Overflow hidden is commonly used to clear floats9.\n\nA simple fix can be applied to resolve this, if the column is floated you can override this with float:none similarly overflow:hidden can be overridden with overflow:visible or the offending rules can be banished to a screen only stylesheet.\n\nUsing position:absolute on long columns also has a very similar effect in truncating the content, but can be overridden in print with position:static;\n\nWhilst I only recommend having a print stylesheet for content pages on your site; do at least check other landing pages, section indexes and your homepage. If these are inaccessible in print possibly due to the above gotcha, it might be wise to provide a light dusting of print styles or move the offending overflow / float rules to a screen only stylesheet to fix the issues.\n\n2. Damn those background browser settings\n\nOne of the factors of life you now need to accept is that you can\u2019t control the user\u2019s browser settings, no more than you can control whether or not they use IE6. Most browsers by default will not print background colours or images unless explicitly told to by the user.\n\nNaturally this causes a number of problems, for starters you will need to rethink things like branding. At this point it helps if you are doing the print styles early in the project so that you can control the logo not being a background image for example.\n\nWhere colour is important to the meaning of the document, for example a status on an invoice, bear in mind that a textural representation will also need to be supplied as the user may be printing in black and white. Borders will print however regardless of setting, so assuming the user is printing in colour you can always use borders to indicate colour.\n\nCheck the colour contrast of the text against white, this may need to be altered without backgrounds. You should check how your page looks with backgrounds turned on too, for consistency with the default browser settings you may want to override your background anyway.\n\nOne final issue with backgrounds being off is list items. It is relatively common practice to suppress the list-style-type and replace with a background image to finely control the bullet positioning. This technique doesn\u2019t translate to print, you will need to disable this background bullet and re-instate your trusty friend the list-style-type.\n\n3. Using JavaScript in your CSS? \u2026 beware IE6\n\nInternet explorer has an issue that when Javascript is used in a stylesheet it applies this to all media types even if only applied to screen. For example, if you happen to be using expressions to set a width for IE, perhaps to mimic min-width, a simple width:100% !important rule can overcome the effects the expression has on your print styles10.\n\n4. De-enhance your Progressive enhancements\n\nQuite a classic \u201cdoh\u201d moment is when you realise that, of course paper doesn\u2019t support Javascript. If you have any dynamic elements on the page, for example a document collapsed per section, you really should have been using Progressive enhancement techniques11 and building for browsers without Javascript first, adding in the fancy stuff later.\n\nIf this is the case it should be trivial to override your wizzy JS styles in your print stylesheet, to display all your content and make it accessible for print, which is by far the best method of achieving this affect.\n\nAnd Finally\u2026\n\nI refer you back to the nature of the document in hand, consider the context of your site and the page. Use the tips here to help you add that extra bit of flair to your printed media.\n\nBe careful you don\u2019t get caught out by the common gotchas, keep the design simple, test cross browser and relish in the medium of print.\n\nFurther Reading\n\n1 For more information constantly updated, please see the CSS discuss wiki on print stylesheets\n\n2 For more information on media types and ways of including CSS please refer to the CSS discuss wiki on Media Stylesheets\n\n3 Eric Meyer talks to ThinkVitamin about the importance of context when designing your print strategy.\n\n4 Mark Boulton describes how he applies a newspaper like print stylesheet to an article in the Guardian website. Mark also has some persuasive arguments that print should not be left to last\n\n5 Richard Rutter Has a fantastic resource on typography which also applies to print.\n\n6 Aaron Gustafson has a great solution to link problem by creating footnotes at the end of the page.\n\n7 The CSS discuss wiki has more detailed information on printing tables and detailed browser support\n\n8 This \u2018A List Apart\u2019 article is dated May 10th 2002 though is still mostly relevant\n\n9 Float clearing technique using \u2018overflow:hidden\u2019\n\n10 Autistic Cuckoo describes the interesting insight with regards to expressions specified for screen in IE6 remaining in print\n\n11 Wikipedia has a good article on the definition of progressive enhancement\n\n12 For a really neat trick involving a dynamically generated column to displaying and meanings (as well as somewhere for the user to write notes), try print previewing on Brian Suda\u2019s site", "year": "2007", "author": "Natalie Downe", "author_slug": "nataliedowne", "published": "2007-12-09T00:00:00+00:00", "url": "https://24ways.org/2007/back-to-the-future-of-print/", "topic": "design"} {"rowid": 168, "title": "Unobtrusively Mapping Microformats with jQuery", "contents": "Microformats are everywhere. You can\u2019t shake an electronic stick these days without accidentally poking a microformat-enabled site, and many developers use microformats as a matter of course. And why not? After all, why invent your own class names when you can re-use pre-defined ones that give your site extra functionality for free?\n\nNevertheless, while it\u2019s good to know that users of tools such as Tails and Operator will derive added value from your shiny semantics, it\u2019s nice to be able to reuse that effort in your own code.\n\nWe\u2019re going to build a map of some of my favourite restaurants in Brighton. Fitting with the principles of unobtrusive JavaScript, we\u2019ll start with a semantically marked up list of restaurants, then use JavaScript to add the map, look up the restaurant locations and plot them as markers.\n\nWe\u2019ll be using a couple of powerful tools. The first is jQuery, a JavaScript library that is ideally suited for unobtrusive scripting. jQuery allows us to manipulate elements on the page based on their CSS selector, which makes it easy to extract information from microformats.\n\nThe second is Mapstraction, introduced here by Andrew Turner a few days ago. We\u2019ll be using Google Maps in the background, but Mapstraction makes it easy to change to a different provider if we want to later.\n\nGetting Started\n\nWe\u2019ll start off with a simple collection of microformatted restaurant details, representing my seven favourite restaurants in Brighton. The full, unstyled list can be seen in restaurants-plain.html. Each restaurant listing looks like this:\n\n
    • \n\t

      Riddle & Finns

      \n\t
      \n\t\t

      12b Meeting House Lane

      \n\t\t

      Brighton, UK

      \n\t\t

      BN1 1HB

      \n\t
      \n\t

      Telephone: +44 (0)1273 323 008

      \n\t

      E-mail: info@riddleandfinns.co.uk

      \n
    • \n\nSince we\u2019re dealing with a list of restaurants, each hCard is marked up inside a list item. Each restaurant is an organisation; we signify this by placing the classes fn and org on the element surrounding the restaurant\u2019s name (according to the hCard spec, setting both fn and org to the same value signifies that the hCard represents an organisation rather than a person).\n\nThe address information itself is contained within a div of class adr. Note that the HTML
      element is not suitable here for two reasons: firstly, it is intended to mark up contact details for the current document rather than generic addresses; secondly, address is an inline element and as such cannot contain the paragraphs elements used here for the address information.\n\nA nice thing about microformats is that they provide us with automatic hooks for our styling. For the moment we\u2019ll just tidy up the whitespace a bit; for more advanced style tips consult John Allsop\u2019s guide from 24 ways 2006.\n\n.vcard p {\n\tmargin: 0;\n}\n.adr {\n\tmargin-bottom: 0.5em;\n}\n\nTo plot the restaurants on a map we\u2019ll need latitude and longitude for each one. We can find this out from their address using geocoding. Most mapping APIs include support for geocoding, which means we can pass the API an address and get back a latitude/longitude point. Mapstraction provides an abstraction layer around these APIs which can be included using the following script tag:\n\n\n\nWhile we\u2019re at it, let\u2019s pull in the other external scripts we\u2019ll be using:\n\n\n\n\n\n\nThat\u2019s everything set up: let\u2019s write some JavaScript!\n\nIn jQuery, almost every operation starts with a call to the jQuery function. The function simulates method overloading to behave in different ways depending on the arguments passed to it. When writing unobtrusive JavaScript it\u2019s important to set up code to execute when the page has loaded to the point that the DOM is available to be manipulated. To do this with jQuery, pass a callback function to the jQuery function itself:\n\njQuery(function() {\n\t// This code will be executed when the DOM is ready\n});\n\nInitialising the map\n\nThe first thing we need to do is initialise our map. Mapstraction needs a div with an explicit width, height and ID to show it where to put the map. Our document doesn\u2019t currently include this markup, but we can insert it with a single line of jQuery code:\n\njQuery(function() {\n\t// First create a div to host the map\n\tvar themap = jQuery('
      ').css({\n\t\t'width': '90%',\n\t\t'height': '400px'\n\t}).insertBefore('ul.restaurants');\n});\n\nWhile this is technically just a single line of JavaScript (with line-breaks added for readability) it\u2019s actually doing quite a lot of work. Let\u2019s break it down in to steps:\n\nvar themap = jQuery('
      ')\n\nHere\u2019s jQuery\u2019s method overloading in action: if you pass it a string that starts with a < it assumes that you wish to create a new HTML element. This provides us with a handy shortcut for the more verbose DOM equivalent:\n\nvar themap = document.createElement('div');\nthemap.id = 'themap';\n\nNext we want to apply some CSS rules to the element. jQuery supports chaining, which means we can continue to call methods on the object returned by jQuery or any of its methods:\n\nvar themap = jQuery('
      ').css({\n\t'width': '90%',\n\t'height': '400px'\n})\n\nFinally, we need to insert our new HTML element in to the page. jQuery provides a number of methods for element insertion, but in this case we want to position it directly before the
        we are using to contain our restaurants. jQuery\u2019s insertBefore() method takes a CSS selector indicating an element already on the page and places the current jQuery selection directly before that element in the DOM.\n\nvar themap = jQuery('
        ').css({\n\t'width': '90%',\n\t'height': '400px'\n}).insertBefore('ul.restaurants');\n\nFinally, we need to initialise the map itself using Mapstraction. The Mapstraction constructor takes two arguments: the first is the ID of the element used to position the map; the second is the mapping provider to use (in this case google ):\n\n// Initialise the map\nvar mapstraction = new Mapstraction('themap','google');\n\nWe want the map to appear centred on Brighton, so we\u2019ll need to know the correct co-ordinates. We can use www.getlatlon.com to find both the co-ordinates and the initial map zoom level.\n\n// Show map centred on Brighton\nmapstraction.setCenterAndZoom(\n\tnew LatLonPoint(50.82423734980143, -0.14007568359375),\n\t15 // Zoom level appropriate for Brighton city centre\n);\n\nWe also want controls on the map to allow the user to zoom in and out and toggle between map and satellite view.\n\nmapstraction.addControls({\n\tzoom: 'large',\n\tmap_type: true\n});\n\nAdding the markers\n\nIt\u2019s finally time to parse some microformats. Since we\u2019re using hCard, the information we want is wrapped in elements with the class vcard. We can use jQuery\u2019s CSS selector support to find them:\n\nvar vcards = jQuery('.vcard');\n\nNow that we\u2019ve found them, we need to create a marker for each one in turn. Rather than using a regular JavaScript for loop, we can instead use jQuery\u2019s each() method to execute a function against each of the hCards.\n\njQuery('.vcard').each(function() {\n\t// Do something with the hCard\n});\n\nWithin the callback function, this is set to the current DOM element (in our case, the list item). If we want to call the magic jQuery methods on it we\u2019ll need to wrap it in another call to jQuery:\n\njQuery('.vcard').each(function() {\n\tvar hcard = jQuery(this);\n});\n\nThe Google maps geocoder seems to work best if you pass it the street address and a postcode. We can extract these using CSS selectors: this time, we\u2019ll use jQuery\u2019s find() method which searches within the current jQuery selection:\n\nvar streetaddress = hcard.find('.street-address').text();\nvar postcode = hcard.find('.postal-code').text();\n\nThe text() method extracts the text contents of the selected node, minus any HTML markup.\n\nWe\u2019ve got the address; now we need to geocode it. Mapstraction\u2019s geocoding API requires us to first construct a MapstractionGeocoder, then use the geocode() method to pass it an address. Here\u2019s the code outline:\n\nvar geocoder = new MapstractionGeocoder(onComplete, 'google');\ngeocoder.geocode({'address': 'the address goes here');\n\nThe onComplete function is executed when the geocoding operation has been completed, and will be passed an object with the resulting point on the map. We just want to create a marker for the point:\n\nvar geocoder = new MapstractionGeocoder(function(result) {\n\tvar marker = new Marker(result.point);\n\tmapstraction.addMarker(marker);\n}, 'google'); \n\nFor our purposes, joining the street address and postcode with a comma to create the address should suffice:\n\ngeocoder.geocode({'address': streetaddress + ', ' + postcode}); \n\nThere\u2019s one last step: when the marker is clicked, we want to display details of the restaurant. We can do this with an info bubble, which can be configured by passing in a string of HTML. We\u2019ll construct that HTML using jQuery\u2019s html() method on our hcard object, which extracts the HTML contained within that DOM node as a string.\n\nvar marker = new Marker(result.point);\nmarker.setInfoBubble(\n\t'
        ' + hcard.html() + '
        '\n);\nmapstraction.addMarker(marker);\n\nWe\u2019ve wrapped the bubble in a div with class bubble to make it easier to style. Google Maps can behave strangely if you don\u2019t provide an explicit width for your info bubbles, so we\u2019ll add that to our CSS now:\n\n.bubble {\n\twidth: 300px;\n}\n\nThat\u2019s everything we need: let\u2019s combine our code together:\n\njQuery(function() {\n\t// First create a div to host the map\n\tvar themap = jQuery('
        ').css({\n\t\t'width': '90%',\n\t\t'height': '400px'\n\t}).insertBefore('ul.restaurants');\n\t// Now initialise the map\n\tvar mapstraction = new Mapstraction('themap','google');\n\tmapstraction.addControls({\n\t\tzoom: 'large',\n\t\tmap_type: true\n\t});\n\t// Show map centred on Brighton\n\tmapstraction.setCenterAndZoom(\n\t\tnew LatLonPoint(50.82423734980143, -0.14007568359375),\n\t\t15 // Zoom level appropriate for Brighton city centre\n\t);\n\t// Geocode each hcard and add a marker\n\tjQuery('.vcard').each(function() {\n\t\tvar hcard = jQuery(this);\n\t\tvar streetaddress = hcard.find('.street-address').text();\n\t\tvar postcode = hcard.find('.postal-code').text();\n\t\tvar geocoder = new MapstractionGeocoder(function(result) {\n\t\t\tvar marker = new Marker(result.point);\n\t\t\tmarker.setInfoBubble(\n\t\t\t\t'
        ' + hcard.html() + '
        '\n\t\t\t);\n\t\t\tmapstraction.addMarker(marker);\n\t\t}, 'google');\t \n\t\tgeocoder.geocode({'address': streetaddress + ', ' + postcode});\n\t});\n});\n\nHere\u2019s the finished code.\n\nThere\u2019s one last shortcut we can add: jQuery provides the $ symbol as an alias for jQuery. We could just go through our code and replace every call to jQuery() with a call to $(), but this would cause incompatibilities if we ever attempted to use our script on a page that also includes the Prototype library. A more robust approach is to start our code with the following:\n\njQuery(function($) {\n\t// Within this function, $ now refers to jQuery\n\t// ...\n});\n\njQuery cleverly passes itself as the first argument to any function registered to the DOM ready event, which means we can assign a local $ variable shortcut without affecting the $ symbol in the global scope. This makes it easy to use jQuery with other libraries.\n\nLimitations of Geocoding\n\nYou may have noticed a discrepancy creep in to the last example: whereas my original list included seven restaurants, the geocoding example only shows five. This is because the Google Maps geocoder incorporates a rate limit: more than five lookups in a second and it starts returning error messages instead of regular results.\n\nIn addition to this problem, geocoding itself is an inexact science: while UK postcodes generally get you down to the correct street, figuring out the exact point on the street from the provided address usually isn\u2019t too accurate (although Google do a pretty good job).\n\nFinally, there\u2019s the performance overhead. We\u2019re making five geocoding requests to Google for every page served, even though the restaurants themselves aren\u2019t likely to change location any time soon. Surely there\u2019s a better way of doing this?\n\nMicroformats to the rescue (again)! The geo microformat suggests simple classes for including latitude and longitude information in a page. We can add specific points for each restaurant using the following markup:\n\n
      • \n\t

        E-Kagen

        \n\t
        \n\t\t

        22-23 Sydney Street

        \n\t\t

        Brighton, UK

        \n\t\t

        BN1 4EN

        \n\t
        \n\t

        Telephone: +44 (0)1273 687 068

        \n\t

        Lat/Lon: \n\t\t50.827917, \n\t\t-0.137764\n\t

        \n
      • \n\nAs before, I used www.getlatlon.com to find the exact locations \u2013 I find satellite view is particularly useful for locating individual buildings.\n\nLatitudes and longitudes are great for machines but not so useful for human beings. We could hide them entirely with display: none, but I prefer to merely de-emphasise them (someone might want them for their GPS unit):\n\n.vcard .geo {\n\tmargin-top: 0.5em;\n\tfont-size: 0.85em;\n\tcolor: #ccc;\n}\n\nIt\u2019s probably a good idea to hide them completely when they\u2019re displayed inside an info bubble:\n\n.bubble .geo {\n\tdisplay: none;\n}\n\nWe can extract the co-ordinates in the same way we extracted the address. Since we\u2019re no longer geocoding anything our code becomes a lot simpler:\n\n$('.vcard').each(function() {\n\tvar hcard = $(this);\n\tvar latitude = hcard.find('.geo .latitude').text();\n\tvar longitude = hcard.find('.geo .longitude').text();\n\tvar marker = new Marker(new LatLonPoint(latitude, longitude));\n\tmarker.setInfoBubble(\n\t\t'
        ' + hcard.html() + '
        '\n\t);\n\tmapstraction.addMarker(marker);\n});\n\nAnd here\u2019s the finished geo example.\n\nFurther reading\n\nWe\u2019ve only scratched the surface of what\u2019s possible with microformats, jQuery (or just regular JavaScript) and a bit of imagination. If this example has piqued your interest, the following links should give you some more food for thought.\n\n\n\tThe hCard specification\n\tNotes on parsing hCards\n\tjQuery for JavaScript programmers \u2013 my extended tutorial on jQuery.\n\tDann Webb\u2019s Sumo \u2013 a full JavaScript library for parsing microformats, based around some clever metaprogramming techniques.\n\tJeremy Keith\u2019s Adactio Austin \u2013 the first place I saw using microformats to unobtrusively plot locations on a map. Makes clever use of hEvent as well.", "year": "2007", "author": "Simon Willison", "author_slug": "simonwillison", "published": "2007-12-12T00:00:00+00:00", "url": "https://24ways.org/2007/unobtrusively-mapping-microformats-with-jquery/", "topic": "code"} {"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": 170, "title": "A Pet Project is For Life, Not Just for Christmas", "contents": "I\u2019m excited: as December rolls on, I\u2019m winding down from client work and indulging in a big pet project I\u2019ve been dreaming up for quite some time, with the aim of releasing it early next year. I\u2019ve always been a bit of a sucker for pet projects and currently have a few in the works: the big one, two collaborations with friends, and my continuing (and completely un-web-related) attempt at music. But when I think about the other designers and developers out there whose work I admire, one thing becomes obvious: they\u2019ve all got pet projects! Look around the web and you\u2019ll see that anyone worth their salt has some sort of side project on the go. If you don\u2019t have yours yet, now\u2019s the time!\n\nHave a pet project to collaborate with your friends\n\nIt\u2019s not uncommon to find me staring at my screen, looking at beautiful websites my friends have made, grinning inanely because I feel so honoured to know such talented individuals. But one thing really frustrates me: I hardly ever get to work with these people! Sure, there are times when it\u2019s possible to do so, but due to various project situations, it\u2019s a rarity.\n\nSo, in order to work with my friends, I\u2019ve found the best way is to instigate the collaboration outside of client work; in other words, have a pet project together! Free from the hard realities of budgets, time restraints, and client demands, you and your friends can come up with something purely for your own pleasures. If you\u2019ve been looking for an excuse to work with other designers or developers whose work you love, the pet project is that excuse. They don\u2019t necessarily have to be friends, either: if the respect is mutual, it can be a great way of breaking the ice and getting to know someone. \n\n Figure 1: A forthcoming secret love-child from myself and Tim Van Damme\n\nHave a pet project to escape from your day job\n\nWe all like to moan about our clients and bosses, don\u2019t we? But if leaving your job or firing your evil client just isn\u2019t an option, why not escape from all that and pour your creative energies into something you genuinely enjoy? \n\nIt\u2019s not just about reacting to negativity, either: a pet project is a great way to give yourself a bit of variety. As web designers, our day-to-day work forces us to work within a set of web-related contraints and sometimes it can be demoralising to spend so many hours fixing IE bugs. The perfect antidote? Go and do some print design! If it\u2019s not possible in your day job or client work, the pet project is the perfect place to exercise your other creative muscles. Yes, print design (or your chosen alternative) has its own constraints, but if they\u2019re different to those you experience on a daily basis, it\u2019ll be a welcome relief and you\u2019ll return to your regular work feeling refreshed.\n\n Figure 2: Ligature, Loop & Stem, from Scott Boms & Luke Dorny\n\nHave a pet project to fulfill your own needs\n\nMany pet projects come into being because the designers and/or developers behind them are looking for a tool to accomplish a task and find that it doesn\u2019t exist, thus prompting them to create their own solution. In fact, the very app I\u2019m using to write this article \u2014 Ommwriter, from Herraiz Soto & Co \u2014 was originally a tool they\u2019d created for their internal staff, before releasing it to the public so that it could be enjoyed by others.\n\nJust last week, Tina Roth Eisenberg launched Teux Deux, a pet project she\u2019d designed to meet her own requirements for a to-do list, having found that no existing apps fulfilled her needs. Oh, and it was a collaboration with her studio mate Cameron. Remember what I was saying about working with your friends?\n\n Figure 3: Teux Deux, the GTD pet project that launched just last week\n\nHave a pet project to help people out\n\nOmmwriter and Teux Deux are free for anyone to use. Let\u2019s just think about that for a moment: the creators have invested their time and effort in the project, and then given it away to be used by others. That\u2019s very cool and something we\u2019re used to seeing a lot of in the web community (how lucky we are)! People love free stuff and giving away the fruits of your labour will earn you major kudos. Of course, there\u2019s nothing wrong with making some money, either \u2014 more on that in a second.\n\n Figure 4: Dan Rubin\u2018s extremely helpful Make Photoshop Faster\n\nHave a pet project to raise your profile\n\nSo, giving away free stuff earns you kudos. And kudos usually helps you raise your profile in the industry. We all like a bit of shameless fame, don\u2019t we? But seriously, if you want to become well known, make something cool. It could be free (to buy you the love and respect of the community) or it could be purchasable (if you\u2019ve made something that\u2019s cool enough to deserve hard-earned cash), but ultimately it needs to be something that people will love. \n\n Figure 5: Type designer Jos Buivenga has shot to fame thanks to his beautiful typefaces and \u2018freemium\u2019 business model\n\nIf you\u2019re a developer with no design skills, team up with a good designer so that the design community appreciate its aesthetic. If you\u2019re a designer with no development skills, team up with a good developer so that it works. Oh, and not that I\u2019d recommend you ever do this for selfish reasons, but collaborating with someone you admire \u2014 whose work is well-respected by the community \u2014 will also help raise your profile.\n\nHave a pet project to make money\n\nIn spite of our best hippy-esque intentions to give away free stuff to the masses, there\u2019s also nothing wrong with making a bit of money from your pet project. In fact, if your project involves you having to make a considerable financial investment, it\u2019s probably a good idea to try and recoup those costs in some way.\n\n Figure 6: The success of Shaun Inman\u2018s various pet projects \u2014 Mint, Fever, Horror Vacui, etc. \u2014 have allowed him to give up client work entirely.\n\nA very common way to do that in both the online and offline worlds is to get some sort of advertising. For a slightly different approach, try contacting a company who are relevant to your audience and ask them if they\u2019d be interesting in sponsoring your project, which would usually just mean having their brand associated with yours in some way. This is still a form of advertising but tends to allow for a more tasteful implementation, so it\u2019s worth pursuing. \n\nAdvertising is a great way to cover your own costs and keep things free for your audience, but when costs are considerably higher (like if you\u2019re producing a magazine with high production values, for instance), there\u2019s nothing wrong with charging people for your product. But, as I mentioned above, you\u2019ve got to be positive that it\u2019s worth paying for!\n\nHave a pet project just for fun\n\nSometimes there\u2019s a very good reason for having a pet project \u2014 and sometimes even a viable business reason \u2014 but actually you don\u2019t need any reason at all. Wanting to have fun is just as worthy a motivation, and if you\u2019re not going to have fun doing it, then what\u2019s the point? Assuming that almost all pet projects are designed, developed, written, printed, marketed and supported in our free time, why not do something enjoyable?\n\n Figure 7: Jessica Hische\u2018s beautiful Daily Drop Cap\n\nIn conclusion\n\nThe fact that you\u2019re reading 24 ways shows that you have a passion for the web, and that\u2019s something I\u2019m happy to see in abundance throughout our community. Passion is a term that\u2019s thrown about all over the place, but it really is evident in the work that people do. It\u2019s perhaps most evident, however, in the pet projects that people create. Don\u2019t forget that the very site you\u2019re reading this article on is\u2026 a pet project.\n\nIf you\u2019ve yet to do so, make it a new year\u2019s resolution for 2010 to have your own pet project so that you can collaborate with your friends, escape from your day job, fulfil your own needs, help people out, raise your profile, make money, and \u2014 above all \u2014 have fun.", "year": "2009", "author": "Elliot Jay Stocks", "author_slug": "elliotjaystocks", "published": "2009-12-18T00:00:00+00:00", "url": "https://24ways.org/2009/a-pet-project-is-for-life-not-just-for-christmas/", "topic": "business"} {"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": 172, "title": "The Construction of Instruction", "contents": "If the world were made to my specifications, all your clients would be happy to pay for a web writer to craft every sentence into something as elegant as it was functional, and the client would have planned the content so that you had it just when you asked, but we both know that won\u2019t happen every time. Sometimes you just know they are going to write the About page, two company blog pages and a Facebook fan page before resigning their position as chief content writer and you are going to end up filling in all the details that will otherwise just be Lorem Ipsum.\n\nWelcome to the big world of microcopy:\n\n\n\tA man walks into a bar. The bartender nods a greeting and watches as the man scans the bottles behind the bar. \n\u201cEr, you have a lot of gin here. Is there one you would recommend?\u201d \n\u201cYes sir.\u201d\nLong pause. \n\u201c\u2026 Never mind, I\u2019ll have the one in the green bottle.\u201d \n\u201cCertainly, sir. But you can\u2019t buy it from this part of the bar. You need to go through the double doors there.\u201d \n\u201cBut they look like they lead into the kitchen.\u201d \n\u201cReally, sir? Well, no, that\u2019s where we allow customers to purchase gin.\u201d \nThe man walks through the doors. On the other side he is greeted by the same bartender. \n\u201cY-you!\u201d he stammers but the reticent bartender is now all but silent. \nUnnerved, the man points to a green bottle, \u201cEr, I\u2019d like to buy a shot of that please. With ice and tonic water.\u201d \nThe bartender mixes the drink and puts it on the bar just out of the reach of the man and looks up. \n\u201cUm, do you take cards?\u201d the man asks, ready to present his credit card. \nThe bartender goes to take the card to put it through the machine. \n\u201cWait! How much was it \u2013 with sales tax and everything? Do you take a gratuity?\u201d \nThe bartender simply shrugs. \nThe man eyes him for a moment and decides to try his luck at the bar next door.\n\n\nIn the Choose Your Own Adventure version of this story there are plenty of ways to stop the man giving up. You could let him buy the gin right where he was; you could make the price more obvious; you could signpost the place to buy gin. The mistakes made by the bar and bartender are painfully obvious. And yet, there are websites losing users everyday due to the same lack of clear instruction.\n\nA smidgen of well written copy goes a long way to reassure the nervous prospect. Just imagine if our man walked into the bar and the bartender explained that although the bar was here, sales were conducted in the next room because people were not then able to overhear the man\u2019s card details. Instead, he is left to fend for himself. Online, we kick customers through the anonymous double doors with a merry \u2018Paypal will handle your transaction!\u2019.\n\nRecently I worked on a site where the default error message, to account for anything happening that the developers hadn\u2019t accounted for, was \u2018SOMETHING HAS GONE WRONG!\u2019. It might have been technically accurate but this is not how to inspire confidence in your customers that they can make a successful purchase through you. As everyone knows they can shop just fine, thank you very much, it is your site they will blame. Card declined? It\u2019s the site. Didn\u2019t know my email address has changed? It\u2019s the site. Can\u2019t log in? It\u2019s the site.\n\nYes, yes. I know. None of these things are related to your site, or you the developer, but drop outs will be high and you\u2019ll get imploring emails from your client asking you to wade knee deep into the site analytics to find a solution by testing 41 shades of blue because if it worked for Google\u2026? Before you try a visual fix involving the Dulux paint chart breeding with a Pantone swatch, take an objective look at the information you are giving customers. How much are you assuming they know? How much are you relying on age-old labels and prompts without clarification?\n\nHere\u2019s a fun example for non-North Americans: ask your Granny to write out her billing address. If she looks at you blankly, tell her it is the address where the bank sends her statements. Imagine how many fewer instances of the wrong address there would be if we routinely added that information when people purchased from the UK? Instead, we rely on a language convention that hasn\u2019t much common usage without explanation because, well, because we always have since the banks told us how we could take payments online.\n\nSo. Your client is busying themselves with writing the ultimate Facebook fan page about themselves and here you are left with creating a cohesive signup process or basket or purchase instructions. Here are five simple rules for bending puny humans to your will creating instructive instructions and constructive error messages that ultimately mean less hassle for you.\n\nPlan what you want to say and plan it out as early as possible \n\nThis goes for all content. Walk a virtual mile in the shoes of your users. What specific help can you offer customers to actively encourage continuation and ensure a minimal amount of dropouts? Make space for that information. One of the most common web content mistakes is jamming too much into a space that has been defined by physical boundaries rather than planned out. If you manage it, the best you can hope for is that no-one notices it was a last-minute job. Mostly it reads like a bad game of Tetris with content sticking out all over the place.\n\nUse your words\n\nMicrocopy often says a lot in a few words but without those words you could leave room for doubt. When doubt creeps in a customer wants reassurance just like Alice:\n\n\n\tThis time (Alice) found a little bottle\u2026 with the words \u2018DRINK ME\u2019 beautifully printed on it in large letters. It was all very well to say \u2018Drink me,\u2019 but the wise little Alice was not going to do that in a hurry. \u2018No, I\u2019ll look first,\u2019 she said, \u2018and see whether it\u2019s marked \u201cpoison\u201d or not\u2019\n\n\nAlice in Wonderland, Lewis Carroll.\n\nValue clarity over brevity. Or a little more prosaically, \u201cIf in doubt, spell it out.\u201d Thanks, Jeremy!\n\nBe prepared to help\n\n\n\t\u2018Login failed: email/password combination is incorrect.\u2019\n\n\nOh.\n\n\n\t\u2018Login failed: email/password combination is incorrect. \nAre you typing in all capitals? Caps Lock may be on. \nHave you changed your email address recently and not updated your account with us? Try your old email address first. \nCan\u2019t remember your password? We can help you reset it.\u2019 \n\n\nAh!\n\nBe direct and be informative\n\nThere is rarely a site that doesn\u2019t suffer from some degree of jargon. Squash it early by setting a few guidelines about what language and tone of voice you will use to converse with your users. Be consistent. Equally, try to be as specific as possible when giving error messages or instructions and allay fears upfront.\n\nCard payments are handled by paypal but you do not need a paypal account to pay.\n\nWe will not display your email address but we might need it to contact you.\n\nSign up for our free trial (no credit card required).\n\nCombine copy and visual cues, learn from others and test new combinations\n\nWhile visual design and copy can work independently, they work best together. New phrases and designs are being tested all the time so take a peek at abtests.com for more ideas, then test some new ideas and add your own results. Have a look at the microcopy pool on Flickr for some wonderful examples of little words and pictures working together. And yes, you absolutely should join the group and post more examples.\n\n\n\tA man walks into a bar. The bartender greets him in a friendly manner and asks him what he would like to drink. \n\u201cGin and Tonic, please.\u201d \n\u201cYes sir, we have our house gin on offer but we also have a particularly good import here too.\u201d\n\u201cThe import, please.\u201d \n\u201cHow would you like it? With a slice of lemon? Over ice?\u201d \n\u201cBoth\u201d \n\u201cThat\u2019s \u00a33.80. We accept cash, cards or you could open a tab.\u201d \n\u201cCard please.\u201d \n\u201cCertainly sir. Move just over here so that you can\u2019t be observed. Now, please enter your pin number.\u201d \n\u201cThank you.\u201d \n\u201cAnd here is your drink. Do let me know if there is a problem with it. I shall just be here at the bar. Enjoy.\u201d\n\n\nCheers!", "year": "2009", "author": "Relly Annett-Baker", "author_slug": "rellyannettbaker", "published": "2009-12-08T00:00:00+00:00", "url": "https://24ways.org/2009/the-construction-of-instruction/", "topic": "content"} {"rowid": 173, "title": "Real Fonts and Rendering: The New Elephant in the Room", "contents": "My friend, the content strategist Kristina Halvorson, likes to call content \u201cthe elephant in the room\u201d of web design. She means it\u2019s the huge problem that no one on the web development team or client side is willing to acknowledge, face squarely, and plan for. \n\nA typical web project will pass through many helpful phases of research, and numerous beneficial user experience design iterations, while the content\u2014which in most cases is supposed to be the site\u2019s primary focus\u2014gets handled haphazardly at the end. Hence, elephant in the room, and hence also artist Kevin Cornell\u2019s recent use of elephantine imagery to illustrate A List Apart articles on the subject. But I digress.\n\nWithout discounting the primacy of the content problem, we web design folk have now birthed ourselves a second lumbering mammoth, thanks to our interest in \u201creal fonts on the web\u201c (the unfortunate name we\u2019ve chosen for the recent practice of serving web-licensed fonts via CSS\u2019s decade-old @font-face declaration\u2014as if Georgia, Verdana, and Times were somehow unreal). \n\nFor the fact is, even bulletproof and mo\u2019 bulletproofer @font-face CSS syntax aren\u2019t really bulletproof if we care about looks and legibility across browsers and platforms.\n\nHyenas in the Breakfast Nook\n\nThe problem isn\u2019t just that foundries have yet to agree on a standard font format that protects their intellectual property. And that, even when they do, it will be a while before all browsers support that standard\u2014leaving aside the inevitable politics that impede all standardization efforts. Those are problems, but they\u2019re not the elephant. Call them the coyotes in the room, and they\u2019re slowly being tamed.\n\nNor is the problem that workable, scalable business models (of which Typekit\u2018s is the most visible and, so far, the most successful) are still being shaken out and tested. The quality and ease of use of such services, their stability on heavily visited sites (via massively backed-up server clusters), and the fairness and sustainability of their pricing will determine how licensing and serving \u201creal fonts\u201d works in the short and long term for the majority of designer/developers.\n\nNor is our primary problem that developers with no design background may serve ugly or illegible fonts that take forever to load, or fonts that take a long time to download and then display as ordinary system fonts (as happens on, say, about.validator.nu). Ugliness and poor optimization on the web are nothing new. That support for @font-face in Webkit and Mozilla browsers (and for TrueType fonts converted to Embedded OpenType in Internet Explorer) adds deadly weapons to the non-designer\u2019s toolkit is not the technology\u2019s fault. JavaScript and other essential web technologies are equally susceptible to abuse. \n\nBeauty is in the Eye of the Rendering Engine\n\nNo, the real elephant in the room\u2014the thing few web developers and no \u201cweb font\u201d enthusiasts are talking about\u2014has to do with legibility (or lack thereof) and aesthetics (or lack thereof) across browsers and platforms. Put simply, even fonts optimized for web use (which is a whole thing: ask a type designer) will not look good in every browser and OS. That\u2019s because every browser treats hinting differently, as does every OS, and every OS version. \n\nFirefox does its own thing in both Windows and Mac OS, and Microsoft is all over the place because of its need to support multiple generations of Windows and Cleartype and all kinds of hardware simultaneously. Thus \u201creal type\u201d on a single web page can look markedly different, and sometimes very bad, on different computers at the same company. If that web page is your company\u2019s, your opinion of \u201cweb fonts\u201d may suffer, and rightfully. (The advantage of Apple\u2019s closed model, which not everyone likes, is that it allows the company to guarantee the quality and consistency of user experience.) \n\nAs near as my font designer friends and I can make out, Apple\u2019s Webkit in Safari and iPhone ignores hinting and creates its own, which Apple thinks is better, and which many web designers think of as \u201cwhat real type looks like.\u201d The forked version of Webkit in Chrome, Android, and Palm Pre also creates its own hinting, which is close to iPhone\u2019s\u2014close enough that Apple, Palm, and Google could propose it as a standard for use in all browsers and platforms. Whether Firefox would embrace a theoretical Apple and Google standard is open to conjecture, and I somehow have difficulty imagining Microsoft buying in\u2014even though they know the web is more and more mobile, and that means more and more of their customers are viewing web content in some version of Webkit.\n\nThe End of Simple\n\nThere are ways around this ugly type ugliness, but they involve complicated scripting and sniffing\u2014the very nightmares from which web standards and the simplicity of @font-face were supposed to save us. I don\u2019t know that even mighty Typekit has figured out every needed variation yet (although, working with foundries, they probably will). \n\nFor type foundries, the complexity and expense of rethinking classic typefaces to survive in these hostile environments may further delay widespread adoption of web fonts and the resolution of licensing and formatting issues. The complexity may also force designers (even those who prefer to own) to rely on a hosted rental model simply to outsource and stay current with the detection and programming required.\n\nForgive my tears. I stand in a potter\u2019s field of ideas like \u201cKeep it simple,\u201d by a grave whose headstone reads \u201cWrite once, publish everywhere.\u201d", "year": "2009", "author": "Jeffrey Zeldman", "author_slug": "jeffreyzeldman", "published": "2009-12-22T00:00:00+00:00", "url": "https://24ways.org/2009/real-fonts-and-rendering/", "topic": "design"} {"rowid": 174, "title": "Type-Inspired Interfaces", "contents": "One of the things that terrifies me most about a new project is the starting point. How is the content laid out? What colors do I pick? Once things like that are decided, it becomes significantly easier to continue design, but it\u2019s the blank page where I spend the most time.\n\nTo that end, I often start by choosing type. I don\u2019t need to worry about colors or layout or anything else\u2026 just the right typefaces that support the art direction. (This article won\u2019t focus on how to choose a typeface, but there are some really great resources if you interested in that sort of thing.)\n\nAnd just like that, all your work is done. \u201cHold it just a second,\u201d you might say. \u201cAll I\u2019ve done is pick type. I still have to do the rest!\u201d\n\nTo which I would reply, \u201cSilly rabbit. You already have!\u201d You see, picking the right typeface gets you farther than you might think. Here are a few tips on taking cues from type to design interfaces and interface elements.\n\nPerfecting Web 2.0\n\nIf you\u2019re going for that beloved rounded corner look, you might class it up a bit by choosing the wonderful Omnes Pro by Joshua Darden. As the typeface already has a rounded aesthetic, making buttons that fit the style should be pretty easy.\n\nI\u2019ve found that using multiples helps to keep your interfaces looking balanced and proportional. Noticing that the top left edge of the letter \u201cP\u201d has about an 12px corner radius, let\u2019s choose a 24px radius for our button (a multiple of 2), so that we get proper rounded corners. By taking mathematical measurements from the typeface, our button looks more thought out than just \u201cplace arbitrary text on arbitrarily-sized button.\u201d Pretty easy, eh?\n\n\n\nWhat\u2019s in a name(plate)?\n\nRounded buttons are pretty popular buttons nowadays, so let\u2019s try something a bit more stylized.\n\nHave a gander at Brothers, a sturdy face from Emigre. The chiseled edges give us a perfect cue for a stylized button. Using the same slope, you can make plated-looking buttons that fit a different kind of style.\n\n\n\nHeadlining\n\nYou might even take some cues from the style of the typeface itself. Didone serifs are known for their lack of brackets\u30fcthat is, a gradual transition from the stem to the serif. Instead, they typically connect at a right angle. Another common characteristic is the high contrast in the strokes: very thick stems, very thin serifs.\n\nSo, when using a high contrast typeface, you can use it to your advantage to enhance hierarchy. Following our \u201cmultiples\u201d guideline, a 12px measurement from the stems helps us create a top rule with a height of 24px (a multiple of 2). We can take the exact 1px measurement from the serif\u2014a multiple of 1\u2014to create the bottom rule. Voil\u00e0! I use this technique a lot.\n\n\n\nSwashbucklers\n\nAnd don\u2019t forget the importance of visual \u201cspeed bumps\u201d to break up long passages of text. A beautiful face like Alejandro Paul\u2019s Ministry Script has over a thousand characters that can be manipulated or even combined to create elegant interface elements. Altering the partial differential character (\u2202) creates a delightful ornament that can help to guide the eye through content.\n\n\n\nStagger & Swagger\n\nWhat about layout? How can we use typography to inform how our content is displayed?\n\nLet\u2019s take a typeface like Assembler. We might use this for a design that needs to feel uneasy or uncomfortable. In design terms, that might translate into using irregular shapes and asymmetry. Using the proportional distances and degrees from the perpendiculars, we could easily create a multi-column layout that jives with the general tone. And for all you skeptics that don\u2019t think a layout like this is doable on the web, stranger things have happened.\n\n Background texture generously offered by Bittbox.\n\nOverall Design Direction\n\nFinally, your typography could impact the entire look of the site, from the navigation to the interaction and everything in between. Check out how the (now-defunct) Nike Free site\u2019s typography echoes the product itself, and in turn influences the navigation.\n\n\n\nFind Your Type\n\nWith thousands of fonts to choose from, the possibilities are ridiculously open. From angles to radii to color to weight, you\u2019ve got endless fodder before you. Great type designers spent countless hours slaving over these detailed letterforms; take advantage of it! Don\u2019t feel like you have to limit yourself to the same old Helvetica and wet floors\u2026 unless your design calls for it. \n\nHappy hunting!", "year": "2009", "author": "Dan Mall", "author_slug": "danmall", "published": "2009-12-07T00:00:00+00:00", "url": "https://24ways.org/2009/type-inspired-interfaces/", "topic": "design"} {"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": 176, "title": "What makes a website successful? It might not be what you expect!", "contents": "What makes some sites succeed and others fail? Put another way, when you are asked to redesign an existing website, what problems are you looking out for and where do you concentrate your efforts?\n\nI would argue that as web designers we spend too much time looking at the wrong kind of problem.\n\nI recently ran a free open door consultancy clinic to celebrate the launch of my new book (yes I know, two shameless plugs in one sentence). This involved various website owners volunteering their sites for review. Both myself and the audience then provided feedback.\n\nWhat quickly became apparent is that the feedback being given by the audience was biased towards design and development.\n\nAlthough their comments were excellent it focused almost exclusively on the quality of code, site aesthetics and usability. To address these issues in isolation is similar to treating symptoms and ignoring the underlying illness.\n\nCure the illness not the symptoms\n\nPoor design, bad usability and terribly written code are symptoms of bigger problems. Often when we endeavour to address these symptoms, we meet resistance from our clients and become frustrated. This is because our clients are still struggling with fundamental concepts we take for granted.\n\nBefore we can address issues of aesthetics, usability and code, we need to tackle business objectives, calls to action and user tasks. Without dealing with these fundamental principles our clients\u2019 website will fail.\n\nLet me address each in turn:\n\nUnderstand the business objectives\n\nDo you ask your clients why they have a website? It feels like an obvious question. However, it is surprising how many clients do not have an answer.\n\nWithout having a clear idea of the site\u02bcs business objectives, the client has no way to know whether it is succeeding. This means they have no justification for further investment and that leads to quibbling over every penny.\n\nHowever most importantly, without clearly defined business aims they have no standard against which to base their decisions. Everything becomes subjective and that will inevitably lead to problems.\n\nBefore we start discussing design, usability and development, we need to focus our clients on establishing concrete business objectives. This will provide a framework for decision making during the development phase.\n\nThis will not only help the client make decisions, it will also focus them on the business and away from micro managing the design.\n\nEstablish clear calls to action\n\nOnce business objectives have been set this opens up the possibility to establish clear calls to action.\n\nI am amazed at how few website owners can name their calls to action. However, I am even more staggered at how few web designers ask about them.\n\nCalls to action are not just limited to ecommerce sites. Whether you are asking people to sign up for a newsletter or complete a contact us form, every site should have a desired objective for users.\n\nWhat is more, each page of a site should have micro calls to action that always draw users on and never leave them at a dead end.\n\nWithout clearly defined calls to action you cannot successfully design a site, structure the user experience or measure its success. They bring focus to the site and encourage the client to concentrate their efforts on helping people reach those goals.\n\nOf course in order to know if a call to action is going to work, it is necessary to do some user testing.\n\nTest against the right tasks\n\nAs web designers we all like to boast about being \u02bbuser centric\u02bc whatever that means! However, in reality I think many of us are paying lip service to the subject.\n\nSure, we ask our clients about who their users are and maybe even do some usability testing. However, usability testing is no good if we are not asking the right questions.\n\nAgain we find ourselves working on a superficial level rather than tackling the deeper issues.\n\nClients find it relatively easy to tell you who their target audience is. Admittedly the list they come back with is often overly long and contains a lot of edge cases. However, where they begin to struggle is articulating what these users will want to achieve on the website. They know who they want to reach. However, they cannot always tell you why those people would be interested in the site.\n\nThese user tasks are another fundamental building block for any successful website. Although it is important for a website owner to understand what their objectives are and what they want users to do, it is even more important that they understand the users objectives as well.\n\nAgain, this provides context for the decisions they are making about design, usability and functionality. Without it the site will become self serving, largely ignoring the needs of users.\n\nUser tasks help to focus the client\u02bcs mind on the needs of their user, rather than what they can get out of them.\n\nSo am I claiming that design, usability and code do not matter? Well the shocking truth is that to some extent I am!\n\nThe shocking truth\n\nWhether we like it or not there is significant evidence that you can create a successful website with bad design, terrible code and without ever running a usability test session.\n\nYou only need to look at the design of Craigslist or the code of Amazon to see that this is true.\n\nHowever, I do not believe it is possible to build a successful website without business objectives, calls to action and a clear idea of user tasks.\n\nDo not misunderstand me. I do believe design, usability and code matters. I just believe that they only matter if the fundamentals are already in place. These things improve a solid foundation but are no use in their own right.\n\nAs web designers it is our responsibility to ensure fundamental questions are being asked, before we start exploring other issues. If we do not, our websites will look great, be well coded and have gone through endless usability tests, however it will not be truly successful.", "year": "2009", "author": "Paul Boag", "author_slug": "paulboag", "published": "2009-12-04T00:00:00+00:00", "url": "https://24ways.org/2009/what-makes-a-website-successful/", "topic": "business"} {"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": 178, "title": "Make Out Like a Bandit", "contents": "If you are anything like me, you are a professional juggler. No, we don\u2019t juggle bowling pins or anything like that (or do you? Hey, that\u2019s pretty rad!). I\u2019m talking about the work that we juggle daily. In my case, I\u2019m a full-time designer, a half-time graduate student, a sometimes author and conference speaker, and an all-the-time social networker. Only two of these \u201cpositions\u201d have actually put any money in my pocket (and, well, the second one takes a lot of money out). Still, this is all part of the work that I do. Your work situation is probably similar. We are workaholics.\n\nSo if we work so much in our daily lives, shouldn\u2019t we be making out like bandits? Umm, honestly, I\u2019m not hitting on you, silly. I\u2019m talking about our success. We work and work and work. Shouldn\u2019t we be filthy, stinking rich? Well\u2026 okay, that\u2019s not quite what I mean either. I\u2019m not necessarily talking about money (though that could potentially be a part of it). I\u2019m talking about success \u2014 as in feeling a true sense of accomplishment and feeling happy about what we do and why we do it.\n\nIt\u2019s important to feel accomplished and a general happiness in our work. To make out like a bandit (or have an incredible amount of success), you can either get lucky or work hard for it. And if you\u2019re going to work hard for it, you might as well make it all meaningful and worthwhile. This is what I strive for in my own work and my life, and the following points I\u2019m sharing with you are the steps I am taking to work toward this.\n\n\n\tI know the price of success: dedication, hard work & an unremitting devotion to the things you want to see happen. \u2014 Frank Lloyd Wright\n\n\nLearn. Participate. Do.\n\nThe best way to get good at something is to keep doing whatever it is you\u2019re doing that you want to be good at. For example, a sushi-enthusiast might take a sushi-making class because she wants to learn to make sushi for herself. It totally makes sense while the teacher demonstrates all the procedures, materials, and methods needed to make good, beautiful sushi. Later, the student goes home and tries to make sushi on her own, she gets totally confused and lost. Okay, I\u2019m not even going to hide it, I\u2019m talking about myself (this happened to me). As much as I love sushi, I couldn\u2019t even begin to make good sushi because I\u2019ve never really practiced.\n\nTake advantage of learning opportunities where possible. Whether you\u2019re learning CSS, Actionscript, or visual design, the best way to grasp how to do things is to participate, practice, do. Apply what you learn in your work. Participation is so vital to your success. If you have problems, let people know, and ask. But definitely practice on your own. And as clich\u00e9 as it may sound, believe in yourself because if you don\u2019t think you can do it, no one else will think you can either.\n\nMaintain momentum\n\nWith whatever it is you\u2019re doing, if you find yourself \u201con a roll\u201d, you should take advantage of that momentum and keep moving. Sure, you\u2019ll definitely want to take breaks here or there, but remember that momentum can be very difficult to obtain again once you\u2019ve lost it. Get it done!\n\nDeal with people\n\nWhether you love or hate people, the fact is, you gotta deal with them \u2014 even the difficult ones. If you\u2019re in a management position, then you know pretty well that most people don\u2019t like being told what to do (even if that\u2019s their job). Find ways to get people excited about what they\u2019re doing. Make people feel that they (and what they do) are needed \u2014 people respond better if they\u2019re valued, not commanded. Even if you\u2019re not in a management position, this still applies to the way you work with your coworkers, clients, vendors, etc.\n\nResolve any conflicts right away. Conflicts will inevitably happen. Move on to how you can improve the situation, and do it as quickly as possible. Don\u2019t spend too much time focusing on whose screw up it is \u2014 nobody feels good in this situation. Also, try to keep people informed on whatever it is you need or what it is you\u2019re doing. If you\u2019re waiting on something from someone, and it\u2019s been a while, don\u2019t be afraid to say something (tactfully). Sometimes people are forgetful \u2014 or just slacking. Hey, it happens!\n\nHelp yourself by helping others\n\nWhat are some of the small, simple things you can do when you\u2019re working that will help the people you work with (and in most cases, will end up helping yourself)? For example: if you\u2019re a designer, perhaps taking a couple minutes now to organize and name your Photoshop layers will end up saving time later (since it will be easier to find things). This is going to help both you and your team. Or, developers: taking some time to write some documentation (even if it\u2019s as simple as a comment in the code, or a well-written commit message) could potentially save valuable time for both you and your team later. Maybe you have to take a little time to sit down with a coworker and explain why something works the way it does. This helps them out tremendously \u2014 and will most likely lead to them respecting you a little more. This is a benefit.\n\nIf you make little things like this a habit, people will notice. People will enjoy working with you. People will trust you and rely on you. Sure, it might seem beneficial at any given moment to be \u201cin it for yourself\u201d (and therefore only helping yourself), but that won\u2019t last very long. Helping others (whether it be a small or large feat) will cause a positive impact in the long run \u2014 and that is what will be more valuable to you and your career.\n\nDo work that is meaningful\n\nOne of the best ways to feel successful about what you do is to feel good and happy about it. And a great way to feel good and happy about what you\u2019re doing is to actually do good. This could be purpose-driven work that focuses on sustainability and environmentalism, or work that helps support causes and charity. Perhaps the work simply inspires people. Or maybe the work is just something you are very passionate about. Whatever the work may be, try working on projects that are meaningful to you. You\u2019ll do well simply by being more motivated and interested. And it\u2019s a double-win if the project is meaningful to others as well.\n\nI feel very fortunate to work at a place like Crush + Lovely, where we have found quite frequently that the projects that inspire people, focus on global and social good, and create some sort of positive impact are the very projects that bring us more paid projects. But more importantly, we are happy and excited to do it. You might not work at a company that takes on those types of projects. But perhaps you have your own personal endeavors that create this excitement for you. Elliot Jay Stocks wrote about having pet projects. Do you take on side projects? What are those projects?\n\nOver the last couple years, I\u2019ve seen some really fantastic side projects come out that are great examples of meaningful work. These projects reflect the passions and goals of the respective designers and developers involved, and therefore become quite successful (because the people involved simply love what they are doing while they\u2019re doing it). Some of these projects include:\n\n\n\tTypedia is a shared encyclopedia of typefaces which serves as a resource to classify, categorize, and connect typefaces. It was founded by Jason Santa Maria, a graphic designer with a love and passion for typography. He created it as a solution to a problem he faced as a designer: finding the right typeface.\n\tHuffduffer was created by Jeremy Keith, a web developer who wanted to create a podcast of inspirational talks \u2014 but after he found that this could be tedious, he decided to create a tool to automate this.\n\tLevel & Tap was created by passionate photographer and web developer, Tom Watson. It began as a photography print store for Tom\u2019s best personal photography. Over time, more photographers were added to the site and the site has grown to become quite a great collection of beautiful photography.\n\tHeat Eat Review is a review blog created by information architect and user experience designer, Abi Jones. As a foodie, she is able to use this passion for this blog, as it focuses on reviewing TV Dinners, Frozen Meals, and Microwavable Foods.\n\tArt in My Coffee, a favorite personal project of my own, is a photo blog of coffee art I created, after I found that my friends and I were frequently posting coffee art photos to Flickr, Twitter, and other websites. After the blog became more popular, I teamed up with Meagan Fisher on the project, who has just as much a passion for coffee art, if not more.\n\n\nSo, what\u2019s important to you?\n\nThis is the very, very important question here. What really matters to you most? Beyond just working on meaningful projects you are passionate about, is the work you\u2019re doing the right work for you, so that you can live a good lifestyle? Scott Boms wrote an excellent article, Burnout, in which he shares his own experience in battling stress and exhaustion, and what he learned from it. You should definitely read the article in its entirety, but a couple of his points that are particularly excellent are:\n\n\n\tMake time for numero uno, in which you make time for the things in life that make you happy\n\tExamine your values, goals, and measures of success, in which you work toward the things you are passionate about, your own personal development, and focusing on the things that matter.\n\n\nA solid work-life balance can be a challenging struggle to obtain. Of course, you can cheat this by finding ways to combine the things you love with the things you do (so then it doesn\u2019t even feel like you\u2019re working \u2014 oh, you sneaky little bandit!). However, there are other factors to consider beyond your general love for the work you\u2019re doing. Take proper care of yourself physically, mentally, and socially.\n\nSo, are you making out like a bandit?\n\nDo you feel accomplished and generally happy with your work? If not, perhaps that is something to focus on for the next year. Consider your work (both in your job as well as any side projects you may take on) and how it benefits you \u2014 present and future. Take any steps necessary to get you to where you need to be. If you are miserable, fix it!\n\nFinally, it\u2019s important to be thankful for the things that matter to you and make you happy. Pass it along everyday. Thank people. It\u2019s a simple thing, really. Saying \u201cthank you\u201d can and will have enormous impact on the people around you. Oh. And, I apologize if the title of this article led you to thinking it would teach you how to be an amazing kisser. That\u2019s a different article entirely for 24 ways to impress your friends!", "year": "2009", "author": "Jina Anne", "author_slug": "jina", "published": "2009-12-21T00:00:00+00:00", "url": "https://24ways.org/2009/make-out-like-a-bandit/", "topic": "business"} {"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": 183, "title": "Designing For The Switch", "contents": "For a long time on the web, we\u2019ve been typographically spoilt. Yes, you heard me correctly. Think about it: our computers come with web fonts already installed; fonts that have been designed specifically to work well online and at small size; and fonts that we can be sure other people have too. \n\nYes, we\u2019ve been spoilt. We don\u2019t need to think about using Verdana, Arial, Georgia or Cambria. \n\nYet, for a long time now, designers have felt we needed more. We want to choose whatever typeface we feel necessary for our designs. We did bad things along the way in pursuit of this goal such as images for text. Smart people dreamt up tools to help us such as sIFR, or Cuf\u00f3n. Only fairly recently, @font-face is supported in most browsers. The floodgates are opening. It really is the dawn of a new typographic era on the web. And we must tread carefully. \n\nThe New Typesetters \n\nMany years ago, before the advent of desktop publishing, if you wanted words set in a particular typeface, you had to go to a Typesetter. A Typesetter, or Compositor, as they were sometimes called, was a person whose job it was to take the written word (in the form of a document or manuscript) and \u2018set\u2019 the type in the desired typeface. The designer would chose what typeface they wanted \u2013 and all the ligatures, underlines, italics and whatnot \u2013 and then scribble all over the manuscript so the typesetter could set the correct type. \n\nThen along came Desktop Publishing and every Tom, Dick and Harry could choose type on their computer and an entire link in the typographic chain was removed within just a few years. Well, that\u2019s progress I guess. That was until six months ago when Typesetting was reborn on the web in the guise of a font service: Typekit. \n\nTypekit \u2013 and services like Typekit such as Typotheque, Kernest and the upcoming Fontdeck \u2013 are typesetting services for the web. You supply them with your content, in the form of a webpage, and they provide you with some JavaScript to render that webpage in the typeface you\u2019ve specified simply by adding the font name in your CSS file. \n\nThanks to services like these, font foundries are now talking to create licensing structures to allow us to embed fonts into our web pages legally \u2013 which has always been a sticking point in the past. So, finally, us designers can get what we want: whatever typeface we want on the web. \n\nYes, but\u2026 there are hurdles. One of which is the subject of this article. \n\nThe differences between Web Fonts and other fonts \n\nWeb fonts are different to normal fonts. They differ in a whole bunch of ways, from loose letter spacing to larger x-heights. But perhaps the most notable practical difference is file size. Let\u2019s take a look at one of Typekit\u2019s latest additions from the FontFont library, Meta. \n\nMeta Roman weighs in at 42 KB. This is a fairly typical file size for a single weight of a good font. Now, let\u2019s have a look at Verdana. Verdana is 186 KB. For one weight. The four weight family for Verdana weighs in at 686 KB. Four weights for half a megabyte!? Why so huge? \n\nWell, Verdana has a lot of information packed into its 186 KB. It has the largest hinting data table of any typeface (the information carried by a font that tells it how to align itself to the pixels on your screen). As it has been shipped with Microsoft products since 1996, it has had time to grow to support many, many languages. Along with its cousin, Georgia (283 KB), Verdana was a new breed of typeface. And it\u2019s grown fat. \n\nIf really serious web typography takes off \u2013 and by that I mean typefaces specifically designed for the screen \u2013 then we\u2019re going to see more fonts increase in file size as the font files include more data. So, if you\u2019re embedding a font weighing in at 100 KB, what happens? \n\nThe Flash of Unstyled Text \n\nWe all remember the Flash of Unstyled Content bug on Internet Explorer, right? That annoying bug that caused a momentary flash of unstyled HTML page. Well, the same thing can happen with embedding fonts using @font-face. An effect called The Flash of Unstyled Text (FOUT), first coined by Paul Irish. Personally, I prefer to call it the Flash of UnTypeset Text (still FOUT), as the text is styled, just not with what you want. \n\nIf you embed a typeface in your CSS, then the browser will download that typeface. Typically, browsers differ in the way they handle this procedure. \n\nFirefox and Opera will render the text using the next font in your font stack until the first (embedded) font is loaded. It will then switch to the embedded font. \n\nWebkit takes the approach that you asked for that font so it will wait until it\u2019s completely loaded before showing it you. \n\nIn Opera and Firefox, you get a FOUT. In Webkit, you don\u2019t. You wait. \n\nHang on there. Didn\u2019t I say that good web fonts weigh in considerably more than \u2018normal\u2019 fonts? And whilst the browser is downloading the font, the user gets what to look at? Some pictures, background colours and whatever else isn\u2019t HTML? I believe Webkit\u2019s handling of font embedding \u2013 as deliberate as it is \u2013 is damaging to the practice of font embedding. Why? Well, we can design to a switch in typeface (as jarring as that is for the user), but we can\u2019t design to blank space. \n\nLet\u2019s have a closer look at how we can design to FOUT. \n\nMore considered font stacks \n\nWe all know that font stacks in CSS are there for when a user doesn\u2019t have a font; the browser will jump to the next one in the stack. Adding embedded fonts into the font stack means that because of FOUT (in gecko and Opera), the user can see a switch, and depending on their connection that switch could happen well into any reading that the user may be doing. \n\nThe practicalities of this are that a user could be reading and be towards the end of a line when the paragraph they are reading changes shape. The word they were digesting suddenly changes to three lines down. It\u2019s the online equivalent of someone turning the page for you when you least expect it. So, how can we think about our font stacks slightly differently so we can minimise the switch? \n\nTwo years ago, Richard Rutter wrote on this very site about increasing our font stacks. By increasing the font stacks (by using his handy matrix) we can begin to experiment with different typefaces. However, when we embed a typeface, we must look very carefully at the typefaces in the font stack and the relationship between them. Because, previously, the user would not see a switch from one typeface to another, they\u2019d just get either one or the other. Not both. With FOUT, the user sees two typefaces. \n\nBy carefully looking at the characteristics of the typefaces you choose, you can minimise the typographic \u2018distance\u2019 between the type down the stack. In doing so, you minimise the jarring effect of the switch. \n\nLet\u2019s take a look at an example of how to go about this. \n\nMicro Typography to build better font stacks \n\nLet\u2019s say I want to use a recent edition to Typekit \u2013 Meta Serif Book \u2013 as my embedded font. My font stack would start like this: \n\nfont-family: 'Meta Serif Bold'; \n\nWhere do you go from here? Well, first, familiarise yourself with Richard\u2019s Font Matrix so you get an idea of what fonts are available for different people. Then start by looking closely at the characters of the embedded font and then compare them to different fonts from the matrix. \n\nWhen I do this, I\u2019m looking to match type characteristics such as x-height, contrast (the thickness and thinness of strokes), the stress (the angle of contrast) and the shape of the serifs (if the typeface has any). \n\n\n\nUsing just these simple comparative metrics means you can get to a \u2018best fit\u2019 reasonably quickly. And remember, you\u2019re not after an ideal match. You\u2019re after a match that means the switch is less painful for the reader, but also a typeface that carries similar characteristics so your design doesn\u2019t change too much. \n\nBuilding upon my choice of embedded font, I can quickly build up a stack by comparing letters. \n\n\n\nThis then creates my \u2018best fit\u2019 stack. \n\n\n\nThis translates to the CSS as: \n\nfont-family: 'Meta Serif Bold', 'Lucida Bright', Cambria, Georgia, serif \n\nFollowing this process, and ending up with considered font stacks, means that we can design to the Flash of UnTypeset Content and ensure that our readers don\u2019t get a diminished experience.", "year": "2009", "author": "Mark Boulton", "author_slug": "markboulton", "published": "2009-12-16T00:00:00+00:00", "url": "https://24ways.org/2009/designing-for-the-switch/", "topic": "design"} {"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": 185, "title": "Make Your Mockup in Markup", "contents": "We aren\u2019t designing copies of web pages, we\u2019re designing web pages.\n\n\t Andy Clarke, via Quotes on Design\n\n\nThe old way\n\nI used to think the best place to design a website was in an image editor. I\u2019d create a pixel-perfect PSD filled with generic content, send it off to the client, go through several rounds of revisions, and eventually create the markup.\n\nDoes this process sound familiar? You\u2019re not alone. In a very scientific and official survey I conducted, close to 90% of respondents said they design in Photoshop before the browser. \n\nThat process is whack, yo!\n\nRecently, thanks in large part to the influence of design hero Dan Cederholm, I\u2019ve come to the conclusion that a website\u2019s design should begin where it\u2019s going to live: in the browser.\n\nDie Photoshop, die\n\nSome of you may be wondering, \u201cwhat\u2019s so bad about using Photoshop for the bulk of my design?\u201d Well, any seasoned designer will tell you that working in Photoshop is akin to working in a minefield: you never know when it\u2019s going to blow up in your face.\n\n The application Adobe Photoshop CS4 has unexpectedly ruined your day.\n\nPhotoshop\u2019s propensity to crash at crucial moments is a running joke in the industry, as is its barely usable interface. And don\u2019t even get me started on the hot, steaming pile of crap that is text rendering.\n\n Text rendered in Photoshop (left) versus Safari (right).\n\nCrashing and text rendering issues suck, but we\u2019ve learned to live with them. The real issue with using Photoshop for mockups is the expectations you\u2019re setting for a client. When you send the client a static image of the design, you\u2019re not giving them the whole picture \u2014 they can\u2019t see how a fluid grid would function, how the design will look in a variety of browsers, basic interactions like :hover effects, or JavaScript behaviors. For more on the disadvantages to showing clients designs as images rather than websites, check out Andy Clarke\u2019s Time to stop showing clients static design visuals.\n\nA necessary evil?\n\nIn the past we\u2019ve put up with Photoshop because it was vital to achieving our beloved rounded corners, drop shadows, outer glows, and gradients. However, with the recent adaptation of CSS3 in major browsers, and the slow, joyous death of IE6, browsers can render mockups that are just as beautiful as those created in an image editor. With the power of RGBA, text-shadow, box-shadow, border-radius, transparent PNGs, and @font-face combined, you can create a prototype that radiates shiny awesomeness right in the browser. If you can see this epic article through to the end, I\u2019ll show you step by step how to create a gorgeous mockup using mostly markup.\n\nGet started by getting naked \n\n\n\tContent precedes design. Design in the absence of content is not design, it\u2019s decoration.\n\n\t Jeffrey Zeldman\n\n\nIn the beginning, don\u2019t even think about style. Instead, start with the foundation: the content. Lay the groundwork for your markup order, and ensure that your design will be useable with styles and images turned off. This is great for prioritizing the content, and puts you on the right path for accessibility and search engine optimization. Not a bad place to start, amirite?\n\n An example of unstyled content, in all its naked glory. View it large.\n\nFlush out the layout \n\nThe next step is to structure the content in a usable way. With CSS, making basic layout changes is as easy as switching up a float, so experiment to see what structure suits the content best.\n\n The mockup with basic layout work done.\n\nGot your grids covered\n\nThere are a variety of tools that allow you to layer a grid over your browser window. For Mac users I recommend using Slammer, and PC users can check out one of the bookmarklets that are available, such as 960 Gridder.\n\n The mockup with a grid applied using Slammer.\n\nOnce you\u2019ve found a layout that works well for the content, pass it along to the client for review. This keeps them involved in the design process, and gives them an idea of how the site will be structured when it\u2019s live.\n\nStart your styling\n\nNow for the fun part: begin applying the presentation layer. Let usability considerations drive your decisions about color and typography; use highlighted colors and contrasting typefaces on elements you wish to emphasize.\n\nRGBA? More like RGByay!\n\nIntroducing color is easy with RGBA. I like to start with the page\u2019s main color, then use white at varying opacities to empasize content sections.\n\n In the example mockup the body background is set to rgba(203,111,21), the content containers are set to rgba(255,255,255,0.7), and a few elements are highlighted with rgba(255,255,255,0.1) If you\u2019re not sure how RGBA works, check out Drew McLellan\u2019s super helpful 24ways article.\n\nLaying down type\n\nJust like with color, you can use typography to evoke a feeling and direct a user\u2019s attention. Have contrasting typefaces (like serif headlines and sans-serif body text) to group the content into meaningful sections.\n\nIn a recent A List Apart article, the Master of Web Typography\u2122 Jason Santa Maria offers excellent advice on how to choose your typefaces:\n\n\n\tWrite down a general description of the qualities of the message you are trying to convey, and then look for typefaces that embody those qualities.\n\n\nSounds pretty straightforward. I wanted to give my design a classic feel with a hint of nostalgia, so I used Georgia for the headlines, and incorporated the ornate ampersand from Baskerville into the header.\n\n A closeup on the site\u2019s header.\n\nLet\u2019s get sexy\n\nThe design doesn\u2019t look too bad as it is, but it\u2019s still pretty flat. We can do better, and after mixing in some CSS3 and a couple of PNGs, it\u2019s going to get downright steamy in here.\n\nGive it some glow\n\nObjects in the natural world reflect light, so to make your design feel tangible and organic, give it some glow. In the example design I achieved this by creating two white to transparent gradients of varying opacities. Both have a solid white border across their top, which gives edges a double border effect and makes them look sharper. Using CSS3\u2019s text-shadow on headlines and box-shadow on content modules is another quick way to add depth.\n\n A wide and closeup view of the design with gradients, text-shadow and box-shadow added. For information on how to implement text-shadow and box-shadow using RGBA, check out the article I wrote on it last week.\n\n\n37 pieces of flair\n\nOkay, maybe you don\u2019t need that much flair, but it couldn\u2019t hurt to add a little; it\u2019s the details that will set your design apart. Work in imagery and texture, using PNGs with an alpha channel so you can layer images and still tweak the color later on.\n\n The design with grungy textures, a noisy diagonal stripe pattern, and some old transportation images layered behind the text. Because the colors are rendered using RGBA, these images bleed through the content, giving the design a layered feel. Best viewed large.\n\n\nSend it off\n\nHey, look at that. You\u2019ve got a detailed, well structured mockup for the client to review. Best of all, your markup is complete too. If the client approves the design at this stage, your template is practically finished. Bust out the party hats!\n\nNot so fast, Buster!\n\nSo I don\u2019t know about you, but I\u2019ve never gotten a design past the client\u2019s keen eye for criticism on the first go. Let\u2019s review some hypothetical feedback (none of which is too outlandish, in my experience), and see how we\u2019d make the requested changes in the browser. \n\nUpdating the typography\n\n\n\tMy ex-girlfriend loved Georgia, so I never want to see it again. Can we get rid of it? I want to use a font that\u2019s chunky and loud, just like my stupid ex-girlfriend.\n\n\t Fakey McClient\n\n\nYikes! Thankfully with CSS, removing Georgia is as easy as running a find and replace on the stylesheet. In my revised mockup, I used @font-face and League Gothic on the headlines to give the typography the, um, unique feel the client is looking for.\n\n The same mockup, using @font-face on the headlines. If you\u2019re unfamiliar with implementing @font-face, check out Nice Web Type\u2018s helpful article.\n\nAdding rounded corners\n\n\n\tI\u2019m not sure if I\u2019ll like it, but I want to see what it\u2019d look like with rounded corners. My cousin, a Web 2.0 marketing guru, says they\u2019re trendy right now.\n\n\t Fakey McClient\n\n\nSwitching to rounded corners is a nightmare if you\u2019re doing your mockup in Photoshop, since it means recreating most of the shapes and UI elements in the design. Thankfully, with CSS border-radius comes to our rescue! By applying this gem of a style to a handful of classes, you\u2019ll be rounded out in no time.\n\n The mockup with rounded corners, created using border-radius. If you\u2019re not sure how to implement border-radius, check out CSS3.info\u2018s quick how-to.\n\nMaking changes to the color\n\n\n\tThe design is too dark, it\u2019s depressing! They call it \u2018the blues\u2019 for a reason, dummy. Can you try using a brighter color? I want orange, like Zeldman uses.\n\n\t Fakey McClient\n\n\nMaking color changes is another groan-inducing task when working in Photoshop. Finding and updating every background layer, every drop shadow, and every link can take forever in a complex PSD. However, if you\u2019ve done your mockup in markup with RGBA and semi-transparent PNGs, making changes to your color is as easy as updating the body background and a few font colors.\n\n The mockup with an orange color scheme. Best viewed large.\n\nAhem, what about Internet Explorer?\n\nGee, thanks for reminding me, buzzkill. Several of the CSS features I\u2019ve suggested you use, such as RGBA, text-shadow and box-shadow, and border-radius, are not supported in Internet Explorer. I know, it makes me sad too. However, this doesn\u2019t mean you can\u2019t try these techniques out in your markup based mockups. The point here is to get your mockups done as efficiently as possible, and to keep the emphasis on markup from the very beginning.\n\nOnce the design is approved, you and the client have to decide if you can live with the design looking different in different browsers. Is it so bad if some users get to see drop shadows and some don\u2019t? Or if the rounded corners are missing for a portion of your audience? The design won\u2019t be broken for IE people, they\u2019re just missing out on a few visual treats that other users will see.\n\nThe idea of rewarding users who choose modern browsers is not a new concept; Dan covers it thoroughly in Handcrafted CSS, and it\u2019s been written about in the past by Aaron Gustafson and Andy Clarke on several occasions. I believe we shouldn\u2019t have to design for the lowest common denominator (cough, IE6 users, cough); instead we should create designs that are beautiful in modern browsers, but still degrade nicely for the other guy. However, some clients just aren\u2019t that progressive, and in that case you can always use background images for drop shadows and rounded corners, as you have in the past. \n\nClosing thoughts\n\nWith the advent of CSS3, browsers are just as capable of giving us beautiful, detailed mockups as Photoshop, and in half the time. I\u2019m not the only one to make an argument for this revised process; in his article Time to stop showing clients static design visuals, and in his presentation Walls Come Tumbling Down, Andy Clarke makes a fantastic case for creating your mockups in markup.\n\nSo I guess my challenge to you for 2010 is to get out of Photoshop and into the code. Even if the arguments for designing in the browser aren\u2019t enough to make you change your process permanently, it\u2019s worthwhile to give it a try. Look at the New Year as a time to experiment; applying constraints and evaluating old processes can do wonders for improving your efficiency and creativity.", "year": "2009", "author": "Meagan Fisher", "author_slug": "meaganfisher", "published": "2009-12-24T00:00:00+00:00", "url": "https://24ways.org/2009/make-your-mockup-in-markup/", "topic": "process"} {"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": 187, "title": "A New Year's Resolution", "contents": "The end of 2009 is fast approaching. Yet another year has passed in a split second. Our Web Designing careers are one year older and it\u2019s time to reflect on the highs and lows of 2009. What was your greatest achievement and what could you have done better? Perhaps, even more importantly, what are your goals for 2010?\n\nSomething that I noticed in 2009 is that being a web designer 24/7; it\u2019s easy to get consumed by the web. It\u2019s easy to get caught up in the blog posts, CSS galleries, web trends and Twitter! Living in this bubble can lead to one\u2019s work becoming stale, boring and basically like everyone else\u2019s work on the web. No designer wants this.\n\nSo, I say on 1st January 2010 let\u2019s make it our New Year\u2019s resolution to create something different, something special or even ground-breaking! Make it your goal to break the mold of current web design trends and light the way for your fellow web designer comrades!\n\nOf course I wouldn\u2019t let you embark on the New Year empty handed. To help you on your way I\u2019ve compiled a few thoughts and ideas to get your brains ticking!\n\nDon\u2019t design for the web, just design\n\nA key factor in creating something original and fresh for the web is to stop thinking in terms of web design. The first thing we need to do is forget the notion of headers, footers, side bars etc. A website doesn\u2019t necessarily need any of these, so even before we\u2019ve started we\u2019ve already limited our design possibilities by thinking in these very conventional and generally accepted web terms. The browser window is a 2D canvas like any other and we can do with it what we like. \n\nWith this in mind we can approach web design from a fresh perspective. We can take inspiration for web design from editorial design, packaging design, comics, poster design, album artwork, motion design, street signage and anything else you can think of. Web design is way more than the just the web and by taking this more wide angled view of what web design is and can be you\u2019ll find there are a thousand more exiting design possibilities.\n\nNote: Try leaving the wire framing till after you\u2019ve gone to town with some initial design concepts. You might find it helps keep your head out of that \u2018web space\u2019 a little bit longer, thus enabling you to think more freely about your design. Really go crazy with these as you can always pull it back into line later. The key is to think big initially and then work backwards. There\u2019s no point restricting your creativity early on because your technical knowledge can foresee problems down the line. You can always sort these problems out later on\u2026 let your creative juices flow!\n\n Inspiration can come from anywhere! (Photo: modomatic)\n\nTry something new!\n\nProgress in web design or in any design discipline is a sort of evolution. Design trends and solutions merge and mutate to create new design trends and hopefully better solutions. This is fine but the real leaps are made when someone has the guts to do something different. \n\nDon\u2019t be afraid to challenge the status quo. To create truly original work you have to be prepared to get it wrong and that\u2019s hard to do. When you\u2019re faced with this challenge just remind yourself that in web design there is rarely a \u2018best way to do something\u2019, or why would we ever do it any other way? \n\nIf you do this and get it right the pay off can be immense. Not only will you work stand out from the crowd by a mile, you will have become a trend setter as opposed to a trend follower.\n\nTell a story with your design\n\nGreat web design is way more than just the aesthetics, functionality or usability. Great web design goes beyond the pixels on the screen. For your website to make a real impact on it\u2019s users it has to connect with them emotionally. So, whether your website is promoting your own company or selling cheese it needs to move people. You need to weave a story into your design. It\u2019s this story that your users will connect with. \n\nTo do this the main ingredients of your design need to be strongly connected. In my head those main ingredients are Copy, Graphic Design, Typography, imagery and colour. \n\nCopy\n\nStrong meaningful copy is the backbone to most great web design work. Pay special attention to strap lines and headlines as these are often the sparks that start the fire. All the other elements can be inspired by this backbone of strong copy.\n\nGraphic Design\n\nUse the copy to influence how you treat the page with your graphic design. Let the design echo the words.\n\nTypography\n\nWhat really excites me about typography isn\u2019t the general text presentation on a page, most half decent web designer have a grasp of this already. What excites me is the potential there is to base a whole design on words and letters. Using the strong copy you already have, one has the opportunity the customise, distort, build and arrange words and letters to create beautiful and powerful compositions that can be the basis for an entire site design.\n\n Get creative with Typography (Photo: Pam Sattler)\n\nImagery and Colour\n\nWith clever use of imagery (photographs or illustrations) and colour you further have the chance to deepen the story you are weaving into your design. The key is to use meaningful imagery, don\u2019t to insert generic imagery for the sake of filling space\u2026 it\u2019s just a wasted opportunity.\n\nRemember, the main elements of your design combined are greater than the sum of their parts. Whatever design decisions you make on a page, make them for a good reason. It\u2019s not good enough to try and seduce your users with slick and shiny web pages. For your site to leave a lasting impression on the user you need to make that emotional connection.\n\n Telling the Story (Advertising Agency: Tita, Milano, Italy, Art Director: Emanuele Basso)\n\nGo one step further\n\nSo you\u2019ve almost finished your latest website design. You\u2019ve fulfilled the brief, you\u2019re happy with the result and you\u2019re pretty sure your client will be too. It\u2019s at this point we should ask ourselves \u201cCan I push this further\u201d? What touches could you add to the site that\u2019ll take it beyond what was required and into something exceptional? The truth is, to produce exceptional work we need to do more than is required of us. We need to answer the brief and then some!\n\nGo back through your site and make a note of what enhancements could be made to make the site not just good but outstanding. It might be revisiting a couple of pages that were neglected in the design process, it might be adding some CSS 3 gloss for the users that can benefit from it or it might just be adding some clever little easter eggs to show that you care. These touches will soon add up and make a massive difference to the finished product.\n\nSo, go one step further\u2026 take it further than you anyone else will. Then your work will stand out for sure.\n\nParting message\n\nI love being a designer for many of reasons but the main one being that with every new project we embark on we have the chance to express ourselves. We have the chance to create something special, something that people will talk about. It\u2019s this chance that drives us onwards day after day, year after year. So in 2010 shout louder than you ever have before, take chances, try something new and above all design your socks off!", "year": "2009", "author": "Mike Kus", "author_slug": "mikekus", "published": "2009-12-10T00:00:00+00:00", "url": "https://24ways.org/2009/a-new-years-resolution/", "topic": "business"} {"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": 189, "title": "Ignorance Is Bliss", "contents": "This is a true story.\n\nMeet Mike \n\nMike\u2019s a smart guy. He knows a great browser when he sees one. He uses Firefox on his Windows PC at work and Safari on his Mac at home. Mike asked us to design a Web site for his business. So we did.\n\nWe wanted to make the best Web site for Mike that we could, so we used all of the CSS tools that are available today. That meant using RGBa colour to layer elements, border-radius to add subtle rounded corners and (possibly most experimental of all new CSS), generated gradients.\n\n The home page Mike sees in Safari on his Mac\n\nMike loves what he sees.\n\nMeet Sam\n\nSam works with Mike. She uses Internet Explorer 7 because it came on the Windows laptop that the company bought her when she joined. \n\n The home page Sam sees in Internet Explorer 7 on her PC\n\nSam loves the new Web site too.\n\nHow could both of them be happy when they experienced the Web site differently?\n\nThe new WYSIWYG\n\nWhen I first presented my designs to Mike and Sam, I showed them a Web page made with HTML and CSS in their respective browsers and not a picture of a Web page. By showing neither a static image of my design, I set none of the false expectations that, by definition, a static Photoshop or Fireworks visual would have established.\n\nMike saw rounded corners and subtle shadows in Firefox and Safari. Sam saw something equally as nice, just a little different, in Internet Explorer. Both were very happy because they saw something that they liked.\n\nNeither knew, or needed to know, about the subtle differences between browsers. Their users don\u2019t need to know either.\n\nThat\u2019s because in the real world, people using the Web don\u2019t find a Web site that they like, then open up another browser to check that it looks they same. They simply buy what they came to buy, read what what they came to read, do what they came to do, then get on with their lives in blissful ignorance of what they might be seeing in another browser.\n\nOften when I talk or write about using progressive CSS, people ask me, \u201cHow do you convince clients to let you work that way? What\u2019s your secret?\u201d Secret? I tell them what they need to know, on a need-to-know basis.\n\nEpilogue\n\nSam has a new iPhone that Mike bought for her as a reward for achieving her sales targets. She loves her iPhone and was surprised at just how fast and good-looking the company Web site appears on that. So she asked,\n\n\n\t\u201cAndy, I didn\u2019t know you optimised our site for mobile. I don\u2019t remember seeing an invoice for that.\u201d\n\n\nI smiled.\n\n\n\t\u201cThat one was on the house.\u201d", "year": "2009", "author": "Andy Clarke", "author_slug": "andyclarke", "published": "2009-12-23T00:00:00+00:00", "url": "https://24ways.org/2009/ignorance-is-bliss/", "topic": "business"} {"rowid": 190, "title": "Self-Testing Pages with JavaScript", "contents": "Working at an agency I am involved more and more on projects in which client side code is developed internally then sent out to a separate team for implementation. You provide static HTML, CSS and JavaScript which then get placed into the CMS and brought to life as an actual website. As you can imagine this can sometimes lead to frustrations. However many safeguards you include, handing over your code to someone else is always a difficult thing to do effectively.\n\nIn this article I will show you how you can create a JavaScript implementation checker and that will give you more time for drink based activity as your web site and apps are launched quicker and with less unwanted drama!\n\nAn all too frequent occurrence\n\nYou\u2019ve been working on a project for weeks, fixed all your bugs and send it to be implemented. You hear nothing and assume all is going well then a few days before it\u2019s meant to launch you get an email from the implementation team informing you of bugs in your code that you need to urgently fix.\n\n The 24ways website with a misspelt ID for the years menu\n\nBeing paranoid you trawl through the preview URL, check they have the latest files, check your code for errors then notice that a required HTML attribute has been omitted from the build and therefore CSS or JavaScript you\u2019ve hooked onto that particular attribute isn\u2019t being applied and that\u2019s what is causing the \u201cbug\u201d.\n\nIt takes you seconds drafting an email informing them of this, it takes then seconds putting the required attribute in and low and behold the bug is fixed, everyone is happy but you\u2019ve lost a good few hours of your life \u2013 this time could have been better spent in the pub.\n\nI\u2019m going to show you a way that these kind of errors can be alerted immediately during implementation of your code and ensure that when you are contacted you know that there actually is a bug to fix. You probably already know the things that could be omitted from a build and look like bugs so you\u2019ll soon be creating tests to look for these and alert when they are not found on the rendered page. The error is reported directly to those who need to know about it and fix it. Less errant bug reports and less frantic emails ahoy!\n\n A page with an implementation issue and instant feedback on the problem\n\nJavaScript selector engines to the rescue\n\nWhether you\u2019re using a library or indeed tapping into the loveliness of the new JavaScript Selector APIs looking for particular HTML elements in JavaScript is fairly trivial now. \n\nFor instance this is how you look for a div element with the id attribute of year (the missing attribute from top image) using jQuery (the library I\u2019ll be coding my examples in): \n\nif ($(\u2018div#year\u2019).length) {\n\talert(\u2018win\u2019);\n}\n\nUsing this logic you can probably imagine how you can write up a quick method to check for the existence of a particular element and alert when it\u2019s not present \u2014 but assuming you have a complex page you\u2019re going to be repeating yourself a fair bit and we don\u2019t want to be doing that.\n\nTest scripts\n\nIf you\u2019ve got a lot of complex HTML patterns that need testing across a number of different pages it makes sense to keep your tests out of production code. Chances are you\u2019ve already got a load of heavy JavaScript assets, and when it comes to file size saving every little helps.\n\nI don\u2019t think that tests should contain code inside of them so keep mine externally as JSON. This also means that you can use the one set of tests in multiple places. We already know that it\u2019s a good idea to keep our CSS and JavaScript separate so lets continue along those lines here.\n\nThe test script for this example looks like this:\n\n{\n\t\"title\": \"JS tabs implementation test\",\n\t\"description\": \"Check that the correct HTML patterns has been used\",\n\t\"author\": \"Ross Bruniges\",\n\t\"created\": \"20th July 2009\",\n\t\"tests\": [\n\t\t{\n\t\t\t\"name\": \"JS tabs elements\",\n\t\t\t\"description\": \"Checking that correct HTML elements including class/IDs are used on the page for the JS to progressively enhance\",\n\t\t\t\"selector\": \"div.tabbed_content\",\n\t\t\t\"message\": \"We couldn't find VAR on the page - it's required for our JavaScript to function correctly\",\n\t\t\t\"check_for\": {\n\t\t\t\t\"contains\": {\n\t\t\t\t\t\"elements\": [\n\t\t\t\t\t\t\"div.tab_content\", \"h2\" \n\t\t\t\t\t],\n\t\t\t\t\t\"message\": \"We've noticed some missing HTML:

                        • VAR

                        please refer to the examples sent for reference\" \n\t\t\t\t} \n\t\t\t} \n\t\t} \n\t]\n}\n\nThe first four lines are just a little bit of meta data so we remember what this test was all about when we look at it again in the future, or indeed if it ever breaks. The tests are the really cool parts and firstly you\u2019ll notice that it\u2019s an array \u2013 we\u2019re only going to show one example test here but there is no reason why you can\u2019t place in as many as you want. I\u2019ll explain what each of the lines in the example test means:\n\n\n\tname \u2013 short test name, I use this in pass/fail messaging later\n\tdescription \u2013 meta data for future reference\n\tselector \u2013 the root HTML element from which your HTML will be searched\n\tmessage \u2013 what the app will alert if the initial selector isn\u2019t found\n\tcheck_for \u2013 a wrapper to hold inner tests \u2013 those run if the initial selector does match\n\t\n\t\tcontains \u2013 the type of check, we\u2019re checking that the selector contains specified elements\n\t\t\n\t\t\telements \u2013 the HTML elements we are searching for\n\t\t\tmessage \u2013 a message for when these don\u2019t match (VAR is substituted when it\u2019s appended to the page with the name of any elements that don\u2019t exist)\n\t\t\n\t\t\n\t\t\n\nIt\u2019s very important to pass the function valid JSON (JSONLint is a great tool for this) otherwise you might get a console showing no tests have even been run. \n\nThe JavaScript that makes this helpful\n\nAgain, this code should never hit a production server so I\u2019ve kept it external. This also means that the only thing that\u2019s needed to be done by the implementation team when they are ready to build is that they delete this code.\n\n\n\n\n\u201cView the full JavaScript:/examples/self-testing-pages-with-javascript/js/tests/test_suite.js\n\nThe init function appends the test console to the page and inserts the CSS file required to style it (you don\u2019t need to use pictures of me when tests pass and fail though I see no reason why you shouldn\u2019t), goes and grabs the JSON file referenced and parses it. The methods to pass (tests_pass) and fail (haz_fail) the test I hope are pretty self-explanatory as is the one which creates the test summary once everything has been run (create_summary).\n\nThe two interesting functions are init_tests and confirm_html.\n\ninit_tests\n\ninit_tests:function(i,obj) {\n\tvar $master_elm = $(obj.selector);\n\tsleuth.test_page.$logger.append(\"

                        \" + obj.name + \"

                        \");\n\tvar $container = $('#test_' + i);\n\tif (!$master_elm.length) {\n\t\tvar err_sum = obj.message.replace(/VAR/gi, obj.selector);\n\t\tsleuth.test_page.haz_failed(err_sum, $container);\n\t\treturn;\n\t}\n\tif (obj.check_for) {\n\t\t$.each(obj.check_for,function(key, value){\n\t\t\tsleuth.test_page.assign_checks($master_elm, $container, key, value);\n\t\t});\n\t} else {\n\t\tsleuth.test_page.tests_passed($container);\n\t\treturn;\n\t}\n}\n\nThe function gets sent the number of the current iteration (used to create a unique id for its test summary) and the current object that contains the data we\u2019re testing against as parameters.\n\nWe grab a reference to the root element and this is used (pretty much in the example shown right at the start of this article) and its length is checked. If the length is positive we know we can continue to the inner tests (if they exist) but if not we fail the test and don\u2019t go any further. We append the error to the test console for everyone to see.\n\nIf we pass the initial check we send the reference to the root element, message contains and the inner object to a function that in this example sends us on to confirm_html (if we had a more complex test suite it would do a lot more). \n\nconfirm_html\n\nconfirm_html:function(target_selector, error_elm, obj) {\n\tvar missing_elms = [];\n\t$.each(obj.elements, function(i, val) {\n\t\tif (!target_selector.find(val).length) {\n\t\t\tmissing_elms.push(val);\n\t\t}\t\n\t});\n\tif (missing_elms.length) {\n\t\tvar file_list = missing_elms.join('
                      • ');\n\t\tvar err_sum = obj.message.replace(/VAR/gi, file_list);\n\t\tsleuth.test_page.haz_failed(err_sum, error_elm);\n\t\treturn;\n\t}\n\tsleuth.test_page.tests_passed(error_elm);\n\treturn;\n}\n\nWe\u2019re again using an array to check for a passed or failed test and checking its length but this time we push in a reference to each missing element we find.\n\nIf the test does fail we\u2019re providing even more useful feedback by informing what elements have been missed out. All the implementation team need do is look for them in the files we\u2019ve sent and include them as expected.\n\nNo more silly implementation bugs!\n\nHere is an example of a successful implementation.\n\nHere are some examples of failed implementations \u2013 one which fails at finding the root node and one that has the correct root node but none of the inner HTML tests pass.\n\nIs this all we can check for?\n\nCertainly not!\n\nJavaScript provides pretty easy ways to check for attributes, included files (if the files being checked for are being referenced correctly and not 404ing) and even applied CSS.\n\nWant to check that those ARIA attributes are being implemented correctly or that all images contain an alt attribute well this simple test suite can be extended to include tests for this \u2013 the sky is pretty much up to your imagination.", "year": "2009", "author": "Ross Bruniges", "author_slug": "rossbruniges", "published": "2009-12-12T00:00:00+00:00", "url": "https://24ways.org/2009/self-testing-pages-with-javascript/", "topic": "process"} {"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"} {"rowid": 193, "title": "Web Content Accessibility Guidelines\u2014for People Who Haven't Read Them", "contents": "I\u2019ve been a huge fan of the Web Content Accessibility Guidelines 2.0 since the World Wide Web Consortium (W3C) published them, nine years ago. I\u2019ve found them practical and future-proof, and I\u2019ve found that they can save a huge amount of time for designers and developers. You can apply them to anything that you can open in a browser. My favourite part is when I use the guidelines to make a website accessible, and then attend user-testing and see someone with a disability easily using that website.\nToday, the United Nations International Day of Persons with Disabilities, seems like a good time to re-read Laura Kalbag\u2019s explanation of why we should bother with accessibility. That should motivate you to devour this article.\nIf you haven\u2019t read the Web Content Accessibility Guidelines 2.0, you might find them a bit off-putting at first. The editors needed to create a single standard that countries around the world could refer to in legislation, and so some of the language in the guidelines reads like legalese. The editors also needed to future-proof the guidelines, and so some terminology\u2014such as \u201ctime-based media\u201d and \u201cprogrammatically determined\u201d\u2014can sound ambiguous. The guidelines can seem lengthy, too: printing the guidelines, the Understanding WCAG 2.0 document, and the Techniques for WCAG 2.0 document would take 1,200 printed pages.\nThis festive season, let\u2019s rip off that legalese and ambiguous terminology like wrapping paper, and see\u2014in a single article\u2014what gifts the Web Content Accessibility Guidelines 2.0 editors have bestowed upon us.\nCan your users perceive the information on your website?\nThe first guideline has criteria that help you prevent your users from asking \u201cWhat the **** is this thing here supposed to be?\u201d\n1.1.1 Text is the most accessible format for information. Screen readers\u2014such as the \u201cVoiceOver\u201d setting on your iPhone or the \u201cTalkBack\u201d app on your Android phone\u2014understand text better than any other format. The same applies for other assistive technology, such as translation apps and Braille displays. So, if you have anything on your webpage that\u2019s not text, you must add some text that gives your user the same information. You probably know how to do this already; for example:\n\nfor images in webpages, put some alternative text in an alt attribute to tell your user what the image conveys to the user;\nfor photos in tweets, add a description to make the images accessible;\nfor Instagram posts, write a caption that conveys the photo\u2019s information.\n\nThe alternative text should allow the user to get the same information as someone who can see the image. For websites that have too many images for someone to add alternative text to, consider how machine learning and Dynamically Generated Alt Text might\u2014might\u2014be appropriate.\nYou can probably think of a few exceptions where providing text to describe an image might not make sense. Remember I described these guidelines as \u201cpractical\u201d? They cover all those exceptions:\n\nUser interface controls such as buttons and text inputs must have names or labels to tell your user what they do.\nIf your webpage has video or audio (more about these later on!), you must\u2014at least\u2014have text to tell the user what they are.\nMaybe your webpage has a test where your user has to answer a question about an image or some audio, and alternative text would give away the answer. In that case, just describe the test in text so your users know what it is.\nIf your webpage features a work of art, tell your user the experience it evokes.\nIf you have to include a Captcha on your webpage\u2014and please avoid Captchas if at all possible, because some users cannot get past them\u2014you must include text to tell your user what it is, and make sure that it doesn\u2019t rely on only one sense, such as vision.\nIf you\u2019ve included something just as decoration, you must make sure that your user\u2019s assistive technology can ignore it. Again, you probably know how to do this. For example, you could use CSS instead of HTML to include decorative images, or you could add an empty alt attribute to the img element. (Please avoid that recent trend where developers add empty alt attributes to all images in a webpage just to make the HTML validate. You\u2019re better than that.)\n\n(Notice that the guidelines allow you to choose how to conform to them, with whatever technology you choose. To make your website conform to a guideline, you can either choose one of the techniques for WCAG 2.0 for that guideline or come up with your own. Choosing a tried-and-tested technique usually saves time!)\n1.2.1 If your website includes a podcast episode, speech, lecture, or any other recorded audio without video, you must include a transcription or some other text to give your user the same information. In a lot of cases, you might find this easier than you expect: professional transcription services can prove relatively inexpensive and fast, and sometimes a speaker or lecturer can provide the speech or lecture notes that they read out word-for-word. Just make sure that all your users can get the same information and the same results, whether they can hear the audio or not. For example, David Smith and Marco Arment always publish episode transcripts for their Under the Radar podcast. \nSimilarly, if your website includes recorded video without audio\u2014such as an animation or a promotional video\u2014you must either use text to detail what happens in the video or include an audio version. Again, this might work out easier then you perhaps fear: for example, you could check to see whether the animation started life as a list of instructions, or whether the promotional video conveys the same information as the \u201cAbout Us\u201d webpage. You want to make sure that all your users can get the same information and the same results, whether they can see that video or not.\n1.2.2 If your website includes recorded videos with audio, you must add captions to those videos for users who can\u2019t hear the audio. Professional transcription services can provide you with time-stamped text in caption formats that YouTube supports, such as .srt and .sbv. You can upload those to YouTube, so captions appear on your videos there. YouTube can auto-generate captions, but the quality varies from impressively accurate to comically inaccurate. If you have a text version of what the people in the video said\u2014such as the speech that a politician read or the bedtime story that an actor read\u2014you can create a transcript file in .txt format, without timestamps. YouTube then creates captions for your video by synchronising that text to the audio in the video. If you host your own videos, you can ask a professional transcription service to give you .vtt files that you can add to a video element\u2019s track element\u2014or you can handcraft your own. (A quick aside: if your website has more videos than you can caption in a reasonable amount of time, prioritise the most popular videos, the most important videos, and the videos most relevant to people with disabilities. Then make sure your users know how to ask you to caption other videos as they encounter them.)\n1.2.3 If your website has recorded videos that have audio, you must add an \u201caudio description\u201d narration to the video to describe important visual details, or add text to the webpage to detail what happens in the video for users who cannot see the videos. (I like to add audio files from videos to my Huffduffer account so that I can listen to them while commuting.) Maybe your home page has a video where someone says, \u201cI\u2019d like to explain our new TPS reports\u201d while \u201cBill Lumbergh, division Vice President of Initech\u201d appears on the bottom of the screen. In that case, you should add an audio description to the video that announces \u201cBill Lumbergh, division Vice President of Initech\u201d, just before Bill starts speaking. As always, you can make life easier for yourself by considering all of your users, before the event: in this example, you could ask the speaker to begin by saying, \u201cI\u2019m Bill Lumbergh, division Vice President of Initech, and I\u2019d like to explain our new TPS reports\u201d\u2014so you won\u2019t need to spend time adding an audio description afterwards. \n1.2.4 If your website has live videos that have some audio, you should get a stenographer to provide real-time captions that you can include with the video. I\u2019ll be honest: this can prove tricky nowadays. The Web Content Accessibility Guidelines 2.0 predate YouTube Live, Instagram live Stories, Periscope, and other such services. If your organisation creates a lot of live videos, you might not have enough resources to provide real-time captions for each one. In that case, if you know the contents of the audio beforehand, publish the contents during the live video\u2014or failing that, publish a transcription as soon as possible.\n1.2.5 Remember what I said about the recorded videos that have audio? If you can choose to either add an audio description or add text to the webpage to detail what happens in the video, you should go with the audio description.\n1.2.6 If your website has recorded videos that include audio information, you could provide a sign language version of the audio information; some people understand sign language better than written language. (You don\u2019t need to caption a video of a sign language version of audio information.)\n1.2.7 If your website has recorded videos that have audio, and you need to add an audio description, but the audio doesn\u2019t have enough pauses for you to add an \u201caudio description\u201d narration, you could provide a separate version of that video where you have added pauses to fit the audio description into.\n1.2.8 Let\u2019s go back to the recorded videos that have audio once more! You could add text to the webpage to detail what happens in the video, so that people who can neither read captions nor hear dialogue and audio description can use braille displays to understand your video.\n1.2.9 If your website has live audio, you could get a stenographer to provide real-time captions. Again, if you know the contents of the audio beforehand, publish the contents during the live audio or publish a transcription as soon as possible.\n(Congratulations on making it this far! I know that seems like a lot to remember, but keep in mind that we\u2019ve covered a complex area: helping your users to understand multimedia information that they can\u2019t see and/or hear. Grab a mince pie to celebrate, and let\u2019s keep going.)\n1.3.1 You must mark up your website\u2019s content so that your user\u2019s browser, and any assistive technology they use, can understand the hierarchy of the information and how each piece of information relates to the rest. Once again, you probably know how to do this: use the most appropriate HTML element for each piece of information. Mark up headings, lists, buttons, radio buttons, checkboxes, and links with the most appropriate HTML element. If you\u2019re looking for something to do to keep you busy this Christmas, scroll through the list of the elements of HTML. Do you notice any elements that you didn\u2019t know, or that you\u2019ve never used? Do you notice any elements that you could use on your current projects, to mark up the content more accurately? Also, revise HTML table advanced features and accessibility, how to structure an HTML form, and how to use the native form widgets\u2014you might be surprised at how much you can do with just HTML! Once you\u2019ve mastered those, you can make your website much more usable for your all of your users.\n1.3.2 If your webpage includes information that your user has to read in a certain order, you must make sure that their browser and assistive technology can present the information in that order. Don\u2019t rely on CSS or whitespace to create that order visually. Check that the order of the information makes sense when CSS and whitespace aren\u2019t formatting it. Also, try using the Tab key to move the focus through the links and form widgets on your webpage. Does the focus go where you expect it to? Keep this in mind when using order in CSS Grid or Flexbox.\n1.3.3 You must not presume that your users can identify sensory characteristics of things on your webpage. Some users can\u2019t tell what you\u2019ve positioned where on the screen. For example, instead of asking your users to \u201cChoose one of the options on the left\u201d, you could ask them to \u201cChoose one of our new products\u201d and link to that section of the webpage.\n1.4.1 You must not rely on colour as the only way to convey something to your users. Some of your users can\u2019t see, and some of your users can\u2019t distinguish between colours. For example, if your webpage uses green to highlight the products that your shop has in stock, you could add some text to identify those products, or you could group them under a sub-heading.\n1.4.2 If your webpage automatically plays a sound for more than 3 seconds, you must make sure your users can stop the sound or change its volume. Don\u2019t rely on your user turning down the volume on their computer; some users need to hear the screen reader on their computer, and some users just want to keep listening to whatever they were listening before your webpage interrupted them!\n1.4.3 You should make sure that your text contrasts enough with its background, so that your users can read it. Bookmark Lea Verou\u2019s Contrast Ratio calculator now. You can enter the text colour and background colour as named colours, or as RGB, RGBa, HSL, or HSLa values. You should make sure that:\n\nnormal text that set at 24px or larger has a ratio of at least 3:1;\nbold text that set at 18.75px or larger has a ratio of at least 3:1;\nall other text has a ratio of at least 4\u00bd:1.\n\nYou don\u2019t have to do this for disabled form controls, decorative stuff, or logos\u2014but you could!\n1.4.4 You should make sure your users can resize the text on your website up to 200% without using their assistive technology\u2014and still access all your content and functionality. You don\u2019t have to do this for subtitles or images of text.\n1.4.5 You should avoid using images of text and just use text instead. In 1998, Jeffrey Veen\u2019s first Hot Design Tip said, \u201cText is text. Graphics are graphics. Don\u2019t confuse them.\u201d Now that you can apply powerful CSS text-styling properties, use CSS Grid to precisely position text, and choose from thousands of web fonts (Jeffrey co-founded Typekit to help with this), you pretty much never need to use images of text. The guidelines say you can use images of text if you let your users specify the font, size, colour, and background of the text in the image of text\u2014but I\u2019ve never seen that on a real website. Also, this doesn\u2019t apply to logos.\n1.4.6 Let\u2019s go back to colour contrast for a second. You could make your text contrast even more with its background, so that even more of your users can read it. To do that, use Lea Verou\u2019s Contrast Ratio calculator to make sure that:\n\nnormal text that is 24px or larger has a ratio of at least 4\u00bd:1;\nbold text that 18.75px or larger has a ratio of at least 4\u00bd:1;\nall other text has a ratio of at least 7:1.\n\n1.4.7 If your website has recorded speech, you could make sure there are no background sounds, or that your users can turn off any background sounds. If that\u2019s not possible, you could make sure that any background sounds that last longer than a couple of seconds are at least four times quieter than the speech. This doesn\u2019t apply to audio Captchas, audio logos, singing, or rapping. (Yes, these guidelines mention rapping!)\n1.4.8 You could make sure that your users can reformat blocks of text on your website so they can read them better. To do this, make sure that your users can:\n\nspecify the colours of the text and the background, and\nmake the blocks of text less than 80-characters wide, and \nalign text to the left (or right for right-to-left languages), and \nset the line height to 150%, and \nset the vertical distance between paragraphs to 1\u00bd times the line height of the text, and \nresize the text (without using their assistive technology) up to 200% and still not have to scroll horizontally to read it.\n\nBy the way, when you specify a colour for text, always specify a colour for its background too. Don\u2019t rely on default background colours!\n1.4.9 Let\u2019s return to images of text for a second. You could make sure that you use them only for decoration and logos.\nCan users operate the controls and links on your website?\nThe second guideline has criteria that help you prevent your users from asking, \u201cHow the **** does this thing work?\u201d\n2.1.1 You must make sure that you users can carry out all of your website\u2019s activities with just their keyboard, without time limits for pressing keys. (This doesn\u2019t apply to drawing or anything else that requires a pointing device such as a mouse.) Again, if you use the most appropriate HTML element for each piece of information and for each form element, this should prove easy.\n2.1.2 You must make sure that when the user uses the keyboard to focus on some part of your website, they can then move the focus to some other part of your webpage without needing to use a mouse or touch the screen. If your website needs them to do something complex before they can move the focus elsewhere, explain that to your user. These \u201ckeyboard traps\u201d have become rare, but beware of forms that move focus from one text box to another as soon as they receive the correct number of characters.\n2.1.3 Let\u2019s revisit making sure that you users can carry out all of your website\u2019s activities with just their keyboard, without time limits for pressing keys. You could make sure that your user can do absolutely everything on your website with just the keyboard.\n2.2.1 Sometimes people need more time than you might expect to complete a task on your website. If any part of your website imposes a time limit on a task, you must do at least one of these: \n\nlet your users turn off the time limit before they encounter it; or\nlet your users increase the time limit to at least 10 times the default time limit before they encounter it; or\nwarn your users before the time limit expires and give them at least 20 seconds to extend it, and let them extend it at least 10 times.\n\nRemember: these guidelines are practical. They allow you to enforce time limits for real-time events such as auctions and ticket sales, where increasing or extending time limits wouldn\u2019t make sense. Also, the guidelines allow you to enforce a maximum time limit of 20 hours. The editors chose 20 hours because people need to go to sleep at some stage. See? Practical!\n2.2.2 In my experience, this criterion remains the least well-known\u2014even though some users can only use websites that conform to it. If your website presents content alongside other content that can distract users by automatically moving, blinking, scrolling, or updating, you must make sure that your users can:\n\npause, stop, or hide the other content if it\u2019s not essential and lasts more than 5 seconds; and\npause, stop, hide, or control the frequency of the other content if it automatically updates.\n\nIt\u2019s OK if your users miss live information such as stock price updates or football scores; you can\u2019t do anything about that! Also, this doesn\u2019t apply to animations such as progress bars that you put on a website to let all users know that the webpage isn\u2019t frozen.\n(If this one sounds complex, just add a pause button to anything that might distract your users.)\n2.2.3 Let\u2019s go back to time limits on tasks on your website. You could make your website even easier to use by removing all time limits except those on real-time events such as auctions and ticket sales. That would mean your user wouldn\u2019t need to interact with a timer at all.\n2.2.4 You could let your users turn off all interruptions\u2014server updates, promotions, and so on\u2014apart from any emergency information.\n2.2.5 This is possibly my favourite of these criteria! After your website logs your user out, you could make sure that when they log in again, they can continue from where they were without having lost any information. Do that, and you\u2019ll be on everyone\u2019s Nice List this Christmas.\n2.3.1 You must make sure that nothing flashes more than three times a second on your website, unless you can make sure that the flashes remain below the acceptable general flash and red flash thresholds\u2026\n2.3.2 \u2026or you could just make sure that nothing flashes more than three times per second on your website. This is usually an easier goal.\n2.4.1 You must make sure that your users can jump past any blocks of content, such as navigation menus, that are repeated throughout your website. You know the drill here: using HTML\u2019s sectioning elements such as header, nav, main, aside, and footer allows users with assistive technology to go straight to the content they need, and adding \u201cSkip Navigation\u201d links allows everyone to get to your main content faster.\n2.4.2 You must add a proper title to describe each webpage\u2019s topic. Your webpage won\u2019t even validate without a title element, so make it a useful one.\n2.4.3 If your users can focus on links and native form widgets, you must make sure that they can focus on elements in an order that makes sense.\n2.4.4 You must make sure that your users can understand the purpose of a link when they read:\n\nthe text of the link; or\nthe text of the paragraph, list item, table cell, or table header for the cell that contains the link; or\nthe heading above the link.\n\nYou don\u2019t have to do that for games and quizzes.\n2.4.5 You should give your users multiple ways to find any webpage within a set of webpages. Add site-wide search and a site map and you\u2019re done!\nThis doesn\u2019t apply for a webpage that is part of a series of actions (like a shopping cart and checkout flow) or to a webpage that is a result of a series of actions (like a webpage confirming that the user has bought what was in the shopping cart).\n2.4.6 You should help your users to understand your content by providing:\n\nheadings that describe the topics of you content;\nlabels that describe the purpose of the native form widgets on the webpage.\n\n2.4.7 You should make sure that users can see which element they have focussed on. Next time you use your website, try hitting the Tab key repeatedly. Does it visually highlight each item as it moves focus to it? If it doesn\u2019t, search your CSS to see whether you\u2019ve applied outline: 0; to all elements\u2014that\u2019s usually the culprit. Use the :focus pseudo-element to define how elements should appear when they have focus.\n2.4.8 You could help your user to understand where the current webpage is located within your website. Add \u201cbreadcrumb navigation\u201d and/or a site map and you\u2019re done.\n2.4.9 You could make links even easier to understand, by making sure that your users can understand the purpose of a link when they read the text of the link. Again, you don\u2019t have to do that for games and quizzes.\n2.4.10 You could use headings to organise your content by topic. \nCan users understand your content?\nThe third guideline has criteria that help you prevent your users from asking, \u201cWhat the **** does this mean?\u201d\n3.1.1 Let\u2019s start this section with the criterion that possibly takes the least time to implement; you must make sure that the user\u2019s browser can identify the main language that your webpage\u2019s content is written in. For a webpage that has mainly English content, use . \n3.1.2 You must specify when content in another language appears in your webpage, like so: I wish you a Joyeux No\u00ebl.. You don\u2019t have to do this for proper names, technical terms, or words that you can\u2019t identify a language for. You also don\u2019t have to do it for words from a different language that people consider part of the language around those words; for example, Come to our Christmas rendezvous! is OK.\n3.1.3 You could make sure that your users can find out the meaning of any unusual words or phrases, including idioms like \u201cstocking filler\u201d or \u201cBah! Humbug!\u201d and jargon such as \u201cVoiceOver\u201d and \u201cTalkBack\u201d. Provide a glossary or link to a dictionary.\n3.1.4 You could make sure that your users can find out the meaning of any abbreviation. For example, VoiceOver pronounces \u201cXmas\u201d as \u201cSmas\u201d instead of \u201cChristmas\u201d. Using the abbr element and linking to a glossary can help. (Interestingly, VoiceOver pronounces \u201cabbr\u201d as \u201cabbreviation\u201d!)\n3.1.5 Do your users need to be able to read better than a typically educated nine-year-old, to read your content (apart from proper names and titles)? If so, you could provide a version that doesn\u2019t require that level of reading ability, or you could provide images, videos, or audio to explain your content. (You don\u2019t have to add captions or audio description to those videos.)\n3.1.6 You could make sure that your users can access the pronunciation of any word in your content if that word\u2019s meaning depends on its pronunciation. For example, the word \u201cclose\u201d could have one of two meanings, depending on pronunciation, in a phrase such as, \u201cReady for Christmas? Close now!\u201d\n3.2.1 Some users need to focus on elements to access information about them. You must make sure that focusing on an element doesn\u2019t trigger any major changes, such as opening a new window, focusing on another element, or submitting a form.\n3.2.2 Webpages are easier for users when the controls do what they\u2019re supposed to do. Unless you have warned your users about it, you must make sure that changing the value of a control such as a text box, checkbox, or drop-down list doesn\u2019t trigger any major changes, such as opening a new window, focusing on another element, or submitting a form.\n3.2.3 To help your users to find the content they want on each webpage, you should put your navigation elements in the same place on each webpage. (This doesn\u2019t apply when your user has changed their preferences or when they use assistive technology to change how your content appears.) \n3.2.4 When a set of webpages includes things that have the same functionality on different webpages, you should name those things consistently. For example, don\u2019t use the word \u201cSearch\u201d for the search box on one webpage and \u201cFind\u201d for the search box on another webpage within that set of webpages.\n3.2.5 Let\u2019s go back to major changes, such as a new window opening, another element taking focus, or a form being submitted. You could make sure that they only happen when users deliberately make them happen, or when you have warned users about them first. For example, you could give the user a button for updating some content instead of automatically updating that content. Also, if a link will open in a new window, you could add the words \u201copens in new window\u201d to the link text.\n3.3.1 Users make mistakes when filling in forms. Your website must identify each mistake to your user, and must describe the mistake to your users in text so that the user can fix it. One way to identify mistakes reliably to your users is to set the aria-invalid attribute to true in the element that has a mistake. That makes sure that users with assistive technology will be alerted about the mistake. Of course, you can then use the [aria-invalid=\"true\"] attribute selector in your CSS to visually highlight any such mistakes. Also, look into how certain attributes of the input element such as required, type, and list can help prevent and highlight mistakes.\n3.3.2 You must include labels or instructions (and possibly examples) in your website\u2019s forms, to help your users to avoid making mistakes. \n3.3.3 When your user makes a mistake when filling in a form, your webpage should suggest ways to fix that mistake, if possible. This doesn\u2019t apply in scenarios where those suggestions could affect the security of the content.\n3.3.4 Whenever your user submits information that:\n\nhas legal or financial consequences; or\naffects information that they have previously saved in your website; or\nis part of a test\n\n\u2026you should make sure that they can:\n\nundo it; or\ncorrect any mistakes, after your webpage checks their information; or\nreview, confirm, and correct the information before they finally submit it.\n\n3.3.5 You could help prevent your users from making mistakes by providing obvious, specific help, such as examples, animations, spell-checking, or extra instructions.\n3.3.6 Whenever your user submits any information, you could make sure that they can:\n\nundo it; or\ncorrect any mistakes, after your webpage checks their information; or\nreview, confirm, and correct the information before they finally submit it.\n\nHave you made your website robust enough to work on your users\u2019 browsers and assistive technologies?\nThe fourth and final guideline has criteria that help you prevent your users from asking, \u201cWhy the **** doesn\u2019t this work on my device?\u201d\n4.1.1 You must make sure that your website works as well as possible with current and future browsers and assistive technology. Prioritise complying with web standards instead of relying on the capabilities of currently popular devices and browsers. Web developers didn\u2019t expect their users to be unwrapping the Wii U Browser five years ago\u2014who knows what browsers and assistive technologies our users will be unwrapping in five years\u2019 time? Avoid hacks, and use the W3C Markup Validation Service to make sure that your HTML has no errors.\n4.1.2 If you develop your own user interface components, you must make their name, role, state, properties, and values available to your user\u2019s browsers and assistive technologies. That should make them almost as accessible as standard HTML elements such as links, buttons, and checkboxes.\n\u201c\u2026and a partridge in a pear tree!\u201d\n\u2026as that very long Christmas song goes. We\u2019ve covered a lot in this article\u2014because your users have a lot of different levels of ability. Hopefully this has demystified the Web Content Accessibility Guidelines 2.0 for you. Hopefully you spotted a few situations that could arise for users on your website, and you now know how to tackle them. \nTo start applying what we\u2019ve covered, you might like to look at Sarah Horton and Whitney Quesenbery\u2019s personas for Accessible UX. Discuss the personas, get into their heads, and think about which aspects of your website might cause problems for them. See if you can apply what we\u2019ve covered today, to help users like them to do what they need to do on your website.\nHow to know when your website is perfectly accessible for everyone\nLOL! There will never be a time when your website becomes perfectly accessible for everyone. Don\u2019t aim for that. Instead, aim for regularly testing and making your website more accessible.\nWeb Content Accessibility Guidelines (WCAG) 2.1\nThe W3C hope to release the Web Content Accessibility Guidelines (WCAG) 2.1 as a \u201crecommendation\u201d (that\u2019s what the W3C call something that we should start using) by the middle of next year. Ten years may seem like a long time to move from version 2.0 to version 2.1, but consider the scale of the task: the editors have to update the guidelines to cover all the new ways that people interact with new technologies, while keeping the guidelines backwards-compatible. Keep an eye out for 2.1!\nYou\u2019ll go down in history\nOne last point: I\u2019ve met a surprising number of web designers and developers who do great work to make their websites more accessible without ever telling their users about it. Some of your potential customers have possibly tried and failed to use your website in the past. They probably won\u2019t try again unless you let them know that things have improved. A quick Twitter search for your website\u2019s name alongside phrases like \u201cassistive technology\u201d, \u201cdoesn\u2019t work\u201d, or \u201c#fail\u201d can let you find frustrated users\u2014so you can tell them about how you\u2019re making your website more accessible. Start making your websites work better for everyone\u2014and please, let everyone know.", "year": "2017", "author": "Alan Dalton", "author_slug": "alandalton", "published": "2017-12-03T00:00:00+00:00", "url": "https://24ways.org/2017/wcag-for-people-who-havent-read-them/", "topic": "code"} {"rowid": 194, "title": "Design Systems and Hybrids", "contents": "The other day on Twitter, I saw a thread started by Dorian Taylor about why design systems are so hot right now. In the thread, he made the case that they\u2019ve been around for ages and some folks were just slow to catch up. It was an interesting thread, and not the first time I\u2019ve seen folks discuss this. \u201cDesign systems are so hot right now\u201d was even used recently\u00a0in this very publication.\nAnd yes it\u2019s true that they\u2019ve been around for ages. Design artefact collectors\u2019 obsession with reprints of old graphic standards manuals of the past\u00a0are a reminder. Sometimes old things become new again, either through a rediscovery or awakening (wow, that sounds really deep). But I think that\u2019s definitely what happened here.\nSome very opinionated answers that come to mind for me are:\n\nThe need for them has increased with the needs of software development. With the increasing number of devices (phones, tablets, watches, etc.), scaling design has required the need to double down on systems thinking and processes.\nInvestments with huge cost-saving returns. The time investment it takes to onboard new people as you staff up large teams (and the time it takes to fix bugs and inconsistencies) could be better spent building up a system that lets you ship at a faster pace. It also gives you more time to focus on the bigger picture instead of what color a button border is.\nIf you do\u00a0have to onboard new designers, the design system is a great educational resource to get up to speed quickly on your organization\u2019s design principles, materials/tools, and methods.\n\n\n\u201cHere\u2019s the simple truth: you can\u2019t innovate on products without first innovating the way you build them.\u201d\n\u2014 Alex Schleifer, The Way We Build\n\nThese are just some of the reasons. But there is another answer, and a personal conclusion that I\u2019ve reached. It relates to the way I work and what I love working on, but I don\u2019t see it talked about much.\nHybrids Have a Home\nI\u2019m a hybrid designer. I code in HTML & CSS (with a preference for Sass). But I don\u2019t call myself a frontend developer. I used to back in the day (I was a UI frontend developer at Apple over a decade ago, but all I wrote was HTML & CSS). I identify with designer because that\u2019s my training and interest, but the ideas of what a frontend developer can do has changed quite a ton over the years. Setting things up in build tools and processes are not my skill. And I know a lot of designers who share this experience with me.\nThere are also hybrid developers who identify as developers, but have excellent design skills. Buddies like my pal Brandon Ferrua\u00a0who was on my team at Salesforce is a great example of this. And we worked fantastically together.\nSometimes, companies don\u2019t know how to deal with hybrids. I\u2019ve been told to choose a side, and have even been made to join a development team simply because I could code my designs (and then when I couldn\u2019t deliver the same type of code my teammates could, and I felt like I wasn\u2019t able to use my talents in the most effective way).\nThere are a lot more folks out there I know of who identify as a hybrid, and many have found ourselves working on design systems. Una Kravets recently had a thread discussing this as well. At Clarity, this came up a lot in hallway conversations, breaks, and the after parties. I think that this job is a haven for folks who often find themselves in the middle.\nFor companies that get it, these people find joy in getting to use a wider variety of skills and being bridges; advocates that can speak to designers and developers, helping bring \u2028unity to an organization. They can wireframe, throw together a prototype, create color systems, architect naming conventions for design tokens. Design systems are their perfect home. I think this has contributed to the uptick in discussions and interest on this subject (in addition to the team- and company-focused reasons).\nKeep Design Systems Teams Cross-Functional\nSpeaking of teams, something some larger companies fall prey to is creating walls and silos where they need not be. If you place all your visual designers in one place, all your coders in another, and so on, you\u2019re not doing yourselves any favors. Meanwhile, your hybrids are caught in the middle not knowing exactly where they belong. Design systems teams should have representatives (whether on a core team, or a virtual/federated team) that bring different skillsets. Design, code, writing, accessibility, product management, and so on. You\u2019ll have a stronger vision on where to take your design system and to make it succeed. Siloing defeats the whole purpose of what design systems are meant for.\nHappy holidays, and may the force be with you.\nFurther Reading\n\nWhy Design Systems Fail\nDesign Systems are for People\nDesign Systems Handbook", "year": "2017", "author": "Jina Anne", "author_slug": "jina", "published": "2017-12-22T00:00:00+00:00", "url": "https://24ways.org/2017/design-systems-and-hybrids/", "topic": "process"} {"rowid": 195, "title": "Levelling Up for Junior Developers", "contents": "If you are a junior developer starting out in the web industry, things can often seem a little daunting. There are so many things to learn, and as soon as you\u2019ve learnt one framework or tool, there seems to be something new out there.\nI am lucky enough to lead a team of developers building applications for the web. During a recent One to One meeting with one of our junior developers, he asked me about a learning path and the basic fundamentals that every developer should know. After a bit of digging around, I managed to come up with a (not so exhaustive) list of principles that was shared with him.\n\nIn this article, I will share the list with you, and hopefully help you level up from junior developer and become a better developer all round. This list doesn\u2019t focus on an particular programming language, but rather coding concepts as a whole. The idea behind this list is that whether you are a front-end developer, back-end developer, full stack developer or just a curious one, these principles apply to everyone that writes code. \nI have tried to be technology agnostic, so that you can use these tips to guide you, whatever your tech stack might be.\nWithout any further ado and in no particular order, let\u2019s get started.\nRefactoring code like a boss\nThe Boy Scouts have a rule that goes \u201calways leave the campground cleaner than you found it.\u201d This rule can be applied to code too and ensures that you leave code cleaner than you found it. As a junior developer, it\u2019s almost certain that you will either create or come across older code that could be improved. The resources below are a guide that will help point you in the right direction.\n\nMy favourite book on this subject has to be Clean Code by Robert C. Martin. It\u2019s a must read for anyone writing code as it helps you identify bad code and shows you techniques that you can use to improve existing code.\nIf you find that in your day to day work you deal with a lot of legacy code, Improving Existing Technology through Refactoring is another useful read.\nDesign Patterns are a general repeatable solution to a commonly occurring problem in software design. My friend and colleague Ranj Abass likes to refer to them as a \u201ccommon language\u201d that helps developers discuss the way that we write code as a pattern. My favourite book on this subject is Head First Design Patterns which goes right back to the basics. Another great read on this topic is Refactoring to Patterns.\nWorking Effectively With Legacy Code is another one that I found really valuable.\n\nImproving your debugging skills\nA solid understanding of how to debug code is a must for any developer. Whether you write code for the web or purely back-end code, the ability to debug will save you time and help you really understand what is going on under the hood.\n\nIf you write front-end code for the web, one of my favourite resources to help you understand how to debug code in Chrome can be found on the Chrome Dev Tools website. While some of the tips are specific to Chrome, these techniques apply to any modern browser of your choice.\nAt Settled, we use Node.js for much of our server side code. Without a doubt, our most trusted IDE has to be Visual Studio Code and the built-in debuggers are amazing. Regardless of whether you use Node.js or not, there are a number of plugins and debuggers that you can use in the IDE. I recommend reading the website of your favourite IDE for more information. \nAs a side note, it is worth mentioning that Chrome Developer Tools actually has functionality that allows you to debug Node.js code too. This makes it a seamless transition from front-end code to server-side code debugging.\nThe Debugging Mindset is an informative online article by Devon H. O\u2019Dell and discusses the the psychology of learning strategies that lead to effective problem-solving skills. \n\nA good understanding of relational databases and NoSQL databases\nAlmost all developers will need to persist data at some point in their career. Even if you don\u2019t write SQL queries in your day to day job, a solid understanding of how they work will help you become a better developer.\n\nIf you are a complete newbie when it comes to databases, I recommend checking out Code Academy. They offer a free online course that can help you get your head around how relational databases work. The course is quite basic, but is a useful hands-on approach to learning this topic.\nThis article provides a great explainer for the difference between the SQL and NoSQL databases, and this Stackoverflow answer goes a little deeper into the subject of the two database types.\nIf you\u2019d like to learn more about NoSQL queries, I would recommend starting with this article on MongoDB queries. Unfortunately, there isn\u2019t one overall course as most NoSQL databases have their own syntax. \n\nYou may also have noticed that I haven\u2019t included other types of databases such as Graph or In-memory; it\u2019s worth focussing on the basics before going any deeper.\nPerformance on the web\nIf you build for the web today, it is important to understand how the browser receives and renders the content that you send it. I am pretty passionate about Web Performance, and hope that everyone can learn how to make websites faster and more efficient. It can be fun at the same time!\n\nSteve Souders High Performance Websites is the godfather of web performance books. While it was created a few years ago and many of the techniques might have changed slightly, it is the original book on the subject and set up many of the ground rules that we know about web performance today.\nA free online resource on this topic is the Google Developers website. The site is an up to date guide on the best web performance techniques for your site. It is definitely worth a read.\nThe network plays a key role in delivering data to your users, and it plays a big role in performance on the web. A fantastic book on this topic is Ilya Grigorik\u2019s High Performance Browser Networking. It is also available to read online at hpbn.co.\n\nUnderstand the end to end architecture of your software project\nI find that one of the best ways to improve my knowledge is to learn about the architecture of the software at the company I work at. It gives you a good understanding as to why things are designed the way they are, why certain decisions were made, and gives you an understanding of how you might do things differently with hindsight.\nTry and find someone more senior, such as a Technical Lead or Software Architect, at your company and ask them to explain the overall architecture and draw a few high-level diagrams for you. Not to mention that they will be impressed with your willingness to learn.\n\nI recommend reading Clean Architecture: A Craftsman\u2019s Guide to Software Structure and Design for more detail on this subject.\nFar too often, software projects can be over-engineered and over-architected, it is worth reading Just Enough Software Architecture. The book helps developers understand how the smallest of changes can affect the outcome of your software architecture.\n\nHow are things deployed\nA big part of creating software is actually shipping it! How is the software at your company released into the wild? Does your company do Continuous Integration? Continuous Deployment?\n\nEven if you answered no to any of these questions, it is worth finding someone with the knowledge in your company to explain these things to you. If it is not already documented, perhaps you could start a wiki to document everything you\u2019re learning about the system - this is a great way to level up and be appreciated and invaluable.\nA streamlined deployment process is a beautiful thing, and understanding how they work can help you grow your knowledge as a developer. \nContinuous Integration is a practical read on the ins and outs of implementing this deployment technique.\nDocker is another great tool to use when it comes to software deployment. It can be tricky at first to wrap your head around, but it is definitely worth learning about this great technology. The documentation on the website will teach and guide you on how to get started using Docker.\n\nWriting Tests\nTesting is an essential tool in the developer bag of skills. They help you to make big refactoring changes to your code, and feel a lot more confident knowing that your changes haven\u2019t broken anything. There are so many benefits to testing, which make it so important for developers at every level to become acquainted with it/them.\n\nThe book that started it all for me was Roy Osherove\u2019s The Art of Unit Testing. The code in the book is written in C#, but the principles apply to every language. It\u2019s a great, easy-to-understand read.\nAnother great read is How Google Tests Software and covers exactly what it says on the tin. It covers many different testing techniques such as exploratory, black box, white box, and acceptance testing and really helps you understand how large organisations test their code.\n\nSoft skills\nWhilst reading through this article, you\u2019ve probably noticed that a large chunk of it focusses on code and technical ability. Without a doubt, I\u2019d say that it is even more important to be a good teammate. If you look up the definition of soft skills in the dictionary, it is defined as \u201cpersonal attributes that enable someone to interact effectively and harmoniously with other people\u201d and I think that it sums this up perfectly. Working on your \u201csoft skills\u201d is something that can truly help you level up in your career. You may be the world\u2019s greatest coder, but if you colleagues can\u2019t get along with you, your coding skills won\u2019t matter!\nWhile you may not learn how to become the perfect co-worker overnight, I really try and live by the motto \u201cdon\u2019t be an arsehole\u201d. Think about how you like to be treated and then try and treat your co-workers with the same courtesy and respect. The next time you need to make a decision at work, ask yourself \u201cis this something an arsehole would do\u201d? If you answered yes to that question, you probably shouldn\u2019t do it!\nSummary\nLevelling up as a junior developer doesn\u2019t have to be scary. Focus on the fundamentals and they should hold you in good stead, regardless of the new things that come along. Software engineering is built on these great principles that have stood the test of time.\nWhilst researching for this article, I came across a useful Github repo that is worth mentioning. Things Every Programmer Should Know is packed with useful information. I have to admit, I didn\u2019t know everything on there!\nI hope that you have found this list helpful. Some of the topics I have mentioned might not be relevant for you at this stage in your career, but should give a nudge in the right direction. After all, knowledge is power!\nIf you are a junior developer reading this article, what would you add to it?", "year": "2017", "author": "Dean Hume", "author_slug": "deanhume", "published": "2017-12-05T00:00:00+00:00", "url": "https://24ways.org/2017/levelling-up-for-junior-developers/", "topic": "code"} {"rowid": 196, "title": "Designing a Remote Project", "contents": "I came across an article recently, which I have to admit made my blood boil a little. Yes, I know it\u2019s the season of goodwill and all that, and I\u2019m going to risk sounding a little Scrooge-like, but I couldn\u2019t help it. It was written by someone who\u2019d tried out \u2018telecommuting\u2019 (big sigh) a.k.a. remote or distributed working. They\u2019d tested it in their company and decided it didn\u2019t work. \nWhy did it enrage me so much? Well, this person sounded like they\u2019d almost set it up to fail. To them, it was the latest buzzword, and they wanted to offer their employees a \u2018perk\u2019. But it was going to be risky, because, well, they just couldn\u2019t trust their employees not to be lazy and sit around in their pyjamas at home, watching TV, occasionally flicking their mousepad to \u2018appear online\u2019. Sounds about right, doesn\u2019t it?\nWell, no. This attitude towards remote working is baked in the past, where working from one office and people all sitting around together in a cosy circle singing kum-by-yah* was a necessity not an option. We all know the reasons remote working and flexibility can happen more easily now: fast internet, numerous communication channels, and so on. But why are companies like Yahoo! and IBM backtracking on this? Why is there still such a negative perception of this way of working when it has so much real potential for the future?\n*this might not have ever really happened in an office.\nSo what is remote working? It can come in various formats. It\u2019s actually not just the typical office worker, working from home on a specific day. The nature of digital projects has been changing over a number of years. In this era where organisations are squeezing budgets and trying to find the best value wherever they can, it seems that the days of whole projects being tackled by one team, in the same place, is fast becoming the past. What I\u2019ve noticed more recently is a much more fragmented way of putting together a project \u2013 a mixture of in-house and agency, or multiple agencies or organisations, or working with an offshore team. In the past we might have done the full integrated project from beginning to end, now, it\u2019s a piece of the pie. \nWhich means that everyone is having to work with people who aren\u2019t sat next to them even more than before. Whether that\u2019s a freelancer you\u2019re working with who\u2019s not in the office, an offshore agency doing development or a partner company in another city tackling UX\u2026 the future is looking more and more like a distributed workplace.\nSo why the negativity, man?\nAs I\u2019ve seen from this article, and from examples of large corporations changing their entire philosophy away from remote working, there\u2019s a lot of negativity towards this way of working. Of course if you decide to let everyone work from home when they want, set them off and then expect them all to check in at the right time or be available 24/7 it\u2019s going to be a bit of a mess. Equally if you just jump into work with a team on the other side of the world without any setup, should you expect anything less than a problematic project?\nOkay, okay so what about these people who are going to sit on Facebook all day if we let them work from home? It\u2019s the age old response to the idea of working from home. I can\u2019t see the person, so how do I know what they are doing?\nThis comes up regularly as one of the biggest fears of letting people work remotely. There\u2019s also the perceived lack of productivity and distractions at home. The limited collaboration and communication with distributed workers. The lack of availability. The lower response times. \nHang on a second, can\u2019t these all still be problems even if you\u2019ve got your whole team sat in the same place? \u201cThey won\u2019t focus on work.\u201d How many people will go on Facebook or Twitter whilst sat in an office? \u201cThey won\u2019t collaborate as much.\u201d How many people sit in the office with headphones on to block out distractions? I think we have to move away from the idea that being sat next to people automatically makes them work harder. If the work is satisfying, challenging, and relevant to a person \u2013 surely we should trust them to do it, wherever they are sat?\nThere\u2019s actually a lot of benefits to remote working, and having distributed teams. Offering this as a way of working can attract and retain employees, due to the improved flexibility. There can actually be fewer distractions and disruptions at home, which leads to increased productivity. To paraphrase Jason Fried in his talk \u2018Why work doesn\u2019t happen at work\u2019, at home there are voluntary distractions where you have to choose to distract yourself with something. At the office these distractions become involuntary. Impromptu meetings and people coming to talk to you all the time are actually a lot more disruptive. Often, people find it easier to focus away from the office environment. \nThere\u2019s also the big benefit for a lot of people of the time saved commuting. The employee can actually do a lot that\u2019s beneficial to them in this time, rather than standing squeezed into people\u2019s armpits on public transport. Hence increased job satisfaction. With a distributed team, say if you\u2019re working with an off-shore team, there could be a wider range of talent to pick from and it also encourages diversity. There can be a wider range of cultural differences and opinions brought to a project, which encourages more diverse ways of thinking.\nTackling the issues - or, how to set up a project with a remote team\nBut that isn\u2019t to say running projects with a distributed team or being a remote worker is easy, and can just happen, like that. It needs work \u2013 and good groundwork \u2013 to ensure you don\u2019t set it up to fail. So how do you help create a smoother remote project?\nStart with trust\nFirst of all, the basis of the team needs to be trust. Yes I\u2019m going to sound a little like a cheesy, self-help guru here (perhaps in an attempt to seem less Scrooge-like and inject some Christmas cheer) but you do need to trust the people working remotely as well as them trusting you. This extends to a distributed team. You can\u2019t just tell the offshore team what to do, and micromanage them, scared they won\u2019t do what you want, how you want it because you can\u2019t see them. You need to give them ownership and let them manage the tasks. Remember, people are less likely to criticise their own work. Make them own the work and they are more likely to be engaged and productive.\nSet a structure\nDistributed teams and remote workers can fail when there is no structure \u2013 just as much as teams sitting together fail without it too. It\u2019s not so much setting rules, as having a framework to work within. Eliminate blockers before they happen. Think about what could cause issues for the team, and think of ways to solve this. For example, what do you do if you won\u2019t be able to get hold of someone for a few hours because of a time difference? Put together a contingency, e.g. is there someone else on your time zone you could go to with queries after assessing the priority? Would it be put aside until that person is back in? Define team roles and responsibilities clearly. Sit down at the beginning of the project and clearly set out expectations. Also ask the team, what are their expectations of you?\nThere won\u2019t be a one size fits all framework either. Think about your team, the people in it, the type of project you\u2019re working with, the type of client and stakeholder. This should give you an idea of what sort of communications you\u2019ll need on the project. Daily calls, video calls, Slack channels, the choice is yours.\nDecide on the tools\nTo be honest, I could spend hours talking about the different tools you can use for communication. But you know them, right? And in the end it\u2019s not the tool that\u2019s important here - it\u2019s the communication that\u2019s being done on the tool. Tools need to match the type of communications needed for your team. One caveat here though, never rely solely on email! Emails are silos, and can become beasts to manage communications on.\nTransparency in communication\nGood communication is key. Make sure there are clear objectives for communication. Set up one time during the week where those people meet together, discuss all the work during that week that they\u2019ve done. If decisions are made between team members who are together, make sure everyone knows what these are. But try to make collective decisions where you can, when it doesn\u2019t impact on people\u2019s time.\nHave a face-to-face kick off\nYes, I know this might seem to counter my argument, but face-to-face comms are still really important. If it\u2019s feasible, have an in-person meeting to kick off your project, and to kick off your team working together. An initial meeting, to break the ice, discuss ways of working, set the goals, can go a long way to making working with distributed teams successful. If this is really not viable, then hold a video call with the team. Try to make this a little more informal. I know, I know, not the dreaded cringey icebreakers\u2026 but something to make everyone relax and get to know each other is really important. Bring everybody together physically on a regular basis if you can, for example with quarterly meetings. You\u2019ve got to really make sure people still feel part of a team, and it often takes a little more work with a remote team. Connect with new team members, one-on-one first, then you can have more of a \u2018remote\u2019 relationship. \nGet visual\nVisual communication is often a lot better tool to use than just a written sentence, and can help bring ideas to life. Encourage people to sketch things, take a photo and add this to your written communications. Or use a mockup tool to sketch ideas.\nBut what about Agile projects?\nThe whole premise of Agile projects is to have face-to-face contact I hear you cry. The Agile Manifesto itself states \u201cThe most efficient and effective method of conveying information to and within a development team is face-to-face conversation\u201d. However, this doesn\u2019t mean the death of remote working. In fact loads of successful companies still run Agile projects, whilst having a distributed team. With all the collaborative tools you can use for centralising code, tracking tasks, visualising products, it\u2019s not difficult to still communicate in a way that works. Just think about how to replicate the principles of Agile remotely - working together daily, a supportive environment, trust, and simplicity. How can you translate these to your remote or distributed team? \nOne last thought to leave you with before you run off to eat your mince pies (in your pyjamas, whilst working). A common mistake in working with a remote project team or working remotely yourself, is replacing distance with time. If you\u2019re away from the office you think you need to always be \u2018on\u2019 \u2013 messaging, being online, replying to requests. If you have a distributed team, you might think a lot of meetings, calls, and messages will be good to foster communication. But don\u2019t overload these meetings, calls, and communication. This can be disruptive in itself. Give people the gift of some uninterrupted time to actually do some work, and not feel like they have to check in every second.", "year": "2017", "author": "Suzanna Haworth", "author_slug": "suzannahaworth", "published": "2017-12-06T00:00:00+00:00", "url": "https://24ways.org/2017/designing-a-remote-project/", "topic": "business"} {"rowid": 197, "title": "Designing for Mobile Performance", "contents": "Last year, some colleagues at Google ran a research study titled \u201cThe Need for Mobile Speed\u201d to find out what the impact of performance and perception of speed had on the way people use the web on their mobile devices. \nThat\u2019s not a trivial distinction; when considering performance, how fast something feels is often more important than how fast it actually is. When dealing with sometimes underpowered mobile devices and slow mobile networks, designing experiences that feel fast is exceptionally important.\nOne of the most startling numbers we found in the study was that 53% of mobile site visits are abandoned if pages take longer than 3 seconds to load.\nWe wanted to find out more, so following on from this study, we conducted research to define what the crucial elements of speed are. We took into consideration the user experience (UX), overall perception of speed, and how differing contexts the user finds themselves in can alter how fast a user thinks something loaded.\nTo understand speed and load times first we must understand that user mobile web behaviour is broken down into three buckets;\n\nIntention\nLocation\nState of mind\n\nLet\u2019s look at each of those in turn.\nIntention\nUsers browse sites on a mobile device for many different reasons. To be able to effectively design a performant user experience for them, it\u2019s important to understand what those reasons might be. When asked to describe their reason for visiting a site, approximately 30% of people asked by the study claimed that they were simply browsing without a particular purpose in mind. Looking deeper, we found that this number increased slightly (34%) for retail sites. 30% said they were just there to find out some information for a future task or action, such as booking a flight.\nInterestingly, the research shows that users are actually window shopping using their mobile browser. Only 29% actually said they had a specific goal or intent in mind, and this number increases significantly for financial services like banking sites (57%). This goes against a traditionally held view of users wanting to perform simple actions efficiently on their mobile device. Sure, some users are absolutely doing that, but many are just browsing around without a goal in mind, just like they would on a desktop browser.\nThis gives great insight into the user\u2019s intentions. It tells us that users are actively using sites on their mobile, but a large majority do not intend to do anything instantly. There\u2019s no goal they\u2019re under pressure to achieve. If a site\u2019s performance is lousy or janky, this will only reaffirm to the user to that they can hold off on completing a task, so they might just give up. \nHowever, if a site is quick to load, sophisticated in expressing its value proposition quickly, and enables the user to perform their actions seamlessly, then turning that \u201cbrowsing user\u201d into a \u201cbuying user\u201d becomes all that much easier. When the user has no goal, there\u2019s more opportunity to convert, and you stand a greater chance of doing that if the performance is good enough so they stick around.\nLocation\nObviously, mobile devices by their nature can be used in many different locations. This is an interesting consideration, because it\u2019s not something we traditionally need to take into account designing experiences for static platforms like desktop computers.\nThe in the study, we found that 82% of users browse the web on their mobile phone while in their home. In contrast, only 7% do the same while at work. This might come across as a bit of a shock, but when you look at mobile usage \u2013 in particular app usage \u2013 most of the apps being used are either a social network or some sort of entertainment or media app. Due to the unreliability of network connections, users will often alternate between these two types of apps.\nThe consequence being that if a site doesn\u2019t work offline, or otherwise compensate for bad network connectivity in some way by providing opportunities to allow users to browse their site, then it becomes a self-fulfilling prophecy as to why users mostly view the mobile web from the comfort of their homes where there is a strong WiFi connection. They\u2019re using mobile devices, but they\u2019re not actually mobile themselves.\nAnother thing to bear in mind is how users alternate between devices, a study by comScore found that 80% of transactions take place on desktop while 69% of the browsing takes place on mobile. Any given user might access from more than one location - they might visit one day from a bus queue on their phone, and then next day from a laptop at home.\nState of mind\nOne more thing we need to take into consideration is the user\u2019s state of mind. Whilst browsing at home, users tend to be more relaxed, and in the research 76% stated they were generally calmer at home. The user\u2019s state of mind can have quite a big impact on how they perceive things. The calmer they are, the quicker a site might appear to load. If the user is anxious and impatiently drumming their fingers on the table, things seem to take longer, and even a small wait can feel like an eternity.\nThis is quite key. Over 40% of sites take longer than 4 seconds to load for users who are are out and about and using a mobile data connection. Coupled with our perception, and amplified by a potentially less-than-calm state of mind, this can seem like an age.\nWhat does this all mean?\nI think we can all agree that users prefer strong, steady connections and comfort when completing transactions. It seems like common sense when we say it out loud. Recreating these feelings and sensations of comfort and predictability under all circumstances therefore becomes paramount. Equally, when asked in the study, users all claimed that speed was the most important factor impacting their mobile web usage. Over 40%, in fact, said it was the most important UX feature of a site, and nobody asked considered it to be of no importance at all.\n\nThe meaning of speed\nWhen it comes to performance, speed is measured in two ways \u2013 real speed; as measured on a clock, and perceived speed; how responsive an interaction feels. We can, of course, improve how quickly a site loads by simply making files smaller. Even then, the study showed that 32% of users felt a site can feel slow even when it loads in less than 4 seconds. This gets even worse when you look at it by age group, with 50% if young people (18-24 year olds) thinking a site was slower than it actually was. When you add to the mix that users think a site loaded faster when they are sitting compared to when they are standing up, then you are in a world of trouble if your site doesn\u2019t have any clear indicators to let the user know the loading state of you website or app.\nSo what can we do about this to improve our designs?\nHow to fix / hack user perception\nThere are some golden rules of speed, the first thing is hacking response time. If a page takes more than 3 seconds to load, you will certainly start to lose your users. However, if that slowness is part of a UX flow such as processing information, the user understands it might take a little time. Under those circumstances, a load time of under 5 seconds is acceptable, but even then, you should take caution. Anything above 8 seconds and you are in very real danger of losing your audience completely. \n\n\n\nLoad time\nUser impression\n\n\n\n\n200 ms\nFeels instant\n\n\n1 s\nFeels it is performing smoothly\n\n\n5 s\nPart of user flow\n\n\n8 s\nLose attention\n\n\n\nRemove the tap delay\nMobile browsers often use a 300-350ms delay between the triggering of the touchend and click events. This delay was added so the browser could determine if there was going to be a double-tap triggered or not, since double-tap is a common gesture used to zoom into text. This delay can have the side effect of making interactions feel laggy, and therefore giving the user the impression that the site is slow, even if it\u2019s their own browser causing the problem.\nFortunately there\u2019s a way to remove the delay. Add following in the of your page, and the delay no longer takes effect:\n\nYou can also use touch-action: manipulation in newer browsers to eliminate click delay. For old browsers, FastClick by FT Labs uses touch events to trigger clicks faster and remove the double-tap gesture.\nMake use of Skeleton Screens\nA skeleton layout is a wireframe version of your app that displays while content is being loaded. This demonstrates to the user that content is about to be loaded, giving the impression that something is happening more quickly than it really is. Consider also using a preloader UI as well, with a text label informing the user that the app is loading. One example would be to pulsate the wireframe content giving the app the feeling that it is alive and loading. This reassures the user that something is happening and helps prevent resubmissions or refreshes of your app. Razvan Caliman created a Codepen example of how to create this effect in purely CSS. \nOne thing to consider though, if data doesn\u2019t load then you might need to create a fallback 404 or error page to let the user know what happened. \n\nExample by Owen-Campbell Moore\nResponsive Touch Feedback\nCarefully designing the process by which items load is one aspect of increasing the perceived speed of your page, but reassuring the user that an action they have taken is in process is another. At Google we use something called a Ripple, which is is animating dot that expands or ripples in order to confirm to the user that their input has been triggered. This happens immediately, expanding outward from the point of touch. This reaffirms to the user that their input has been received and is being acted on, even before the site has had a chance to process or respond to the action. From the user\u2019s point of view, they\u2019ve tapped and the page has responded immediately, so it feels really quick and satisfying.\nYou can mimic this same behavior using our Material Design Components Web GitHub repo.\n\nProgress bars\nThese UI elements have existed for a very long time, but research conducted by Chris Harrison and published in New Scientist found that the style of a progress bar can alter the perception of speed drastically. As a matter of fact, progress bars with ripples that animate towards the left appear like they are loading faster by at least 11% percent. So when including them in your site, take into consideration that ripples and progress bars that pulsate faster as they get to the end will make your sites seem quicker.\n\n \n \n Faster Progress Bars: Manipulating Perceived Duration with Visual Augmentations\nNavigation\nThe speed with which a user can locate navigational items or call to actions adds to their perceived performance of a site. If the user\u2019s next action is quick to spot on the screen, they don\u2019t spend time hunting around the interface with their eyes and fingers. So no matter how quickly your code runs, hiding items behind a nav bar will make a site feel slower than it actually is. \nFacebook found that switching to using bottom navigation saw an increase in engagement, satisfaction, revenue, speed, and importantly, perception of speed. If the user sees the navigation items they\u2019re looking for quickly, the interaction feels fast. What\u2019s more, end-to-end task completion is quicker too, as the interface not only feels quicker, but actually measures quicker as well. Similar reactions were found with Spotify and Redbooth.\nLuke Wroblewski gave a talk last year in Ireland titled \u201cObvious Always Wins\u201d which he demonstrated through the work he did with Google+. Luke\u2019s message is that by making the core features of your app obvious to your user, you will see engagement go up. This again seems obvious, right? However, it is important to note that adding bottom navigation doesn\u2019t just mean a black bar at the bottom of your screen like some kind of performance magic bullet. The goal is to make the items clear to the user so they know what they need to be doing, and how you achieve that could be different from one interface to the next. Google keeps experimenting with different navigation styles, but finally settled with the below when they conducted user research and testing.\n\nConclusion\nBy utilizing a collection of UI patterns and speed optimisation techniques, you can improve not only the actual speed of a site, but the perception of how quickly a user thinks your site is loading. It is critical to remember that users will not always be using your site in a calm and relaxed manner and that even their age can impact how they will use or not use your site. By improving your site\u2019s stability, you increase the likelihood of positive user engagement and task completion.\nYou can learn more about techniques to hack user perception and improve user speed by taking a look at an E-Book we published with Awwwards.com called Speed Matters: Design for Mobile Performance.", "year": "2017", "author": "Mustafa Kurtuldu", "author_slug": "mustafakurtuldu", "published": "2017-12-18T00:00:00+00:00", "url": "https://24ways.org/2017/designing-for-mobile-performance/", "topic": "ux"} {"rowid": 198, "title": "Is Your Website Accidentally Sexist?", "contents": "Women make up 51% of the world\u2019s population. More importantly, women make 85% of all purchasing decisions about consumer goods, 75% of the decisions about buying new homes, and 81% of decisions about groceries. The chances are, you want your website to be as attractive to women as it is to men. But we are all steeped in a male-dominated culture that subtly influences the design and content decisions we make, and some of those decisions can result in a website that isn\u2019t as welcoming to women as it could be. \nTypography tells a story\nStudies show that we make consistent judgements about whether a typeface is masculine or feminine: Masculine typography has a square or geometric form with hard corners and edges, and is emphatically either blunt or spiky. Serif fonts are also considered masculine, as is bold type and capitals.\nFeminine typography favours slim lines, curling or flowing shapes with a lot of ornamentation and embellishment, and slanted letters. Sans-serif, cursive and script fonts are seen as feminine, as are lower case letters. \nThe effect can be so subtle that even choosing between bold and regular styles within a single font family can be enough to indicate masculinity or femininity.\nIf you want to appeal to both men and women, search for fonts that are gender neutral, or at least not too masculine. When you\u2019re choosing groups of fonts that need to work harmoniously together, consider which fonts you are prioritising in your design. Is the biggest word on the page in a masculine or feminine font? What about the smallest words? Is there an imbalance between the prominence of masculine and feminine fonts, and what does this imply? \nTypography is a language in and of itself, so be careful what you say with it. \nColour me unsurprised\nColour also has an obvious gender bias. We associate pinks and purples, especially in combination, with girls and women, and a soft pink has become especially strongly related to breast cancer awareness campaigns. On the other hand, pale blue is strongly associated with boys and men, despite the fact that pastels are usually thought of as more feminine. \nThese associations are getting stronger and stronger as more and more marketers use them to define products as \u201cfor girls\u201d and \u201cfor boys\u201d, setting expectations from an incredibly young age \u2014 children as young as four understand gender stereotypes. It should be obvious that using these highly gender-associated colours sends an incredibly strong message to your visitors about who you think your target audience is. If you want to appeal to both men and women, then avoid pinks and pale blues.\nBut men and women also have different colour preferences. Men tend to prefer intense primary colours and deeper colours (shades), and tolerate greys better, whilst women prefer pastels (tints). When choosing colours, consider not just the hue itself, but also tint, tone and shade.\nSlightly counterintuitively, everyone likes blue, but no one seems to particularly like brown or orange. \nA picture is worth a thousand words, or none\nStock photos are the quickest and easiest way to add a little humanity to your website, directly illustrating the kind of people you believe are in your audience. But the wrong photo can put a woman off before she\u2019s even read your text. \nA website about a retirement home will, for example, obviously include photos of older people, and a baby clothes retailer will obviously show photos of babies. But, in the latter case, should they also show only photographs of mothers with their children, or should they include fathers too? It\u2019s true that women take on the majority of childcare responsibilities, but that\u2019s a cultural holdover from a previous era, rather than some rule of law. We are seeing increasing number of stay at home dads as well as single dads, so showing only photographs of women both enforces the stereotype that only women can care, as well as marginalising male carers. \nEqually, featuring prominent photographs of women on sites about male-dominated topics such as science, technology or engineering help women feel welcomed and appreciated in those fields. Photos really do speak volumes, so make sure that you also represent other marginalised groups, especially ethnic groups. If people do not see themselves represented on your site, they are not going to engage with it as much as they might. \nAnother form of picture that we often ignore is the icon. When you do use icons, make sure that they are gender neutral. For example, avoid using a icon of a man to denote engineers, or of a woman to denote nurses. Avoid overly masculine or feminine metaphors, such as a hammer to denote DIY or a flower to denote gardens. Not only are these gendered, they\u2019re also trite and unappealing, so come up with more exciting and novel metaphors. \nUse gender-neutral language\nLast, but not least, be very careful in your use of gender in language. \nPronouns are an obvious pitfall. A lot of web content is written in the second person, using the cleary gender neutral \u2018you\u2019, but if you have to write in the third person, which uses \u2018she\u2019, \u2018he\u2019, \u2018it\u2019, and \u2018they\u2019, then be very careful which pronouns you use. The singular \u2018they\u2019 is becoming more widely acceptable, and is a useful gender-neutral option. If you must use generic \u2018he\u2019 and \u2018she\u2019, (as opposed to talking about a specific person), then vary the order that they come in, so don\u2019t always put the male pronoun first. \nWhen you are talking about people, make sure that you use the same level of formality for both men and women. The tendency is to refer to men by their surname and women by their first name so, for example, when people are talking about Ada Lovelace and Charles Babbage, they often talk about \u201cAda and Babbage\u201d, rather than \u201cLovelace and Babbage\u201d or \u201cAda and Charles\u201d. As a rule, it\u2019s best to use people\u2019s surnames in formal and semi-formal writing, and their first names only in very informal writing. \nIt\u2019s also very important to make sure that you respect people\u2019s honorifics, especially academic titles such as Dr or Professor, and that you use titles consistently. Studies show that women and people of colour are the most likely to have their honorifics dropped, which is not only disrespectful, it gives readers the idea that women and people of colour are less qualified than white men.\nIf you mention job titles, avoid old-fashioned gendered titles such as \u2018chairman\u2019, and instead look for a neutral version, like \u2018chair\u2019 or \u2018chairperson\u2019. Where neutral terms have strong gender associations, such as nurse or engineer, take special care that the surrounding text, especially pronouns, is diverse and/or neutral. Do not assume engineers are male and nurses female. \nMore subtle intimations of gender can be found in the descriptors people use. Military metaphors and phrases, out-sized claims, competitive words, and superlatives are masculine, such as \u2018ground-breaking\u2019, \u2018best\u2019, \u2018genius\u2019, \u2018world-beating\u2019, or \u2018killer\u2019. Excessive unnecessary factual detail is also very masculine. \nWomen tend to relate to more cooperative, non-competitive, future-focused, and warmer language, paired with more general information. Women\u2019s language includes word like \u2019global\u2019, \u2018responsive\u2019, \u2018support\u2019, \u2018include\u2019, \u2018engage\u2019 and \u2018imagine\u2019. Focus more on the kind of relationship you can build with your customers, how you can help make their lives easier, and less on your company or product\u2019s status. \nSmash the patriarchy, one assumption at a time\nWe\u2019re all brought up in a cultural stew that prioritises men\u2019s needs, feelings and assumptions over women\u2019s. This is the patriarchy, and it\u2019s been around for thousands of years. But given women\u2019s purchasing power, adhering to the patriarchy\u2019s norms is unlikely to be good for your business. If you want to tap into the female market, pay attention to the details of your design and content, and make sure that you\u2019re not inadvertently putting women off. A gender neutral website that designs away gender stereotypes will attract both men and women, expanding your market and helping your business flourish.", "year": "2017", "author": "Suw Charman-Anderson", "author_slug": "suwcharmananderson", "published": "2017-12-20T00:00:00+00:00", "url": "https://24ways.org/2017/is-your-website-accidentally-sexist/", "topic": "content"} {"rowid": 199, "title": "Knowing the Future - Tips for a Happy Launch Day", "contents": "You\u2019ve chosen your frameworks and libraries. You\u2019ve learned how to write code which satisfies the buzzword and performance gods. Now you need to serve it to a global audience, and make things easy to preview, to test, to sign-off, and to evolve.\nBut infrastructure design is difficult and boring for most of us. We just want to get our work out into the wild.\nIf only we had tools which would let us go, \u201cOh yeah! It all deploys perfectly every time\u201d and shout, \u201cYou need another release? BAM! What\u2019s next?\u201d\nA truth that can be hard to admit is that very often, the production environment and its associated deployment processes are poorly defined until late into a project. This can be a problem.\nIt makes my palms sweaty just thinking about it.\nIf like me, you have spent time building things for clients, you\u2019ll probably have found yourself working with a variety of technical partners and customers who bring different constraints and opportunities to your projects. Knowing and proving the environments and the deployment processes is often very difficult, but can be a factor which profoundly impacts our ability to deliver what we promised. To say nothing of our ability to sleep at night or leave our fingernails un-chewed.\nLet\u2019s look at this a little, and see if we can\u2019t set you up for a good night\u2019s sleep, with dry palms and tidy fingernails.\nA familiar problem\nYou\u2019ve been here too, right? The project development was tough, but you\u2019re pleased with what you are running in your local development environments. Now you need to get the client to see and approve your build, and hopefully indicate with a cheery thumbs up that it can \u201cgo live\u201d.\n\nChances are that we have a staging environment where the client can see the build. But be honest, is this exactly the same as the production environment? It should be, but often it\u2019s not. Often the staging environment is nothing more than a visible server with none of the optimisations, security, load balancing, caching, and other vital bits of machinery that we\u2019ll need (and need to test) in \u201cprod\u201d.\nOften the production environment is still being \u201cset up\u201d and you\u2019ll have to wait and see.\nIn development, \u201cwait and see\u201d is the enemy.\nInstead of waiting to see, we need to make the provisioning of, and deployment to our different environments one of the very first jobs of our project. I\u2019ve often needed to be the unpopular voice in the room who makes a big fuss when this is delayed. I\u2019ve described it as being a \u201ccritical blocker\u201d during project meetings and suggested that everything should halt until it is fixed. \nIt is that important.\nClients don\u2019t often like hearing a wary, disruptive voice saying \u201cwhoa there Nelly!\u201d, because the development should be able to continue while the production environment gets sorted out, right? \nSure. But if it is not seen as a blocker, it is seen as something that can just happen later. And if it happens later, all the ugly surprises and unknowns surface later too. And later is when we\u2019ll need to be thinking about other things. Not the plumbing. Trust me, it pays to face up to the issue right away rather than press on optimistically. The client will thank you later.\nAttitudes and expectations\nWe should, I think, exhibit these four attitudes towards production deployment:\n\nMake it scripted\nMake it automated\nMake it real\nMake it first\n\nMake it scripted\nLet\u2019s face it, we are going to need to deploy more than once over the course of the project. We are not going to get things perfect on our first shot. Nor should we expect to. And if we are going to repeat something, we want to be able to do it identically and predictably every time without needing to rely on our memories.\nDevelopers are great at scripting things which they would otherwise need to repeat. It makes us faster and it also helps us keep track of the steps we need to take.\nI\u2019m not crazy enough to try suggest the best technology to script your builds or deployments (holy wars lie down that path). A lot will depend on your languages and your tastes. Some will like Fabric, others will prefer Gulp, you might prefer Make or NPM. It doesn\u2019t really matter as long as you can script the process of building, packaging and deploying your project.\nWait. Won\u2019t we need to know everything about the build from the start in order to do this? Aren\u2019t our dependencies likely to change over time?\nYes. That would be ideal. But it\u2019s ok. Like our code, our deployment script will evolve over the life of a project. So evolve it. Start by scripting what is needed to support the first iteration of the project, and then maintain that script. It will become a valuable \u201csource of truth\u201d, providing a form of documentation of what your project needs for a successful deployment. Another bonus.\nMake it automated\nIf we have a scripted deployment which we can run by executing a single command, then we are in great shape to automate that process by triggering the build and deployment via suitable events.\nAgain, I prefer not to offer one single suggestion of when this should occur. That will depend on your approach to the project, how your development team is organised, and how your QA team operate. You can tune this to suit.\nFor one project I worked on, we chose to trigger the build and deployment to our production environment every time we used Git to tag the master branch of our version control repository. There were a few moving parts, and we needed to do some upfront work to get everything working, but that upfront effort was repaid many fold as we deployed time and time again, and exposed some issues with our environment long before we got to \u201claunch day\u201d.\nWith a scripted and automated process, we can make deployments \u201ccheap\u201d. This is our goal. When there are minimal cognitive or time overheads associated with deploying, we\u2019re likely to do it all the more often and become more confident that it will behave as expected.\nMake it real\nAlright, we have written scripts to build and deploy our projects. Anyone tagging our repo will trigger things to happen as if by magic, but where are we pushing things to? We need to target a real environment if this is to have any value.\nA useful pattern is to have all activity on our develop branch trigger deployments to our staging server. Meanwhile tagging master will deploy a version to the production environment. How we organise this will depend on our git branching approach. (I\u2019ve seen as many ways of approaching Git Flow as I have seen ways of approaching \u201cAgile\u201d).\nIt\u2019s vital though, that we ensure that we are deploying to, and testing against, our real infrastructure. We want to see real results. That\u2019s the best way to learn real lessons.\nMake it first\nBuilding our site to run in an environment not yet fully defined or available to test is like climbing without ropes \u2013 it\u2019s possible, but we put ourselves at risk. And the higher we climb the greater the risk. So it is important to do this as early as we possibly can.\nDon\u2019t have a certificate for our HTTPS yet? Fine, but let\u2019s still deploy to this evolving production environment and introduce HTTPS as soon as we can.\nBefore we know it we\u2019ll be proving that this is set up correctly and we\u2019ll not be surprised by mixed security alerts or other nasties further down the line.\n\nMailchimp perfectly capture the anxiety of sending emails to gazillions of people for a campaign. But we\u2019re lucky. Launching a site doesn\u2019t need to be like performing a mailshot. We can do things to banish that sweaty hand.\nDoing preparation work upfront means that by the time we need to launch the site into the wild, we have exercised the deployment mechanics, and tested the production environment so rigorously that this task will be boring.\n(It won\u2019t be boring. Launching should always be exciting because the world will finally get to see our beautiful, painstaking work. But nor should it be terrifying. Especially as a result of not knowing for certain if our processes and environments are going to work or burst into flames on the big day.)\nWhat tools exist?\nWell this all sounds lovely. But how should we tackle this? Where are the tools for us to use? As it happens, there are many service and tools that we can use to work this way.\nHosting\nAll of the big players like Amazon, Azure and Google offer tools which can help us here. Google for example, can host multiple deployed versions of your project in parallel and you can manage them via their App Engine console. Each build receives its own URL which you can use to access any deployed version of your site.\nHaving immutable deployments which stick around in perpetuity (or until you bin them) is a key feature which unlocks the ability to confidently direct your traffic to any version of your site. With that comes the capacity to test any version or feature in its real environment, and then promote a version, or rollback to a previous version whenever you want.\nA liberating power to have.\nContinuous integration\nIn order to create all of those different versions, we\u2019ll need somewhere to run our build and deployment scripts. Jenkins has been a popular Continuous Integration (CI) option for some time, and can be configured to perform all sorts of tasks, giving you extensive control over your deployment pipeline.\nYou need to host Jenkins yourself, but it provides some simple ways to do that.\nThe landscape for CI is getting richer and richer. With many hosted services like Circle CI providing this kind of automation up in the cloud.\nOne stop shop\nNetlify combines both hosting and continuous integration services. It monitors your git repositories and automatically runs your build in a container on its servers when it finds changes. Each branch and pull request in your git repository will result in an immutable version of your site with its own URL.\nNetlify is unlike Google Cloud, AWS or Azure in that it cannot host a dynamic server-side application for you. Instead it specialises in hosting static, or so called JAMstack sites.\nPersonally, I find that its simplicity makes it an approachable option, and a good place to learn and adopt some of these valuable habits.\nFull disclosure: I\u2019m a Netlify employee. But before I was, I was an avid customer, and it was through using Netlify that I first encountered some of these principles in practice.\nConclusion. It\u2019s all about the approach\nNo matter what tools or services you use (and there are many which can support these practices), the most important thing is to adopt an approach which lets you prove your environments as quickly as possible.\nFront-loading this effort will cast light onto the issues that you\u2019ll need to address early and often, leaving no infrastructure surprises to spoil things for you on launch day.\nAutomating the process will mean that when you do find things that you need to fix or to improve later (and you will), issuing another release will be trivial. It is a lovely feeling when you have confidence that releasing v1.0.0 will be no more stressful v0.0.1. In fact it should actually be less stressful, as you\u2019ll have been down this road many times by then. Fixing the potholes and smoothing the way as you went.\nFrom here, it should be a smooth ride.", "year": "2017", "author": "Phil Hawksworth", "author_slug": "philhawksworth", "published": "2017-12-21T00:00:00+00:00", "url": "https://24ways.org/2017/knowing-the-future/", "topic": "process"} {"rowid": 200, "title": "Care and Feeding of Burnout", "contents": "You\u2019ve been doing too much for too long. And it\u2019s broken you. You\u2019re burned out. You\u2019re done.\nIllustration by Kate Holden\nOccupational burnout is a long-documented effect of stretching yourself further than the limits of your mental and physical health can carry you. And when it finally catches up with you, it can feel like the end of the world. But things can get better. With focused self care, reworking your priorities and lots of time, you can slog through burnout.\nWhat is burnout? The Tl;dr linkdump tour\nIn this article, we\u2019ll be looking at what you can do when you\u2019re burned out. We\u2019ll be skipping past a lot of information on what burnout is, what causes it and how it impacts the tech industry. We\u2019re able to skip past this because many technologists have already created valuable content targeted to our industry. The videos and writing below may be helpful for readers who are less familiar with burnout.\nA Wikipedia article may be a great starting point for learning about occupational burnout.\n\n \n\nUnderstanding burnout: Brandon West\nThis conference talk by Brandon West covers a lot of burnout 101, from the perspective of a developer relations/community professional.\nApril Wensel writes about the need for the tech industry to move from the Valley\u2019s burnout culture to a more sustainable model.\nCatching Burnout [as] early [as possible]\nOne of the most challenging things about burnout is that it develops slowly and gradually. Many impacted don\u2019t notice the water warming around them until it\u2019s been brought to a boil, causing a crisis that can\u2019t be overlooked. Catching burnout and taking steps to deal with it as early as possible can help limit the length and severity of your burnout.\nGetting in the habit of checking in with yourself regularly about your stress and energy levels can be an effective habit for assessing burnout and for general wellness. The Mayo Clinic recommends asking yourself the following questions to determine if you might be suffering from burnout.\n\nHave you become cynical or critical at work?\nDo you drag yourself to work and have trouble getting started once you arrive?\nHave you become irritable or impatient with co-workers, customers or clients?\nDo you lack the energy to be consistently productive?\nDo you lack satisfaction from your achievements?\nDo you feel disillusioned about your job?\nAre you using food, drugs or alcohol to feel better or to simply not feel?\nHave your sleep habits or appetite changed?\nAre you troubled by unexplained headaches, backaches or other physical complaints?\n\nAccording to the Mayo Clinic, answering yes to more than one of these questions can be a sign that you need to take corrective action. We\u2019ll look in more detail about the corrective actions you can take in the rest of this article. \nDo less. Now.\nTo start getting things back on track, you\u2019ll need to start doing less. Less work, less stress, less everything. Many technologists impacted by burnout have written or spoken on taking months or even years off work to give themselves time to recover. This can be a fantastic route back to wellness for those fortunate enough to have the professional and financial security to allow them to take large stretches of time off work. For the much larger group of burned out workers that need to balance earning a paycheck with their wellness, this can be more challenging.\nFor those of us who need to stay in the cycle of work to fund our daily needs, finding ways to do less can feel like adding another daunting task to the pile. To properly assess where and how you can cut back on your commitments, you\u2019ll need to find a short stretch of time clear of stressors and responsibilities to take stock of what can be scaled back. A long weekend, weekend or even a few hours of time dedicated to looking only at how you can cut back on work and stress can be an effective way to take stock of your responsibilities.\nMake a list of stressors and activities to begin to triage. Anything that would damage or seriously disrupt your life if not attended to (doing your taxes, showing up at work, paying rent) should be marked as essential. Grade other activities in your life, marking the ones that aren\u2019t essential and working to temporarily reduce these or remove them from your life. It can feel difficult to let go of things while recovering from burnout. This process can benefit from a second opinion, if you\u2019re working with a coach, therapist or trusted friend to manage your burnout.\nReducing your workload and stressors can let you begin to recover from burnout. You can reintroduce things back into your schedule and life. Reintroduce stressors and activities back into your life slowly, to minimize risk of relapse. Keeping a journal will let you keep tabs on how different activities are impacting your energy levels and state of mind.\nRemove toxicity\nToxic people or settings can drain you faster than overwork alone can. While you work to reduce your workload and stress, coworkers, friends, family or bosses who are toxic influences can act as a multiplier for the stressors that remain. Identifying these people and limiting your interactions with them during your recovery can help you get back on track faster and happier. A journal can be an important tool in tracking how interactions with different people impact your wellness and state of mind. If the toxic presence in your life is someone you can avoid or cut out without penalty, burnout is a great reason to finally replace them with healthier relationships.\nIf you can\u2019t remove them from your life, minimizing the impact toxic people have on your wellness is vital. Work to identify what aspect of the relationship is draining or damaging and create interventions around damaging interactions. While a chronically complaining coworker\u2019s negativity can be stopped short with setting firm conversational boundaries and redirection, a combative boss can be a harder challenge. Seeking allies and advice can make you feel less alone in your battles and provide healthy emotional support. \nAsk for help\nTrying to find your way back to health and wellness after burning out can be a daunting task. Seeking help from health care professionals, trusted peers or both can give you backup on your journey back to feeling better. With symptoms that can mirror those of depression, burnout can be the precursor to a number of mental and physical ailments. Talk to your doctor immediately if you\u2019re experiencing symptoms of depression or any other health concerns.\nBeing open with your trusted friends about burnout can let you access valuable support and help explain why you may need extra care and consideration while you recover. Many suffering from burnout report finding maintaining relationships a challenge. Letting your loved ones know what you\u2019re going through and why you may be less available invites them to be more understanding of cancelled plans or other issues while you\u2019re recovering. Burnout can impact memory and cognitive function. Letting your support network assist in decision making during burnout can help add perspective to counterbalance these deficits.\nTalking to your friends and peers about your health and needs can offer valuable support. But those who are pushed to a mental or physical health crisis by burnout should work with healthcare professionals to plan their recovery. Sufferers of mild to moderate burnout can also benefit from planning their return to wellness with an experienced practitioner. Medical or counseling professionals may prescribe medicines, talk therapy, group sessions or other therapeutic intervention. \nGo easy on yourself\nRecovering from burnout is a process that takes energy, time and compassion for yourself. In the same way that toxic people or workplaces can set you back, negative repetitive thoughts will harm your recovery. Recognizing that burnout\u2019s impact on you is a temporary state that isn\u2019t your fault can help you begin to manage your feelings and expectations for yourself. Sufferers often report feeling stupid, lazy or that they lack the skills to do their job. This is natural, as burnout can severely limit your cognitive function, your energy levels and resilience while dramatically increasing your cognitive load. Working with a counselor may help if you\u2019re finding it difficult to be patient with your progress back to health or are troubled by persistent intrusive thoughts.\nBurnout can seriously limit the amount of energy you have. Spend as little of the energy you have left beating yourself up as possible. You\u2019re going to be ok. It\u2019s all going to be ok.\nThis article doesn\u2019t offer one-size-fits all fixes for burnout or overwork, but aims to provide a framework with points to consider that may help shape your wellness. No article can act as a substitute for professionally administered healthcare or robust self care.", "year": "2017", "author": "Jessica Rose", "author_slug": "jessicarose", "published": "2017-12-16T00:00:00+00:00", "url": "https://24ways.org/2017/care-and-feeding-of-burnout/", "topic": "process"}