{"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": 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": 256, "title": "Develop Your Naturalist Superpowers with Observable Notebooks and iNaturalist", "contents": "We\u2019re going to level up your knowledge of what animals you might see in an area at a particular time of year - a skill every naturalist* strives for - using technology! Using iNaturalist and Observable Notebooks we\u2019re going to prototype seasonality graphs for particular species in an area, and automatically create a guide to what animals you might see in each month.\n*(a Naturalist is someone who likes learning about nature, not someone who\u2019s a fan of being naked, that\u2019s a \u2018Naturist\u2019\u2026 different thing!)\nLooking for critters in rocky intertidal habitats\nOne of my favourite things to do is going rockpooling, or as we call it over here in California, \u2018tidepooling\u2019. Amounting to the same thing, it\u2019s going to a beach that has rocks where the tide covers then uncovers little pools of water at different times of the day. All sorts of fun creatures and life can be found in this \u2018rocky intertidal habitat\u2019\nA particularly exciting creature that lives here is the Nudibranch, a type of super colourful \u2018sea slug\u2019. There are over 3000 species of Nudibranch worldwide. (The word \u201cnudibranch\u201d comes from the Latin nudus, naked, and the Greek \u03b2\u03c1\u03b1\u03bd\u03c7\u03b9\u03b1 / brankhia, gills.)\n\u200b\n\nThey are however quite tricky to find! Even though they are often brightly coloured and interestingly shaped, some of them are very small, and in our part of the world in the Bay Area in California their appearance in our rockpools is seasonal. We see them more often in Summer months, despite the not-as-low tides as in our Winter and Spring seasons.\nMy favourite place to go tidepooling here is Pillar Point in Half Moon bay (at other times of the year more famously known for the surf competition \u2018Mavericks\u2019). The rockpools there are rich in species diversity, of varied types and water-coverage habitat zones as well as being relatively accessible.\n\u200b\n\nI was rockpooling at Pillar Point recently with my parents and we talked to a lady who remarked that she hadn\u2019t seen any Nudibranchs on her visit this time. I realised that having an idea of what species to find where, and at what time of year is one of the many superpower goals of every budding Naturalist. \nUsing technology and the croudsourced species observations of the iNaturalist community we can shortcut our way to this superpower!\nFinding nearby animals with iNaturalist\nWe\u2019re going to be getting our information about what animals you can see in Pillar Point using iNaturalist. iNaturalist is a really fun platform that helps connect people to nature and report their findings of life in the outdoors. It is also a community of nature-loving people who help each other identify and confirm those observations. iNaturalist is a project run as a joint initiative by the California Academy of Sciences and the National Geographic Society.\nI\u2019ve been using iNaturalist for over two years to record and identify plants and animals that I\u2019ve found in the outdoors. I use their iPhone app to upload my pictures, which then uses machine learning algorithms to make an initial guess at what it is I\u2019ve seen. The community is really active, and I often find someone else has verified or updated my species guess pretty soon after posting. \nThis process is great because once an observation has been identified by at least two people it becomes \u2018verified\u2019 and is considered research grade. Research grade observations get exported and used by scientists, as well as being indexed by the Global Biodiversity Information Facility, GBIF.\n\u200b\n\niNaturalist has a great API and API explorer, which makes interacting and prototyping using iNaturalist data really fun. For example, if you go to the API explorer and expand the Observations : Search and fetch section and then the GET /observations API, you get a selection of input boxes that allow you to play with options that you can then pass to the API when you click the \u2018Try it out\u2019 button.\n\u200b\n\nYou\u2019ll then get a URL that looks a bit like\nhttps://api.inaturalist.org/v1/observations?captive=false &geo=true&verifiable=true&taxon_id=47113&lat=37.495461&lng=-122.499584 &radius=5&order=desc&order_by=created_at \nwhich you can call and interrrogate using a programming language of your choice.\nIf you would like to see an all-JavaScript application that uses the iNaturalist API, take a look at OwlsNearMe.com which Simon and I built one weekend earlier this year. It gets your location and shows you all iNaturalist observations of owls near you and lists which species you are likely to see (not adjusted for season).\nRapid development using Observable Notebooks\nWe\u2019re going to be using Observable Notebooks to prototype our examples, pulling data down from iNaturalist. I really like using visual notebooks like Observable, they are great for learning and building things quickly. You may be familiar with Jupyter notebooks for Python which is similar but takes a bit of setup to get going - I often use these for prototyping too. Observable is amazing for querying and visualising data with JavaScript and since it is a hosted product it doesn\u2019t require any setup at all.\nYou can follow along and play with this example on my Observable notebook. If you create an account there you can fork my notebook and create your own version of this example. \nEach \u2018notebook\u2019 consists of a page with a column of \u2018cells\u2019, similar to what you get in a spreadsheet. A cell can contain Markdown text or JavaScript code and the output of evaluating the cell appears above the code that generated it. There are lots of tutorials out there on Observable Notebooks, I like this code introduction one from Observable (and D3) creator Mike Bostock.\nDeveloping your Naturalist superpowers\nIf you have an idea of what plants and critters you might see in a place at the time you visit, you can hone in on what you want to study and train your Naturalist eye to better identify the life around you.\nFor our example, we care about wildlife we can see at Pillar Point, so we need a way of letting the iNaturalist API know which area we are interested in.\nWe could use a latitide, longitude and radius for this, but a rectangular bounding box is a better shape for the reef. We can use this tool to draw the area we want to search within: boundingbox.klokantech.com\n\u200b\n\nThe tool lets you export the bounding box in several forms using the dropdown at the bottom left under the map givese We are going to use the \u2018DublinCore\u2019 format as it\u2019s closest to the format needed by the iNaturalist API.\n westlimit=-122.50542; southlimit=37.492805; eastlimit=-122.492738; northlimit=37.499811\nA quick map primer:\nThe higher the latitude the more north it is\nThe lower the latitude the more south it is\nLatitude 0 = the equator\n\nThe higher the longitude the more east it is of Greenwich\nThe lower the longitude the more west it is of Greenwich\nLongitude 0 = Greenwich\nIn the iNaturalst API we want to use the parameters nelat, nelng, swlat, swlng to create a query that looks inside a bounding box of Pillar Point near Half Moon Bay in California:\nnelat = highest latitude = north limit = 37.499811\nnelng = highest longitude = east limit = -122.492738\nswlat = smallest latitude = south limit = 37.492805\nswlng = smallest longitude = west limit = 122.50542\nAs API parameters these look like this:\n?nelat=37.499811&nelng=-122.492738&swlat=37.492805&swlng=122.50542\nThese parameters in this format can be used for most of the iNaturalist API methods.\nNudibranch seasonality in Pillar Point\nWe can use the iNaturalist observation_histogram API to get a count of Nudibranch observations per week-of-year across all time and within our Pillar Point bounding box.\nIn addition to the geographic parameters that we just worked out, we are also sending the taxon_id of 47113, which is iNaturalists internal number associated with the Nudibranch taxon. By using this we can get all species which are under the parent \u2018Order Nudibranchia\u2019. \nAnother useful piece of naturalist knowledge is understanding the biological classification scheme of Taxanomic Rank - roughly, when a species has a Latin name of two words eg \u2018Glaucus Atlanticus\u2019 the first Latin word is the \u2018Genus\u2019 like a family name \u2018Glaucus\u2019, and the second word identifies that particular species, like a given name \u2018Atlanticus\u2019. \nThe two Latin words together indicate a specific species, the term we use colloquially to refer to a type of animal often differs wildly region to region, and sometimes the same common name in two countries can refer to two different species. The common names for the Glaucus Atlanticus (which incidentally is my favourite sea slug) include: sea swallow, blue angel, blue glaucus, blue dragon, blue sea slug and blue ocean slug! Because this gets super confusing, Scientists like using this Latin name format instead.\nThe following piece of code asks the iNaturalist Histogram API to return per-week counts for verified observations of Nudibranchs within our Pillar Point bounding box:\npillar_point_counts_per_week = fetch(\n \"https://api.inaturalist.org/v1/observations/histogram?taxon_id=47113&nelat=37.499811&nelng=-122.492738&swlat=37.492805&swlng=-122.50542&date_field=observed&interval=week_of_year&verifiable=true\"\n ).then(response => {\n return response.json();\n})\nOur next step is to take this data and draw a graph! We\u2019ll be using Vega-Lite for this, which is a fab JavaScript graphing libary that is also easy and fun to use with Observable Notebooks. \n(Here is a great tutorial on exploring data and drawing graphs with Observable and Vega-Lite)\nThe iNaturalist API returns data that looks like this:\n{\n \"total_results\": 53,\n \"page\": 1,\n \"per_page\": 53,\n \"results\": {\n \"week_of_year\": {\n \"1\": 136,\n \"2\": 20,\n \"3\": 150,\n \"4\": 65,\n \"5\": 186,\n \"6\": 74,\n \"7\": 47,\n \"8\": 87,\n \"9\": 64,\n \"10\": 56,\nBut for our Vega-Lite graph we need data that looks like this:\n[{\n \"week\": \"01\",\n \"value\": 136\n}, {\n \"week\": \"02\",\n \"value\": 20\n}, ...]\nWe can convert what we get back from the API to the second format using a loop that iterates over the object keys:\nobjects_to_plot = {\n let objects = [];\n Object.keys(pillar_point_counts_per_week.results.week_of_year).map(function(week_index) {\n objects.push({\n week: `Wk ${week_index.toString()}`,\n observations: pillar_point_counts_per_week.results.week_of_year[week_index]\n });\n })\n return objects;\n}\nWe can then plug this into Vega-Lite to draw us a graph:\nvegalite({\n data: {values: objects_to_plot},\n mark: \"bar\",\n encoding: {\n x: {field: \"week\", type: \"nominal\", sort: null},\n y: {field: \"observations\", type: \"quantitative\"}\n },\n width: width * 0.9\n})\n\nIt\u2019s worth noting that we have a lot of observations of Nudibranchs particularly at Pillar Point due in no small part to the intertidal monitoring research that Alison Young and Rebecca Johnson facilitate for the California Achademy of Sciences. \nSo, what if we want to look for the seasonality of observations of a particular species of adorable sea slug? We want our interface to have a select box with a list of all the species you might find at any time of year. We can do this using the species_counts API to create us an object with the iNaturalist species ID and common & Latin names.\npillar_point_nudibranches = {\n let api_results = await fetch(\n \"https://api.inaturalist.org/v1/observations/species_counts?taxon_id=47113&nelat=37.499811&nelng=-122.492738&swlat=37.492805&swlng=-122.50542&date_field=observed&verifiable=true\"\n ).then(r => r.json())\n\n let species_list = api_results.results.map(i => ({\n value: i.taxon.id,\n label: `${i.taxon.preferred_common_name} (${i.taxon.name})`\n }));\n\n return species_list\n}\nWe can create an interactive select box by importing code from Jeremy Ashkanas\u2019 Observable Notebook: add import {select} from \"@jashkenas/inputs\" to a cell anywhere in our notebook. Observable is magic: like a spreadsheet, the order of the cells doesn\u2019t matter - if one cell is referenced by any other cell then when that cell updates all the other cells refresh themselves. You can also import and reference one notebook from another!\nviewof select_species = select({\n title: \"Which Nudibranch do you want to see seasonality for?\",\n options: [{value: \"\", label: \"All the Nudibranchs!\"}, ...pillar_point_nudibranches],\n value: \"\"\n})\nThen we go back to our old favourite, the histogram API just like before, only this time we are calling it with the value created by our select box ${select_species} as taxon_id instead of the number 47113.\npillar_point_counts_per_month_per_species = fetch(\n `https://api.inaturalist.org/v1/observations/histogram?taxon_id=${select_species}&nelat=37.499811&nelng=-122.492738&swlat=37.492805&swlng=-122.50542&date_field=observed&interval=month_of_year&verifiable=true`\n).then(r => r.json())\nNow for the fun graph bit! As we did before, we re-format the result of the API into a format compatible with Vega-Lite:\nobjects_to_plot_species_month = {\n let objects = [];\n Object.keys(pillar_point_counts_per_month_per_species.results.month_of_year).map(function(month_index) {\n objects.push({\n month: (new Date(2018, (month_index - 1), 1)).toLocaleString(\"en\", {month: \"long\"}),\n observations: pillar_point_counts_per_month_per_species.results.month_of_year[month_index]\n });\n })\n return objects;\n}\n(Note that in the above code we are creating a date object with our specific month in, and using toLocalString() to get the longer English name for the month. Because the JavaScript Date object counts January as 0, we use month_index -1 to get the correct month)\nAnd we draw the graph as we did before, only now if you interact with the select box in Observable the graph will dynamically update!\nvegalite({\n data: {values: objects_to_plot_species_month},\n mark: \"bar\",\n encoding: {\n x: {field: \"month\", type: \"nominal\", sort:null},\n y: {field: \"observations\", type: \"quantitative\"}\n },\n width: width * 0.9\n})\nNow we can see when is the best time of year to plan to go tidepooling in Pillar Point if we want to find a specific species of Nudibranch.\n\u200b\n\nThis tool is great for planning when we to go rockpooling at Pillar Point, but what about if you are going this month and want to pre-train your eye with what to look for in order to impress your friends with your knowledge of Nudibranchs?\nWell\u2026 we can create ourselves a dynamic guide that you can with a list of the species, their photo, name and how many times they have been observed in that month of the year!\nOur select box this time looks as follows, simpler than before but assigning the month value to the variable selected_month.\nviewof selected_month = select({\n title: \"When do you want to see Nudibranchs?\",\n options: [\n { label: \"Whenever\", value: \"\" },\n { label: \"January\", value: \"1\" },\n { label: \"February\", value: \"2\" },\n { label: \"March\", value: \"3\" },\n { label: \"April\", value: \"4\" },\n { label: \"May\", value: \"5\" },\n { label: \"June\", value: \"6\" },\n { label: \"July\", value: \"7\" },\n { label: \"August\", value: \"8\" },\n { label: \"September\", value: \"9\" },\n { label: \"October\", value: \"10\" },\n { label: \"November\", value: \"11\" },\n { label: \"December\", value: \"12\" },\n ],\n value: \"\"\n })\nWe then can use the species_counts API to get all the relevant information about which species we can see in month=${selected_month}. We\u2019ll be able to reference this response object and its values later with the variable we just created, eg: all_species_data.results[0].taxon.name.\nall_species_data = fetch(\n `https://api.inaturalist.org/v1/observations/species_counts?taxon_id=47113&month=${selected_month}&nelat=37.499811&nelng=-122.492738&swlat=37.492805&swlng=-122.50542&verifiable=true`\n).then(r => r.json())\nYou can render HTML directly in a notebook cell using Observable\u2019s html tagged template literal:\n\n\n

If you go to Pillar Point ${\n {\"\": \"\",\n \"1\":\"in January\",\n \"2\":\"in Febrary\",\n \"3\":\"in March\",\n \"4\":\"in April\",\n \"5\":\"in May\",\n \"6\":\"in June\",\n \"7\":\"in July\",\n \"8\":\"in August\",\n \"9\":\"in September\",\n \"10\":\"in October\",\n \"11\":\"in November\",\n \"12\":\"in December\",\n }[selected_month]\n } you might see\u2026

\n\n
\n${all_species_data.results.map(s => `

${s.taxon.name}

\n

Seen ${s.count} times

\n
\n`)}\n
\nThese few lines of HTML are all you need to get this exciting dynamic guide to what Nudibranchs you will see in each month!\n\u200b\n\nPlay with it yourself in this Observable Notebook.\nConclusion\nI hope by playing with these examples you have an idea of how powerful it can be to prototype using Observable Notebooks and how you can use the incredible crowdsourced community data and APIs from iNaturalist to augment your naturalist skills and impress your friends with your new \u2018knowledge of nature\u2019 superpower.\nLastly I strongly encourage you to get outside on a low tide to explore your local rocky intertidal habitat, and all the amazing critters that live there.\nHere is a great introduction video to tidepooling / rockpooling, by Rebecca Johnson and Alison Young from the California Academy of Sciences.", "year": "2018", "author": "Natalie Downe", "author_slug": "nataliedowne", "published": "2018-12-18T00:00:00+00:00", "url": "https://24ways.org/2018/observable-notebooks-and-inaturalist/", "topic": "code"} {"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": 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": 317, "title": "Putting the World into \"World Wide Web\"", "contents": "Despite the fact that the Web has been international in scope from its inception, the predominant mass of Web sites are written in English or another left-to-right language. Sites are typically designed visually for Western culture, and rely on an enormous body of practices for usability, information architecture and interaction design that are by and large centric to the Western world.\n\nThere are certainly many reasons this is true, but as more and more Web sites realize the benefits of bringing their products and services to diverse, global markets, the more demand there will be on Web designers and developers to understand how to put the World into World Wide Web.\n\nInternationalization\n\nAccording to the W3C, Internationalization is:\n\n\n\t\u201c\u2026the design and development of a product, application or document content that enables easy localization for target audiences that vary in culture, region, or language.\u201d\n\n\nMany Web designers and developers have at least heard, if not read, about Internationalization. We understand that the Web is in fact worldwide, but many of us never have the opportunity to work with Internationalization. Or, when we do, think of it in purely technical terms, such as \u201cwhich character set do I use?\u201d\n\nAt first glance, it might seem to many that Internationalization is the act of making Web sites available to international audiences. And while that is in fact true, this isn\u2019t done by broad-stroking techniques and technologies. Instead, it involves a far more narrow understanding of geographical, cultural and linguistic differences in specific areas of the world. This is referred to as localization and is the act of making a Web site make sense in the context of the region, culture and language(s) the people using the site are most familiar with.\n\nInternationalization itself includes the following technical tasks:\n\n\n\tEnsuring no barrier exists to the localization of sites. Of critical importance in the planning stages of a site for Internationalized audiences, the role of the developer is to ensure that no barrier exists. This means being able to perform such tasks as enabling Unicode and making sure legacy character encodings are properly handled.\n\tPreparing markup and CSS with Internationalization in mind. The earlier in the site development process this occurs, the better. Issues such as ensuring that you can support bidirectional text, identifying language, and using CSS to support non-Latin typographic features.\n\tEnabling code to support local, regional, language or culturally related references. Examples in this category would include time/date formats, localization of calendars, numbering systems, sorting of lists and managing international forms of addresses.\n\tEmpowering the user. Sites must be architected so the user can easily choose or implement the localized alternative most appropriate to them.\n\n\nLocalization\n\nAccording to the W3C, Localization is the:\n\n\n\t\u2026adaptation of a product, application or document content to meet the language, cultural and other requirements of a specific target market (a \u201clocale\u201d).\n\n\nSo here\u2019s where we get down to thinking about the more sociological and anthropological concerns. Some of the primary localization issues are:\n\n\n\tNumeric formats. Different languages and cultures use numbering systems unlike ours. So, any time we need to use numbers, such as in an ordered list, we have to have a means of representing the accurate numbering system for the locale in question.\n\tMoney, honey! That\u2019s right. I\u2019ve got a pocketful of ugly U.S. dollars (why is U.S. money so unimaginative?). But I also have a drawer full of Japanese Yen, Australian Dollars, and Great British Pounds. Currency, how it\u2019s calculated and how it\u2019s represented is always a consideration when dealing with localization.\n\tUsing symbols, icons and colors properly. Using certain symbols or icons on sites where they might offend or confuse is certainly not in the best interest of a site that wants to sell or promote a product, service or information type. Moreover, the colors we use are surprisingly persuasive \u2013 or detrimental. Think about colors that represent death, for example. In many parts of Asia, white is the color of death. In most of the Western world, black represents death. For Catholic Europe, shades of purple (especially lavender) have represented Christ on the cross and mourning since at least Victorian times. When Walt Disney World Europe launched an ad campaign using a lot of purple and very glitzy imagery, millions of dollars were lost as a result of this seeming subtle issue. Instead of experiencing joy and celebration at the ads, the European audience, particularly the French, found the marketing to be overly American, aggressive, depressing and basically unappealing. Along with this and other cultural blunders, Disney Europe has become a well-known case study for businesses wishing to become international. By failing to understand localization differences, and how powerful color and imagery act on the human psyche, designers and developers are put to more of a disadvantage when attempting to communicate with a given culture.\n\tChoosing appropriate references to objects and ideas. What seems perfectly natural in one culture in terms of visual objects and ideas can get confused in another environment. One of my favorite cases of this has to do with Gerber baby food. In the U.S., the baby food is marketed using a cute baby on the package. Most people in the U.S. culturally do not make an immediate association that what is being represented on the label is what is inside the container. However, when Gerber expanded to Africa, where many people don\u2019t read, and where visual associations are less abstract, people made the inference that a baby on the cover of a jar of food represented what is in fact in the jar. You can imagine how confused and even angry people became. Using such approaches as a marketing ploy in the wrong locale can and will render the marketing a failure.\n\n\nAs you can see, the act of localization is one that can have profound impact on the success of a business or organization as it seeks to become available to more and more people across the globe.\n\nRethinking Design in the Context of Culture\n\nWhile well-educated designers and those individuals working specifically for companies that do a lot of localization understand these nuances, most of us don\u2019t get exposed to these ideas. Yet, we begin to see how necessary it becomes to have an awareness of not just the technical aspects of Internationalization, but the socio-cultural ones within localization.\n\nWhat\u2019s more, the bulk of information we have when it comes to designing sites typically comes from studies and work done on sites built in English and promoted to Western culture at large. We\u2019re making a critical mistake by not including diverse languages and cultural issues within our usability and information architecture studies.\n\nConsider the following design from the BBC:\n\n\n\nIn this case, we\u2019re dealing with English, which is read left to right. We are also dealing with U.K. cultural norms. Notice the following:\n\n\n\tLocation of of navigation\n\tUse of the color red\n\tUse of diverse symbols\n\tMix of symbols, icons and photos\n\tLocation of Search\n\n\nNow look at this design, which is the Arabic version of the BBC News, read right to left, and dealing with cultural norms within the Arabic-speaking world.\n\n\n\nNotice the following:\n\n\n\tLocation of of navigation (location switches to the right)\n\tUse of the color blue (blue is considered the \u201csafest\u201d global color)\n\tNo use of symbols and icons whatsoever\n\tLimitation of imagery to photos\n\tIn most cases, the photos show people, not objects\n\tLocation of Search\n\n\nAdmittedly, some choices here are more obvious than others in terms of why they were made. But one thing that stands out is that the placement of search is the same for both versions. Is this the result of a specific localization decision, or based on what we believe about usability at large? This is exactly the kind of question that designers working on localization have to seek answers to, instead of relying on popular best practices and belief systems that exist for English-only Web sites.\n\nIt\u2019s a Wide World Web After All\n\nFrom this brief article on Internationalization, it becomes apparent that the art and science of creating sites for global audiences requires a lot more preparation and planning than one might think at first glance. Developers and designers not working to address these issues specifically due to time or awareness will do well to at least understand the basic process of making sites more culturally savvy, and better prepared for any future global expansion.\n\nOne thing is certain: We not only are on a dramatic learning curve for designing and developing Web sites as it is, the need to localize sites is going to become more and more a part of the day to day work. Understanding aspects of what makes a site international and local will not only help you expand your skill set and make you more marketable, but it will also expand your understanding of the world and the people within it, how they relate to and use the Web, and how you can help make their experience the best one possible.", "year": "2005", "author": "Molly Holzschlag", "author_slug": "mollyholzschlag", "published": "2005-12-09T00:00:00+00:00", "url": "https://24ways.org/2005/putting-the-world-into-world-wide-web/", "topic": "ux"} {"rowid": 212, "title": "Refactoring Your Way to a Design System", "contents": "I love refactoring code. Absolutely love it. There\u2019s something about taking a piece of UI or a bit of code and reworking it in a way that is simpler, modular, and reusable that makes me incredibly happy.\nI also love design systems work. It gives hybrids like me a home. It seems like everyone is talking about design systems right now. Design systems teams are perfect for those who enjoy doing architectural work and who straddle the line between designer and developer. \nUna Kravets recently identified some of the reasons that design systems fail, and chief among them are lack of buy-in, underlying architecture, and communication. While it\u2019s definitely easier to establish these before project work begins, that doesn\u2019t mean it is the only path to success. \nIt\u2019s a privilege to work on a greenfield project, and one that is not afforded to many. Companies with complex and/or legacy codebases may not be able to support a full rewrite of their product. In addition, many people feel overwhelmed at the thought of creating a complete system and are at a loss of how or where to even begin the process. \nThis is where refactoring comes into play.\nAccording to Martin Fowler, \u201crefactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.\u201d It\u2019s largely invisible work, and if you do it right, the end user will never know the difference. What it will do is provide a decent foundation to begin more systematic work.\nBuild a solid foundation\nWhen I was first asked to create Pantsuit, the design system for Hillary for America, I was tasked with changing our codebase to be more modular and scalable, without changing the behavior or visual design of the UI. We needed a system in place that would allow for the rapid creation of new projects while maintaining a consistent visual language. In essence, I was asked to refactor our code into a design system.\nDuring that refactor, I focused the majority of my efforts on creating a scalable architecture based on the UI components in a single workflow. Since I needed to maintain a 1:1 parity with production, the only changes I could create were under-the-hood. I started with writing coding standards and deciding on a CSS architecture that I would then use as I rewrote sections of the codebase. \nIf you already have these in place, great! If not, then this is an excellent place to start. Even if your dream of a design system is never fully realized, having a coding philosophy and architecture in place will still have far-reaching benefits and implications.\nI want to note that if your refactor includes creating new coding standards or a CSS architecture, don\u2019t try to switch everything over right away. Instead, focus on a single new feature and isolate/encapsulate your work from the rest of the codebase.\nFocus on the features\n\nThe key principle to cleaning up a complex codebase is to always refactor in the service of a feature. \n\u2014 Max Kanat-Alexander\n\nRefactoring for the sake of refactoring can easily lead to accusations of misused time and lack of results. Another danger of refactoring is that it can turn into yak-shaving if you aren\u2019t disciplined in your approach. To that end, tying your refactored components to feature work is a great way to limit scope and reduce the rest of unintended changes.\nFor example, the initial work on Pantsuit focused only on components related to the donations flow. Every line of code I wrote was in service to improving the maintainability and modularity of that UI. Because we didn\u2019t have any standards in place, I started with those. From there, I identified all the components present in every step of the donations flow, which included some type styles, buttons, form inputs and error states. Then came the refactor of each individual component. Finally, I reintegrated the newly refactored components into the existing donations flow and tested it against production, checking for visual and behavioral diffs. At the end of this process, I had the beginning of a design system that would grow to serve over 50 applications, and a case study to demonstrate its effectiveness.\nIdeally, you\u2019ll want to get buy-in from your stakeholders and product owners before you begin any design systems work. However, in the absence of buy-in, linking your work to new feature development is a good way to both limit the scope of your refactor and jump start component creation.\nIn addition, if you\u2019re still trying to convince your team of the benefits of a design system, starting small and using the newly refactored, feature-driven work as a case study is one way showcase a design systems\u2019 value. By providing a concrete example of how working towards a design system contributed to the project\u2019s success, you\u2019re gathering the data necessary to secure buy-in for a larger-scale effort. It\u2019s a great way to show value, rather than just talking about it.\nShow, don\u2019t tell\nPerhaps the most important thing you can do for any design system is to document it. The key is to create a frictionless way to keep the documentation up-to-date, otherwise no one will contribute to it, and in turn, it will become obsolete and useless. \nThere are lots of tools out there to help you get started documenting your new system. One of my favorites is KSS, which parses comments in the code and uses them to generate a style guide. For Pantsuit, I used the node version of KSS, along with a template to quickly spin up a documentation site.\nI\u2019ve listed just a few tools below; for even more, check out the tools sections of styleguides.io.\n\nFractal\nPattern Lab\nDrizzle\nFabricator\nAstrum\nCatalog\n\nRegardless of what tool you settle on, it needs to integrate well with your current workflow. \nConclusion: always be refactoring\nIf you\u2019re not lucky enough to be able to start a new design system from scratch, you can start small and work on a single feature or component. With each new project comes a new opportunity to flesh out a new part of the system, and another potential case study to secure buy-in and showcase its value. Make sure to carefully and thoroughly document each new portion of the system as it\u2019s built. After a few projects, you\u2019ll find yourself with a decent start to a design system. \nGood luck, and happy holidays!\nFurther reading:\n\nWhy Design Systems Fail\nCSS Architecture for Design Systems\nRefactoring: Improving the Design of Existing Code\nRefactoring CSS: The Three I\u2019s\nRefactoring is About Features", "year": "2017", "author": "Mina Markham", "author_slug": "minamarkham", "published": "2017-12-23T00:00:00+00:00", "url": "https://24ways.org/2017/refactoring-your-way-to-a-design-system/", "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": 217, "title": "Beyond Web Mechanics \u2013 Creating Meaningful Web Design", "contents": "It was just over three years ago when I embarked on becoming a web designer, and the first opinion piece about the state of web design I came across was a conference talk by Elliot Jay Stocks called \u2018Destroy the Web 2.0 Look\u2019. Elliot\u2019s presentation was a call to arms, a plea to web designers the world over to stop the endless reproductions of the so called \u2018Web 2.0 look\u2019.\n\nThree and a half years on from Elliot\u2019s talk, what has changed? Well, from an aesthetic standpoint, not a whole lot. The Web 2.0 look has evolved, but it\u2019s still with us and much of the web remains filled with cookie cutter websites that bear a striking resemblance to one another. This wouldn\u2019t matter so much if these websites were selling comparable services or products, but they\u2019re not. They look similar, they follow the same web design trends; their aesthetic style sends out a very similar message, yet they\u2019re selling completely different services or products. How can you be communicating effectively with your users when your online book store is visually indistinguishable from an online cosmetic store? This just doesn\u2019t make sense. \n\nI don\u2019t want to belittle the current version of the Web 2.0 look for the sake of it. I want to talk about the opportunity we have as web designers to create more meaningful experiences for the people using our websites. Using design wisely gives us the ability to communicate messages, ideas and attitudes that our users will understand and connect with.\n\nBeing human\n\nAs human beings we respond emotionally to everything around us \u2013 people, objects, posters, packaging or websites. We also respond in different ways to different kinds of aesthetic design and style. We care about style and aesthetics deeply, whether we realise it or not. Aesthetic design has the power to attract or repel. We often make decisions based purely on aesthetics and style \u2013 and don\u2019t retailers the world over know it! We connect attitudes and strongly held beliefs to style. Individuals will proudly associate themselves with a certain style or aesthetic because it\u2019s an expression of who they are. You know that old phrase, \u2018Don\u2019t judge a book by its cover\u2019? Well, the problem is that people do, so it\u2019s important we get the cover right.\n\nMuch is made of how to structure web pages, how to create a logical information hierarchy, how to use layout and typography to clearly communicate with your users. It\u2019s important, however, not to mistake clarity of information or legibility with getting your message across. Few users actually read websites word by word: it\u2019s far more likely they\u2019ll just scan the page. If the page is copy-heavy and nothing grabs their attention, they may well just move on. This is why it\u2019s so important to create a visual experience that actually means something to the user. \n\nMeaningful design\n\nWhen we view a poster or website, we make split-second assessments and judgements of what is in front of us. Our first impressions of what a website does or who it is aimed at are provoked by the style and aesthetic of the website. For example, with clever use of colour, typography, graphic design and imagery we can communicate to users that an organisation is friendly, edgy, compassionate, fun or environmentally conscious.\n\nUsing a certain aesthetic we can convey the personality of that organisation, target age ranges, different sexes or cultural groups, communicate brand attributes, and more. We can make our users feel like they\u2019re part of something and, perhaps even more importantly, we can make new users want to be a part of something. And we can achieve all this before the user has read a single word. \n\nBy establishing a website\u2019s aesthetic and creating a meaningful visual language, a design is no longer just a random collection of pretty gradients that have been plucked out of thin air. There can be a logic behind the design decisions we make. So, before you slap another generic piece of ribbon or an ultra shiny icon into the top-left corner of your website, think about why you are doing it. If you can\u2019t come up with a reason better than \u201cI saw it on another website\u201d, it\u2019s probably a poor application of style.\n\nDesign and style\n\nThere are a number of reasons why the web suffers from a lack meaningful design. Firstly, there are too many preconceptions of what a website should look like. It\u2019s too easy for designers to borrow styles from other websites, thereby limiting the range of website designs we see on the web. Secondly, many web designers think of aesthetic design as of secondary importance, which shouldn\u2019t be the case. Designing websites that are accessible and easy to use is, of course, very important but this is the very least a web designer should be delivering. Easy to use websites should come as standard \u2013 it\u2019s equally important to create meaningful, compelling and beautiful experiences for everyone who uses our websites. The aesthetics of your site are part of the design, and to ignore this and play down the role of aesthetic design is just a wasted opportunity. \n\nNo compromise necessary\n\nEasy to use, accessible websites and beautiful, meaningful aesthetics are not mutually exclusive. The key is to apply style and aesthetic design appropriately. We need to think about who and what we\u2019re designing for and ask ourselves why we\u2019re applying a certain kind of aesthetic style to our design. If you do this, there\u2019s no reason why effective, functional design should come at the expense of jaw-dropping, meaningful aesthetics.\n\nWeb designers need to understand the differences between functional design and aesthetic design but, even more importantly, they need to know how to make them work together. It\u2019s combining these elements of design successfully that makes for the best web design in the world.", "year": "2010", "author": "Mike Kus", "author_slug": "mikekus", "published": "2010-12-05T00:00:00+00:00", "url": "https://24ways.org/2010/beyond-web-mechanics-creating-meaningful-web-design/", "topic": "design"} {"rowid": 281, "title": "Nine Things I've Learned", "contents": "I\u2019ve been a professional graphic designer for fourteen years and for just under four of those a professional web designer. Like most designers I\u2019ve learned a lot in my time, both from a design point of view and in business as freelance designer. A few of the things I\u2019ve learned stick out in my mind, so I thought I\u2019d share them with you. They\u2019re pretty random and in no particular order.\n\n1. Becoming the designer you want to be\n\nWhen I started out as a young graphic designer, I wanted to design posters and record sleeves, pretty much like every other young graphic designer. The problem is that the reality of the world means that when you get your first job you\u2019re designing the back of a paracetamol packet or something equally weird. I recently saw a tweet that went something like this: \u201cYou\u2019ll never become the designer you always dreamt of being by doing the work you never wanted to do\u201d. This is so true; to become the designer you want to be, you need to be designing the things you\u2019re passionate about designing. This probably this means working in the evenings and weekends for little or no money, but it\u2019s time well spent. Doing this will build up your portfolio with the work that really shows what you can do! Soon, someone will ask you to design something based on having seen this work. From this point, you\u2019re carving your own path in the direction of becoming the designer you always wanted to be.\n\n2. Compete on your own terms\n\nAs well as all being friends, we are also competitors. In order to win new work we need a selling point, preferably a unique selling point. Web design is a combination of design disciplines \u2013 user experience design, user interface Design, visual design, development, and so on. Some companies will sell themselves as UX specialists, which is fine, but everyone who designs a website from scratch does some sort of UX, so it\u2019s not really a unique selling point. Of course, some people do it better than others.\n\nOne area of web design that clients have a strong opinion on, and will judge you by, is visual design. It\u2019s an area in which it\u2019s definitely possible to have a unique selling point. Designing the visual aesthetic for a website is a combination of logical decision making and a certain amount of personal style. If you can create a unique visual style to your work, it can become a selling point that\u2019s unique to you.\n\n3. How much to charge and staying motivated\n\nWhen you\u2019re a freelance designer one of the hardest things to do is put a price on your work and skills. Finding the right amount to charge is a fine balance between supplying value to your customer and also charging enough to stay motivated to do a great job. It\u2019s always tempting to offer a low price to win work, but it\u2019s often not the best approach: not just for yourself but for the client as well.\n\nA client once asked me if I could reduce my fee by \u00a31,000 and still be motivated enough to do a good job. In this case the answer was yes, but it was the question that resonated with me. I realized I could use this as a gauge to help me price projects. Before I send out a quote I now always ask myself the question \u201cIs the amount I\u2019ve quoted enough to make me feel motivated to do my best on this project?\u201d I never send out a quote unless the answer is yes. In my mind there\u2019s no point in doing any project half-heartedly, as every project is an opportunity to build your reputation and expand your portfolio to show potential clients what you can do. Offering a client a good price but not being prepared to put everything you have into it, isn\u2019t value for money. \n\n4. Supplying the right design\n\nWhen I started out as a graphic designer it seemed to be the done thing to supply clients with a ton of options for their logo or brochure designs. In a talk given by Dan Rubin, he mentioned that this was a legacy of agencies competing with each other in a bid to create the illusion of offering more value for money. Over the years, I\u2019ve realized that offering more than one solution makes no sense. The reason a client comes to you as a designer is because you\u2019re the person than can get it right. If I were to supply three options, I\u2019d be knowingly offering my client at least two options that I didn\u2019t think worked.\n\nTo this day I still get asked how many homepage design options I\u2019ll supply for the quoted amount. The answer is one. Of course, I\u2019m more than happy to iterate upon the design to fine-tune it and, on the odd occasion, I do revisit a design concept if I just didn\u2019t nail the design first time around. Your time is much better spent refining the right design option than rushing out three substandard designs in the same amount of time.\n\n5. Colour is key\n\nThere are many contributing factors that go into making a good visual design, but one of the simplest ways to do this is through the use of colour. The colour palette used in a design can have such a profound effect on a visual design that it almost feels like you\u2019re cheating. It\u2019s easy to add more and more subtle shades of colour to add a sense of sophistication and complexity to a design, but it dilutes the overall visual impact. When I design, I almost have a rule that only allows me to use a very limited colour palette. I don\u2019t always stick to it, but it\u2019s always in mind and something I\u2019m constantly reviewing through my design process.\n\n6. Creative thinking is central to good or boundary-pushing web design\n\nWhen we think of creativity in web design we often link this to the visual design, as there is an obvious opportunity to be creative in this area if the brief allows it. Something that I\u2019ve learnt in my time as a web designer is that there\u2019s a massive need for creative thinking in the more technical aspects of web design. The tools we use for building websites are there to be manipulated and used in creative ways to design exciting and engaging user experiences. Great developers are constantly using their creativity to push the boundaries of what can be done with CSS, jQuery and JavaScript. \n\nBeing creative and creative thinking are things we should embrace as an industry and they are qualities that can be found in anyone, whether they be a visual designer or Rails developer.\n\n7. Creative block: don\u2019t be afraid to get things wrong\n\nCreative block can be a killer when designing. It\u2019s often applied to visual design, which is more subjective. I suffer from creative block on a regular basis. It\u2019s hugely frustrating and can screw up your schedule. Having thought about what creative block actually is, I\u2019ve come to the conclusion that it\u2019s actually more of a lack of direction than a lack of ideas. You have ideas and solutions in mind but don\u2019t feel committed to any of them. You\u2019re scared that whatever direction you take, it\u2019ll turn out to be wrong. I\u2019ve found that the best remedy for this is to work through this barrier. It\u2019s a bit like designing with a blindfold on \u2013 you don\u2019t really know where you\u2019re going. If you stick to your guns and keep pressing forward I find that, nine times out of ten, this process leads to a solution. As the page begins to fill, the direction you\u2019re looking for slowly begins to take shape.\n\n8. You get better at designing by designing\n\nI often get emails asking me what books someone can read to help them become a better designer. There are a lot of good books on subjects like HTML5, CSS, responsive web design and the like, that will really help improve anyone\u2019s web design skills. But, when it comes to visual design, the best way to get better is to design as much as possible. You can\u2019t follow instructions for these things because design isn\u2019t following instructions. A large part of web design is definitely applying a set of widely held conventions, but there\u2019s another part to it that is invention and the only way to get better at this is to do it as much as possible.\n\n9. Self-belief is overrated\n\nThroughout our lives we\u2019re told to have self-belief. Self-belief and confidence in what we do, whatever that may be. The problem is that some people find it easier than others to believe in themselves. I\u2019ve spent years trying to convince myself to believe in what I do but have always found it difficult to have complete confidence in my design skills. Self-doubt always creeps in.\n\nI\u2019ve realized that it\u2019s ok to doubt myself and I think it might even be a good thing! I\u2019ve realized that it\u2019s my self-doubt that propels me forward and makes me work harder to achieve the best results. The reason I\u2019m sharing this is because I know I\u2019m not the only designer that feels this way. You can spend a lot of time fighting self-doubt only to discover that it\u2019s your body\u2019s natural mechanism to help you do the best job possible.", "year": "2011", "author": "Mike Kus", "author_slug": "mikekus", "published": "2011-12-11T00:00:00+00:00", "url": "https://24ways.org/2011/nine-things-ive-learned/", "topic": "business"} {"rowid": 125, "title": "Accessible Dynamic Links", "contents": "Although hyperlinks are the soul of the World Wide Web, it\u2019s worth using them in moderation. Too many links becomes a barrier for visitors navigating their way through a page. This difficulty is multiplied when the visitor is using assistive technology, or is using a keyboard; being able to skip over a block of links doesn\u2019t make the task of finding a specific link any easier.\n\nIn an effort to make sites easier to use, various user interfaces based on the hiding and showing of links have been crafted. From drop-down menus to expose the deeper structure of a website, to a decluttering of skip links so as not to impact design considerations. Both are well intentioned with the aim of preserving a good usability experience for the majority of a website\u2019s audience; hiding the real complexity of a page until the visitor interacts with the element.\n\nWhen JavaScript is not available\n\nThe modern dynamic link techniques rely on JavaScript and CSS, but regardless of whether scripting and styles are enabled or not, we should consider the accessibility implications, particularly for screen-reader users, and people who rely on keyboard access.\n\nIn typical web standards-based drop-down navigation implementations, the rough consensus is that the navigation should be structured as nested lists so when JavaScript is not available the entire navigation map is available to the visitor. This creates a situation where a visitor is faced with potentially well over 50 links on every page of the website. Keyboard access to such structures is frustrating, there\u2019s far too many options, and the method of serially tabbing through each link looking for a specific one is tedious.\n\nInstead of offering the visitor an indigestible chunk of links when JavaScript is not available, consider instead having the minimum number of links on a page, and when JavaScript is available bringing in the extra links dynamically. Santa Chris Heilmann offers an excellent proof of concept in making Ajax navigation optional.\n\nWhen JavaScript is enabled, we need to decide how to hide links. One technique offers a means of comprehensively hiding links from keyboard users and assistive technology users. Another technique allows keyboard and screen-reader users to access links while they are hidden, and making them visible when reached.\n\nHiding the links\n\nIn JavaScript enhanced pages whether a link displays on screen depends on a certain event happening first. For example, a visitor needs to click a top-level navigation link that makes a set of sub-navigation links appear. In these cases, we need to ensure that these links are not available to any user until that event has happened.\n\nThe typical way of hiding links is to style the anchor elements, or its parent nodes with display: none. This has the advantage of taking the links out of the tab order, so they are not focusable. It\u2019s useful in reducing the number of links presented to a screen-reader or keyboard user to a minimum. Although the links are still in the document (they can be referenced and manipulated using DOM Scripting), they are not directly triggerable by a visitor.\n\nOnce the necessary event has happened, like our visitor has clicked on a top-level navigation link which shows our hidden set of links, then we can display the links to the visitor and make them triggerable. This is done simply by undoing the display: none, perhaps by setting the display back to block for block level elements, or inline for inline elements. For as long as this display style remains, the links are in the tab order, focusable by keyboard, and triggerable.\n\nA common mistake in this situation is to use visibility: hidden, text-indent: -999em, or position: absolute with left: -999em to position these links off-screen. But all of these links remain accessible via keyboard tabbing even though the links remain hidden from screen view. In some ways this is a good idea, but for hiding sub-navigation links, it presents the screen-reader user and keyboard user with too many links to be of practical use.\n\nMoving the links out of sight\n\nIf you want a set of text links accessible to screen-readers and keyboard users, but don\u2019t want them cluttering up space on the screen, then style the links with position: absolute; left: -999em. Links styled this way remain in the tab order, and are accessible via keyboard. (The position: absolute is added as a style to the link, not to a parent node of the link \u2013 this will give us a useful hook to solve the next problem).\n\na.helper {\n\tposition: absolute;\n\tleft: -999em;\n}\n\nOne important requirement when displaying links off-screen is that they are visible to a keyboard user when they receive focus. Tabbing on a link that is not visible is a usability mudpit, since the visitor has no visible cue as to what a focused link will do, or where it will go.\n\nThe simple answer is to restyle the link so that it appears on the screen when the hidden link receives focus. The anchor\u2019s :focus pseudo-class is a logical hook to use, and with the following style repositions the link onscreen when it receives the focus:\n\na.helper:focus, a.helper.focus {\n\ttop: 0;\n\tleft: 0;\n}\n\nThis technique is useful for hiding skip links, and options you want screen-reader and keyboard users to use, but don\u2019t want cluttering up the page. Unfortunately Internet Explorer 6 and 7 don\u2019t support the focus pseudo-class, which is why there\u2019s a second CSS selector a.helper.focus so we can use some JavaScript to help out. When the page loads, we look for all links that have a class of helper and add in onfocus and onblur event handlers:\n\nif (anchor.className == \"helper\") {\n\tanchor.onfocus = function() {\n\t\tthis.className = 'helper focus';\n\t}\n\tanchor.onblur = function() {\n\t\tthis.className = 'helper';\n\t}\n}\n\nSince we are using JavaScript to cover up for deficiencies in Internet Explorer, it makes sense to use JavaScript initially to place the links off-screen. That way an Internet Explorer user with JavaScript disabled can still use the skip link functionality.\n\nIt is vital that the number of links rendered in this way is kept to a minimum. Every link you offer needs to be tabbed through, and gets read out in a screen reader. Offer these off-screen links that directly benefit these types of visitor.\n\nAndy Clarke and Kimberly Blessing use a similar technique in the Web Standards Project\u2018s latest design, but their technique involves hiding the skip link in plain sight and making it visible when it receives focus. Navigate the page using just the tab key to see the accessibility-related links appear when they receive focus.\n\nThis technique is also a good way of hiding image replaced text. That way the screen-readers still get the actual text, and the website still gets its designed look.\n\nWhich way?\n\nIf the links are not meant to be reachable until a certain event has occurred, then the display: none technique is the preferred approach. If you want the links accessible but out of the way until they receive focus, then the off-screen positioning (or Andy\u2019s hiding in plain sight technique) is the way to go.", "year": "2006", "author": "Mike Davies", "author_slug": "mikedavies", "published": "2006-12-05T00:00:00+00:00", "url": "https://24ways.org/2006/accessible-dynamic-links/", "topic": "ux"} {"rowid": 322, "title": "Introduction to Scriptaculous Effects", "contents": "Gather around kids, because this year, much like in that James Bond movie with Denise Richards, Christmas is coming early\u2026 in the shape of scrumptuous smooth javascript driven effects at your every whim.\n\nNow what I\u2019m going to do, is take things down a notch. Which is to say, you don\u2019t need to know much beyond how to open a text file and edit it to follow this article. Personally, I for instance can\u2019t code to save my life.\n\nWell, strictly speaking, that\u2019s not entirely true. If my life was on the line, and the code needed was really simple and I wasn\u2019t under any time constraints, then yeah maybe I could hack my way out of it\n\nBut my point is this: I\u2019m not a programmer in the traditional sense of the word. In fact, what I do best, is scrounge code off of other people, take it apart and then put it back together with duct tape, chewing gum and dumb blind luck.\n\nNo, don\u2019t run! That happens to be a good thing in this case. You see, we\u2019re going to be implementing some really snazzy effects (which are considerably more relevant than most people are willing to admit) on your site, and we\u2019re going to do it with the aid of Thomas Fuchs\u2019 amazing Script.aculo.us library. And it will be like stealing candy from a child.\n\nWhat Are We Doing?\n\nI\u2019m going to show you the very basics of implementing the Script.aculo.us javascript library\u2019s Combination Effects. These allow you to fade elements on your site in or out, slide them up and down and so on.\n\nWhy Use Effects at All?\n\nBefore get started though, let me just take a moment to explain how I came to see smooth transitions as something more than smoke and mirror-like effects included for with little more motive than to dazzle and make parents go \u2018uuh, snazzy\u2019.\n\nEarlier this year, I had the good fortune of meeting the kind, gentle and quite knowledgable Matt Webb at a conference here in Copenhagen where we were both speaking (though I will be the first to admit my little talk on Open Source Design was vastly inferior to Matt\u2019s talk). Matt held a talk called Fixing Broken Windows (based on the Broken Windows theory), which really made an impression on me, and which I have since then referred back to several times.\n\nYou can listen to it yourself, as it\u2019s available from Archive.org. Though since Matt\u2019s session uses many visual examples, you\u2019ll have to rely on your imagination for some of the examples he runs through during it. Also, I think it looses audio for a few seconds every once in a while.\n\nAnyway, one of the things Matt talked a lot about, was how our eyes are wired to react to movement. The world doesn\u2019t flickr. It doesn\u2019t disappear or suddenly change and force us to look for the change. Things move smoothly in the real world. They do not pop up.\n\nHow it Works\n\nOnce the necessary files have been included, you trigger an effect by pointing it at the ID of an element. Simple as that.\n\nImplementing the Effects\n\nSo now you know why I believe these effects have a place in your site, and that\u2019s half the battle. Because you see, actually getting these effects up and running, is deceptively simple.\n\nFirst, go and download the latest version of the library (as of this writing, it\u2019s version 1.5 rc5). Unzip itand open it up.\n\nNow we\u2019re going to bypass the instructions in the readme file. Script.aculo.us can do a bunch of quite advanced things, but all we really want from it is its effects. And by sidestepping the rest of the features, we can shave off roughly 80KB of unnecessary javascript, which is well worth it if you ask me.\n\nAs with Drew\u2019s article on Easy Ajax with Prototype, script.aculo.us also uses the Prototype framework by Sam Stephenson. But contrary to Drew\u2019s article, you don\u2019t have to download Prototype, as a version comes bundled with script.aculo.us (though feel free to upgrade to the latest version if you so please).\n\nSo in the unzipped folder, containing the script.aculo.us files and folder, go into \u2018lib\u2019 and grab the \u2018prototype.js\u2019 file. Move it to whereever you want to store the javascript files. Then fetch the \u2018effects.js\u2019 file from the \u2018src\u2019 folder and put it in the same place.\n\nTo make things even easier for you to get this up and running, I have prepared a small javascript snippet which does some checking to see what you\u2019re trying to do. The script.aculo.us effects are all either \u2018turn this off\u2019 or \u2018turn this on\u2019. What this snippet does, is check to see what state the target currently has (is it on or off?) and then use the necessary effect.\n\nYou can either skip to the end and download the example code, or copy and paste this code into a file manually (I\u2019ll refer to that file as combo.js):\n\nEffect.OpenUp = function(element) {\n element = $(element);\n new Effect.BlindDown(element, arguments[1] || {});\n }\n\n Effect.CloseDown = function(element) {\n element = $(element);\n new Effect.BlindUp(element, arguments[1] || {});\n }\n\n Effect.Combo = function(element) {\n element = $(element);\n if(element.style.display == 'none') { \n new Effect.OpenUp(element, arguments[1] || {}); \n }else { \n new Effect.CloseDown(element, arguments[1] || {}); \n }\n }\n\nCurrently, this code uses the BlindUp and BlindDown code, which I personally like, but there\u2019s nothing wrong with you changing the effect-type into one of the other effects available.\n\nNow, include the three files in the header of your code, like so:\n\n\n\n\n\nNow insert the element you want to use the effect on, like so:\n\n
Lorem ipsum dolor sit amet.
\n\nThe above element will start out invisible, and when triggered will be revealed. If you want it to start visible, simply remove the style parameter.\n\nAnd now for the trigger \n\nClick Here\n\nAnd that, is pretty much it. Clicking the link should unfold the DIV targeted by the effect, in this case \u2018content\u2019.\n\nEffect Options\n\nNow, it gets a bit long-haired though. The documentation for script.aculo.us is next to non-existing, and because of that you\u2019ll have to do some digging yourself to appreciate the full potentialof these effects.\n\nFirst of all, what kind of effects are available? Well you can go to the demo page and check them out, or you can open the \u2018effects.js\u2019 file and have a look around, something I recommend doing regardlessly, to gain an overview of what exactly you\u2019re dealing with.\n\nIf you dissect it for long enough, you can even distill some of the options available for the various effects. In the case of the BlindUp and BlindDown effect, which we\u2019re using in our example (as triggered from combo.js), one of the things that would be interesting to play with would be the duration of the effect. If it\u2019s too long, it will feel slow and unresponsive. Too fast and it will be imperceptible.\n\nYou set the options like so:\n\nClick Here\n\nThe change from the previous link being the inclusion of , {duration: .2}. In this case, I have lowered the duration to 0.2 second, to really make it feel snappy.\n\nYou can also go all-out and turn on all the bells and whistles of the Blind effect like so (slowed down to a duration of three seconds so you can see what\u2019s going on):\n\nClick Here\n\nConclusion\n\nAnd that\u2019s pretty much it. The rest is a matter of getting to know the rest of the effects and their options as well as finding out just when and where to use them. Remember the ancient Chinese saying: Less is more.\n\nDownload Example\n\nI have prepared a very basic example, which you can download and use as a reference point.", "year": "2005", "author": "Michael Heilemann", "author_slug": "michaelheilemann", "published": "2005-12-12T00:00:00+00:00", "url": "https://24ways.org/2005/introduction-to-scriptaculous-effects/", "topic": "code"} {"rowid": 10, "title": "Home Kanban for Domestic Bliss", "contents": "My wife is an architect. I\u2019m a leader of big technical teams these days, but for many years after I was a dev I was a project/program manager. Our friends and family used to watch Grand Designs and think that we would make the ideal team \u2014 she could design, I could manage the project of building or converting whatever dream home we wanted.\n\nThen we bought a house.\n\nA Victorian terrace in the north-east of England that needed, well, a fair bit of work. The big decisions were actually pretty easy: yes, we should knock through a double doorway from the dining room to the lounge; yes, we should strip out everything from the utility room and redo it; yes, we should roll back the hideous carpet in the bedrooms upstairs and see if we could restore the original wood flooring.\n\nThose could be managed like a project.\n\nWhat couldn\u2019t be was all the other stuff. Incremental improvements are harder to schedule, and in a house that\u2019s over a hundred years old you never know what you\u2019re going to find when you clear away some tiles, or pull up the carpets, or even just spring-clean the kitchen (\u201cErm, hon? The paint seems to be coming off. Actually, so does the plaster\u2026\u201d). A bit like going in to fix bugs in code or upgrade a machine \u2014 sometimes you end up quite far down the rabbit hole.\n\nAnd so, as we tried to fit in those improvements in our evenings and weekends, we found ourselves disagreeing. Arguing, even. We were both trying to do the right thing (make the house better) but since we were fitting it in where we could, we often didn\u2019t get to talk and agree in detail what was needed (exactly how to make the house better). And it\u2019s really frustrating when you stay up late doing something, just to find that your other half didn\u2019t mean that they meant this instead, and so your effort was wasted.\n\nThen I saw this tweet from my friend and colleague Jamie Arnold, who was using the same kanban board approach at home as we had instituted at the UK Government Digital Service to manage our portfolio.\n\nMrs Arnold embraces Kanban wall at home. Disagreements about work in progress and priority significantly reduced.. ;) pic.twitter.com/407brMCH\u2014 Jamie Arnold (@itsallgonewrong) October 27, 2012\n\nAnd despite Jamie\u2019s questionable taste in fancy dress outfits (look closely at that board), he is a proper genius when it comes to processes and particularly agile ones. So I followed his example and instituted a home kanban board.\n\nWhat is this kanban of which you speak?\n\nKanban boards are an artefact from lean manufacturing \u2014 basically a visualisation of a production process. They are used to show you where your bottlenecks are, or where one part of the process is producing components faster than another part of the process can cope. Identifying the bottlenecks leads you to set work in progress (WIP) limits, so that you get an overall more efficient system.\n\nIncreasingly kanban is used as an agile software development approach, too, especially where support work (like fixing bugs) needs to be balanced with incremental enhancement (like adding new features).\n\nI\u2019m a big advocate of kanban when you have a system that needs to be maintained and improved by the same team at the same time. Rather than the sprint-based approach of scrum (where the next sprint\u2019s stories or features to be delivered are agreed up front), kanban lets individuals deal with incidents or problems that need investigation and bug fixing when urgent and important. Then, when someone has capacity, they can just go to the board and pull down the next feature to develop or test.\n\nSo, how did we use it?\n\nOne of the key tenets of kanban is that you visualise your workflow, so we put together a whiteboard with columns: Icebox; To Do Next; In Process; Done; and also a section called Blocked. Then, for each thing that needed to happen in the house, we put it on a Post-it note and initially chucked them all in the Icebox \u2014 a collection with no priority assigned yet.\n\nEach week we looked at the Icebox and pulled out a set of things that we felt should be done next. This was pulled into the To Do Next column, and then each time either of us had some time, we could just pull a new thing over into the In Process column. We agreed to review at the end of each week and move things to Done together, and to talk about whether this kanban approach was working for us or not.\n\nWe quickly learned for ourselves why kanban has WIP limits as a key tenet \u2014 it\u2019s tempting to pull everything into the To Do Next column, but that\u2019s unrealistic. And trying to do more than one or two things each at a given time isn\u2019t terribly productive owing to the cost of task switching. So we tend to limit our To Do Next to about seven items, and our In Process to about four (a max of two each, basically).\n\nWe use the Blocked column when something can\u2019t be completed \u2014 perhaps we can\u2019t fix something because we discovered we don\u2019t have the required tools or supplies, or if we\u2019re waiting for a call back from a plumber. But it\u2019s nice to put it to one side, knowing that it won\u2019t be forgotten.\n\nWhat helped the most?\n\nIt wasn\u2019t so much the visualisation that helped us to see what we needed to do, but the conversation that happened when we were agreeing priorities, moving them to In Process and then on to Done made the biggest difference. Getting clear on the order of importance really is invaluable \u2014 as is getting clear on what Done really means!\n\nThe Blocked column is also great, as it helps us keep track of things we need to do outside the house to make sure we can make progress. We also found it really helpful to examine the process itself and figure out whether it was working for us. For instance, one thing we realised is it\u2019s worth tracking some regular tasks that need time invested in them (like taking recycling that isn\u2019t picked up to the recycling centre) and these used to cycle around and around. So they were moved to Done as part of our weekly review, but then immediately put back in the Icebox to float back to the top again at a relevant time.\n\nBut the best thing of all? That moment where we get to mark something as done! It\u2019s immensely satisfying to review at the end of the week and have a physical marker of the progress you\u2019ve made.\n\nAll in all, a home kanban board turned out to be a very effective way to pull tasks through stages rather than always trying to plan them out in advance, and definitely made collaboration on our home tasks significantly smoother. Give it a try!", "year": "2013", "author": "Meri Williams", "author_slug": "meriwilliams", "published": "2013-12-14T00:00:00+00:00", "url": "https://24ways.org/2013/home-kanban-for-domestic-bliss/", "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": 312, "title": "Preparing to Be Badass Next Year", "contents": "Once we\u2019ve eaten our way through the holiday season, people will start to think about new year\u2019s resolutions. We tend to focus on things that we want to change\u2026 and often things that we don\u2019t like about ourselves to \u201cfix\u201d. We set rules for ourselves, or try to start new habits or stop bad ones. We focus in on things we will or won\u2019t do. \nFor many of us the list of things we \u201cought\u201d to be spending time on is just plain overwhelming \u2013 family, charity/community, career, money, health, relationships, personal development. \nIt\u2019s kinda scary even just listing it out, isn\u2019t it? I want to encourage you to think differently about next year.\nThe ever-brilliant Kathy Sierra articulates a better approach really well when talking about the attitude we should have to building great products. She tells us to think not about what the user will do with our product, but about what they are trying to achieve in the real world and how our product helps them to be badass1.\nWhen we help the user be badass, then we are really making a difference. \nI suppose this is one way of saying: focus not on what you will do, focus on what it will help you achieve. How will it help you be awesome?\nIn what ways do you want to be more badass next year?\nA professional lens\nThough of course you might want to focus in on health or family or charity or community or another area next year, many people will want to become more badass in their chosen career. \nSo let\u2019s talk about a scaffold to help you figure out your professional / career development next year. \nFirst up, an assumption: everyone wants to be awesome. Nobody gets up in the morning aiming to be crap at their job. Nobody thinks to themselves \u201cToday I am aiming for just south of mediocre, and if I can mess up everybody else\u2019s ability to do good work then that will be just perfect2\u201d. \nErgo, you want to be awesome. So what does awesome look like? \nDanger!\nThe big trap that people fall into when think about their professional development is to immediately focus on the things that they aren\u2019t good at. When you ask people \u201cwhat do you want to work on getting better at next year?\u201d they frequently gravitate to the things that they believe they are bad at. \nWhy is this a trap? Because if you focus all your time and energy on improving the areas that you suck at, you are going to end up middling at everything. Going from bad \u2192 mediocre at a given skill / behaviour takes a bunch of time and energy. So if you spend all your time going from bad \u2192 mediocre at things, what do you think you end up? That\u2019s right, mediocre. \nMediocrity is not a great career goal, kids. \nWhat do you already rock at?\nThe much better investment of time and energy is to go from good \u2192 awesome. It often takes the same amount of relative time and energy, but wow the end result is better! So first, ask yourself and those who know you well what you are already pretty damn good at. Combat imposter syndrome by asking others. \nThen figure out how to double down on those things. What does brilliant look like for a given skill? What\u2019s the knowledge or practice that you need to level yourself up even further in that thing?\nBut what if I really really suck?\nAdmittedly, sometimes something you suck at really is holding you back. But it\u2019s important to separate out weaknesses (just something you suck at) from controlling weaknesses (something you suck at that actually matters for your chosen career). \nIf skill x is just not an important thing for you to be good at, you may never need to care that you aren\u2019t good at it. If your current role or the one you aspire to next really really requires you to be great at x, then it\u2019s worth investing your time and energy (and possibly money too) getting better at it.\nSo when you look at the things that you aren\u2019t good at, which of those are actually essential for success?\nThe right ratio\nA good rule of thumb is to pick three things you are already good at to work on becoming awesome at and limit yourself to one weakness that you are trying to improve on. That way you are making sure that you get to awesome in areas where you already have an advantage, and limit the amount of time you are spending on going from bad \u2192 mediocre. \nLevelling up learning\nSo once you\u2019ve figured out your areas you want to focus on next year, what do you actually decide to do? \nMost of all, you should try to design your day-to-day work in a way that it is also an effective learning experience. This means making sure you have a good feedback loop \u2013 you get to try something, see if it works, learn from it, rinse and repeat. \nIt\u2019s also about balance: you want to be challenged enough for work to be interesting, without it being so hard it\u2019s frustrating. You want to do similar / the same things often enough that you get to learn and improve, without it being so repetitive that it\u2019s boring. \nContinuously getting better at things you are already good at is actually both easier and harder than it sounds. The advantage is that it\u2019s pretty easy to add the feedback loop to make sure that you are improving; the disadvantage is that you\u2019re already good at these skills so you could easily just \u201cdo\u201d without ever stopping to reflect and improve. Build in time for personal retrospectives (\u201cWhat went well? What didn\u2019t? What one thing will I choose to change next time?\u201d) and find a way of getting feedback from outside sources as well. \nAs for the new skills, it\u2019s worth knowing that skill development follows a particular pattern:\n\nWe all start out unconsciously incompetent (we don\u2019t know what to do and if we tried we\u2019d unwittingly get it wrong), progress on to conscious incompetence (we now know we\u2019re doing it wrong) then conscious competence (we\u2019re doing it right but wow it takes effort and attention) and eventually get to unconscious competence (automatically getting it right). \nYour past experiences and knowledge might let you move faster through these stages, but no one gets to skip them. Invest the time and remember you need the feedback loop to really improve. \nWhat about keeping up?\nEverything changes very fast in our industry. We need to invest in not falling behind, in keeping on top of what great looks like. There are a bunch of ways to do this, from reading blog posts, following links on Twitter, reading books to attending conferences or workshops, or just finding time to build things in new ways or with new technologies. \nWhich will work best for you depends on how you best learn. Do you prefer to swallow a book? Do you learn most by building or experimenting? \nWhatever your learning style though, remember that there are three real needs:\n\nScan the landscape (what\u2019s changing, does it matter)\nGain the knowledge or skills (get the detail)\nApply the knowledge or skills (use it in reality)\n\nWhen you remember that you need all three of these things it can help you get more of what you do. \nFor me personally, I use a combination of conferences and blogs / Twitter to scan the landscape. Half of what I want out of a conference is just a list of things to have on my radar that might become important. I then pick a couple of things to go read up on more (I personally learn most effectively by swallowing a book or spec or similar). And then I pick one thing at a time to actually apply in real life, to embed the skill / knowledge. \nIn summary\n\nAim to be awesome (mediocrity is not a career goal).\nFigure out what you already rock at.\nOnly care about stuff you suck at that matters for your career.\nPick three things to go from good \u2192 awesome and one thing to go from bad \u2192 mediocre (or mediocre \u2192 good) this year.\nDesign learning into your daily work.\nScan the landscape, learn new stuff, apply it for real. \nBe badass!\n\n\n\n\n\nShe wrote a whole book about it. You should read it: Badass: Making Users Awesome\u00a0\u21a9\n\n\nBefore you argue too vehemently: I suppose some antisocial sociopathic bastards do exist. Identify them, and then RUN AWAY FAST AS YOU CAN #realtalk\u00a0\u21a9", "year": "2016", "author": "Meri Williams", "author_slug": "meriwilliams", "published": "2016-12-22T00:00:00+00:00", "url": "https://24ways.org/2016/preparing-to-be-badass-next-year/", "topic": "business"} {"rowid": 261, "title": "Surviving\u2014and Thriving\u2014as a Remote Worker", "contents": "Remote work is hot right now. Many people even say that remote work is the future. Why should a company limit itself to hiring from a specific geographic location when there\u2019s an entire world of talent out there?\nI\u2019ve been working remotely, full-time, for five and a half years. I\u2019ve reached the point where I can\u2019t even fathom working in an office. The idea of having to wake up at a specific time and commute into an office, work for eight hours, and then commute home, feels weirdly anachronistic. I\u2019ve grown attached to my current level of freedom and flexibility.\nHowever, it took me a lot of trial and error to reach success as a remote worker \u2014 and sometimes even now, I slip up. Working remotely requires a great amount of discipline, independence, and communication. It can feel isolating, especially if you lean towards the more extroverted side of the social spectrum. Remote working isn\u2019t for everyone, but most people, with enough effort, can make it work \u2014 or even thrive. Here\u2019s what I\u2019ve learned in over five years of working remotely.\nExperiment with your environment\nAs a remote worker, you have almost unprecedented control of your environment. You can often control the specific desk and chair you use, how you accessorize your home office space \u2014 whether that\u2019s a dedicated office, a corner of your bedroom, or your kitchen table. (Ideally, not your couch\u2026 but I\u2019ve been there.) Hate fluorescent lights? Change your lightbulbs. Cover your work area in potted plants. Put up blackout curtains and work in the dark like a vampire. Whatever makes you feel most comfortable and productive, and doesn\u2019t completely destroy your eyesight.\nWorking remotely doesn\u2019t always mean working from home. If you don\u2019t have a specific reason you need to work from home (like specialized equipment), try working from other environments (which is especially helpful it you have roommates, or children). Cafes are the quintessential remote worker hotspot, but don\u2019t just limit yourself to your favorite local haunt. More cities worldwide are embracing co-working spaces, where you can rent either a roaming spot or a dedicated desk. If you\u2019re a social person, this is a great way to build community in your work environment. Most have phone rooms, so you can still take calls.\nCo-working spaces can be expensive, and not everyone has either the extra income, or work-provided stipend, to work from one. Local libraries are also a great work location. They\u2019re quiet, usually have free wi-fi, and you have the added bonus of being able to check out books after work instead of, ahem, spending too much money on Kindle books. (I know most libraries let you check out ebooks, but reader, I am impulsive and impatient person. When I want a book now, I mean now.) \nJust be polite \u2014 make sure your headphones don\u2019t leak, and don\u2019t work from a library if you have a day full of calls.\nRemember, too, that you don\u2019t have to stay in the same spot all day. It\u2019s okay to go out for lunch and then resume work from a different location. If you find yourself getting restless, take a walk. Wash some dishes while you mull through a problem. Don\u2019t force yourself to sit at your desk for eight hours if that doesn\u2019t work for you.\nSet boundaries\nIf you\u2019re a workaholic, working remotely can be a challenge. It\u2019s incredibly easy to just\u2026 work. All the time. My work computer is almost always with me. If I remember at 11pm that I wanted to do something, there\u2019s nothing but my own willpower keeping me from opening up my laptop and working until 2am. Some people are naturally disciplined. Some have discipline instilled in them as children. And then some, like me, are undisciplined disasters that realize as adults that wow, I guess it\u2019s time to figure this out, eh?\nLearning how to set boundaries is one of the most important lessons I\u2019ve learned working remotely. (And honestly, it\u2019s something I still struggle with). \nFor a long time, I had a bad habit of waking up, checking my phone for new Slack messages, seeing something I need to react to, and then rolling over to my couch with my computer. Suddenly, it\u2019s noon, I\u2019m unwashed, unfed, starting to get a headache, and wondering why suddenly I hate all of my coworkers. Even when I finally tear myself from my computer to shower, get dressed, and eat, the damage is done. The rest of my day is pretty much shot.\nI recently had a conversation with a coworker, in which she remarked that she used to fill her empty time with work. Wake up? Scroll through Slack and email before getting out of bed. Waiting in line for lunch? Check work. Hanging out on her couch in the evening? You get the drift. She was only able to break the habit after taking a three month sabbatical, where she had no contact with work the entire time.\nI too had just returned from my own sabbatical. I took her advice, and no longer have work Slack on my phone, unless I need it for an event. After the event, I delete it. I also find it too easy to fill empty time with work. Now, I might wake up and procrastinate by scrolling through other apps, but I can\u2019t get sucked into work before I\u2019m even dressed. I\u2019ve gotten pretty good at forbidding myself from working until I\u2019m ready, but building any new habit requires intentionality. \nSomething else I experimented with for a while was creating a separate account on my computer for social tasks, so if I wanted to hang out on my computer in the evening, I wouldn\u2019t get distracted by work. It worked exceptionally well. The only problems I encountered were technical, like app licensing and some of my work proxy configurations. I\u2019ve heard other coworkers have figured out ways to work through these technical issues, so I\u2019m hoping to give it another try soon.\nYou might noticed that a lot of these ideas are just hacks for making myself not work outside of my designated work times. It\u2019s true! If you\u2019re a more disciplined person, you might not need any of these coping mechanisms. If you\u2019re struggling, finding ways to subvert your own bad habits can be the difference between thriving or burning out.\nCreate intentional transition time\nI know it\u2019s a stereotype that people who work from home stay in their pajamas all day, but\u2026 sometimes, it\u2019s very easy to do. I\u2019ve found that in order to reach peak focus, I need to create intentional transition time. \nThe most obvious step is changing into different clothing than I woke up in. Ideally, this means getting dressed in real human clothing. I might decide that it\u2019s cold and gross out and I want to work in joggers and a hoody all day, but first, I need to change out of my pajamas, put on a bra, and then succumb to the lure of comfort. \nI\u2019ve found it helpful to take similar steps at the end of my day. If I\u2019ve spent the day working from home, I try to end my day with something that occupies my body, while letting my mind unwind. Often, this is doing some light cleaning or dinner prep. If I try to go straight into another mentally heavy task without allowing myself this transition time, I find it hard to context switch. \nThis is another reason working from outside your home is advantageous. Commutes, even if it\u2019s a ten minute walk down the road, are great transition time. Lunch is a great transition time. You can decompress between tasks by going out for lunch, or cooking and eating lunch in your kitchen \u2014 not next to your computer. \nEmbrace async\nIf you\u2019re used to working in an office, you\u2019ve probably gotten pretty used to being able to pop over to a colleague\u2019s desk if you need to ask a question. They\u2019re pretty much forced to engage with you at that point. When you\u2019re working remotely, your coworkers might not be in the same timezone as you. They might take an hour to finish up a task before responding to you, or you might not get an answer for your entire day because dangit Gary\u2019s in Australia and it\u2019s 3am there right now. \nFor many remote workers, that\u2019s part of the package. When you\u2019re not co-located, you have to build up some patience and tolerance around waiting. You need to intentionally plan extra time into your schedule for waiting on answers.\nAsynchronous communication is great. Not everyone can be present for every meeting or office conversation \u2014 and the same goes for working remotely. However, when you\u2019re remote, you can read through your intranet messages later or scroll back a couple hours in Slack. My company has a bunch of internal blogs (\u201cp2s\u201d) where we record major decisions and hold asynchronous conversations. I feel like even if I missed a meeting, or something big happened while I was asleep, I can catch up later. We have a phrase \u2014 \u201cp2 or it didn\u2019t happen.\u201d\nWorking remotely has made me a better communicator largely because I\u2019ve gotten into the habit of making written updates. I\u2019ve also trained myself to wait before responding, which allows me to distance myself from what could potentially be an emotional reaction. (On the internet, no one can see you making that face.) Having the added space that comes from not being in the same physical location with somebody else creates an opportunity to rein myself in and take the time to craft an appropriate response, without having the pressure of needing to reply right meow. Lean into it!\n(That said, if you\u2019re stuck, sometimes the best course of action is to hop on a video call with someone and hash out the details. Use the tools most appropriate for the problem. They invented Zoom for a reason.)\nSeek out social opportunities\nEven introverts can feel lonely or isolated. When you work remotely, there isn\u2019t a built-in community you\u2019re surrounded by every day. You have to intentionally seek out social opportunities that an office would normally provide.\nI have a couple private Slack channels where I can joke around with work friends. Having that kind of safe space to socialize helps me feel less alone. (And, if the channels get too noisy, I can mute them for a couple hours.)\nEvery now and then, I\u2019ll also hop on a video call with some work friends and just hang out for a little while. It feels great to actually see someone laugh.\nIf you work from a co-working space, that space likely has events. My co-working space hosts social hours, holiday parties, and sometimes even lunch-and-learns. These events are great opportunities for making new friends and forging professional connections outside of work. \nIf you don\u2019t have access to a co-working space, your town or city likely has meetups. Create a Meetup.com account and search for something that piques your interest. If you\u2019ve been stuck inside your house for days, heads-down on a hard deadline, celebrate by getting out of the house. Get coffee or drinks with friends. See a show. Go to a religious service. Take a cooking class. Try yoga. Find excuses to be around someone other than your cats. When you can\u2019t fall back on your work to provide community, you need to build your own.\n\nThese are tips that I\u2019ve found help me, but not everyone works the same way. Remember that it\u2019s okay to experiment \u2014 just because you\u2019ve worked one way, doesn\u2019t mean that\u2019s the best way for you. Check in with yourself every now and then. Are you happy with your work environment? Are you feeling lonely, down, or exhausted? Try switching up your routine for a couple weeks and jot down how you feel at the end of each day. Look for patterns. You deserve to have a comfortable and productive work environment!\nHope to see you all online soon \ud83d\ude4c", "year": "2018", "author": "Mel Choyce", "author_slug": "melchoyce", "published": "2018-12-09T00:00:00+00:00", "url": "https://24ways.org/2018/thriving-as-a-remote-worker/", "topic": "process"} {"rowid": 67, "title": "What I Learned about Product Design This Year", "contents": "2015 was a humbling year for me. In September of 2014, I joined a tiny but established startup called SproutVideo as their third employee and first designer. The role interests me because it affords the opportunity to see how design can grow a solid product with a loyal user-base into something even better. \nThe work I do now could also have a real impact on the brand and user experience of our product for years to come, which is a thrilling prospect in an industry where much of what I do feels small and temporary. I got in on the ground floor of something special: a small, dedicated, useful company that cares deeply about making video hosting effortless and rewarding for our users.\nI had (and still have) grand ideas for what thoughtful design can do for a product, and the smaller-scale product design work I\u2019ve done or helped manage over the past few years gave me enough eager confidence to dive in head first. Readers who have experience redesigning complex existing products probably have a knowing smirk on their face right now. As I said, it\u2019s been humbling. A year of focused product design, especially on the scale we are trying to achieve with our small team at SproutVideo, has taught me more than any projects in recent memory. I\u2019d like to share a few of those lessons.\nProduct design is very different from marketing design\nThe majority of my recent work leading up to SproutVideo has been in marketing design. These projects are so fun because their aim is to communicate the value of the product in a compelling and memorable way. In order to achieve this goal, I spent a lot of time thinking about content strategy, responsive design, and how to create striking visuals that tell a story. These are all pursuits I love.\nProduct design is a different beast. When designing a homepage, I can employ powerful imagery, wild gradients, and somewhat-quirky fonts. When I began redesigning the SproutVideo product, I wanted to draw on all the beautiful assets I\u2019ve created for our marketing materials, but big gradients, textures, and display fonts made no sense in this new context.\nThat\u2019s because the product isn\u2019t about us, and it isn\u2019t about telling our story. Product design is about getting out of the way so people can do their job. The visual design is there to create a pleasant atmosphere for people to work in, and to help support the user experience. Learning to take \u201cus\u201d out of the equation took some work after years of creating gorgeous imagery and content for the sales-driven side of businesses.\nI\u2019ve learned it\u2019s very valuable to design both sides of the experience, because marketing and product design flex different muscles. If you\u2019re currently in an environment where the two are separate, consider switching teams in 2016. Designing for product when you\u2019ve mostly done marketing, or vice versa, will deepen your knowledge as a designer overall. You\u2019ll face new unexpected challenges, which is the only way to grow.\nProduct design can not start with what looks good on Dribbble\nI have an embarrassing confession: when I began the redesign, I had a secret goal of making something that would look gorgeous in my portfolio. I have a collection of product shots that I admire on Dribbble; examples of beautiful dashboards and widgets and UI elements that look good enough to frame. I wanted people to feel the same way about the final outcome of our redesign. Mistakenly, this was a factor in my initial work. I opened Photoshop and crafted pixel-perfect static buttons and form elements and color palettes that\u200a\u2014\u200awhen applied to our actual product\u200a\u2014\u200alooked like a toddler beauty pageant. It added up to a lot of unusable shininess, noise, and silliness.\nI was disappointed; these elements seemed so lovely in isolation, but in context, they felt tacky and overblown. I realized: I\u2019m not here to design the world\u2019s most beautiful drop down menu. Good design has nothing to do with ego, but in my experience designers are, at least a little bit, secret divas. I\u2019m no exception. I had to remind myself that I am not working in service of a bigger Dribbble following or to create the most Pinterest-ing work. My function is solely to serve the users\u200a\u2014\u200ato make life a little better for the good people who keep my company in business.\nThis meant letting go of pixel-level beauty to create something bigger and harder: a system of elements that work together in harmony in many contexts. The visual style exists to guide the users. When done well, it becomes a language that users understand, so when they encounter a new feature or have a new goal, they already feel comfortable navigating it. This meant stripping back my gorgeous animated menu into something that didn\u2019t detract from important neighboring content, and could easily fit in other parts of the app. In order to know what visual style would support the users, I had to take a wider view of the product as a whole.\nJust accept that designing a great product \u2013 like many worthwhile pursuits \u2013 is initially laborious and messy\nOnce I realized I couldn\u2019t start by creating the most Dribbble-worthy thing, I knew I\u2019d have to begin with the unglamorous, frustrating, but weirdly wonderful work of mapping out how the product\u2019s content could better be structured. Since we\u2019re redesigning an existing product, I assumed this would be fairly straightforward: the functionality was already in place, and my job was just to structure it in a more easily navigable way.\nI started by handing off a few wireframes of the key screens to the developer, and that\u2019s when the questions began rolling in: \u201cIf we move this content into a modal, how will it affect this similar action here?\u201d \u201cWhat happens if they don\u2019t add video tags, but they do add a description?\u201d \u201cWhat if the user has a title that is 500 characters long?\u201d \u201cWhat if they want their video to be private to some users, but accessible to others?\u201d.\nHow annoying (but really, fantastic) that people use our product in so many ways. Turns out, product design isn\u2019t about laying out elements in the most ideal scenario for the user that\u2019s most convenient for you. As product designers, we have to foresee every outcome, and anticipate every potential user need.\nWhich brings me to another annoying epiphany: if you want to do it well, and account for every user, product design is so much more snarly and tangled than you\u2019d expect going in. I began with a simple goal: to improve the experience on just one of our key product pages. However, every small change impacts every part of the product to some degree, and that impact has to be accounted for. Every decision is based on assumptions that have to be tested; I test my assumptions by observing users, talking to the team, wireframing, and prototyping. Many of my assumptions are wrong. There are days when it\u2019s incredibly frustrating, because an elegant solution for users with one goal will complicate life for users with another goal. It\u2019s vital to solve as many scenarios as possible, even though this is slow, sometimes mind-bending work.\nAs a side bonus, wireframing and prototyping every potential state in a product is tedious, but your developers will thank you for it. It\u2019s not their job to solve what happens when there\u2019s an empty state, error, or edge case. Showing you\u2019ve accounted for these scenarios will win a developer\u2019s respect; failing to do so will frustrate them.\nWhen you\u2019ve created and tested a system that supports user needs, it will be beautiful\nRemember what I said in the beginning about wanting to create a Dribbble-worthy product? When I stopped focusing on the visual details of the design (color, spacing, light and shadow, font choices) and focused instead on structuring the content to maximize usability and delight, a beautiful design began to emerge naturally.\nI began with grayscale, flat wireframes as a strategy to keep me from getting pulled into the visual style before the user experience was established. As I created a system of elements that worked in harmony, the visual style choices became obvious. Some buttons would need to be brighter and sit off the page to help the user spot important actions. Some elements would need line separators to create a hierarchy, where others could stand on their own as an emphasized piece of content. As the user experience took shape, the visual style emerged naturally to support it. The result is a product that feels beautiful to use, because I was thoughtful about the experience first.\n\nA big takeaway from this process has been that my assumptions will often be proven wrong. My assumptions about how to design a great product, and how users will interact with that product, have been tested and revised repeatedly. At SproutVideo we\u2019re about to undertake the biggest test of our work; we\u2019re going to launch a small part of the product redesign to our users. If I\u2019ve learned anything, it\u2019s that I will continue to be humbled by the ongoing effort of making the best product I can, which is a wonderful thing.\nNext year, I hope you all get to do work that takes you out of our comfort zone. Be regularly confounded and embarrassed by your wrong assumptions, learn from them, and come back and tell us what you learned in 2016.", "year": "2015", "author": "Meagan Fisher", "author_slug": "meaganfisher", "published": "2015-12-14T00:00:00+00:00", "url": "https://24ways.org/2015/what-i-learned-about-product-design-this-year/", "topic": "design"} {"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": 218, "title": "Put Yourself in a Corner", "contents": "Some backstory, and a shameful confession\n\nFor the first couple years of high school I was one of those jerks who made only the minimal required effort in school. Strangely enough, how badly I behaved in a class was always in direct proportion to how skilled I was in the subject matter. In the subjects where I was confident that I could pass without trying too hard, I would give myself added freedom to goof off in class.\n\nBecause I was a closeted lit-nerd, I was most skilled in English class. I\u2019d devour and annotate required reading over the weekend, I knew my biblical and mythological allusions up and down, and I could give you a postmodern interpretation of a text like nobody\u2019s business. But in class, I\u2019d sit in the back and gossip with my friends, nap, or scribble patterns in the margins of my textbooks. I was nonchalant during discussion, I pretended not to listen during lectures. I secretly knew my stuff, so I did well enough on tests, quizzes, and essays. But I acted like an ass, and wasn\u2019t getting the most I could out of my education.\n\nThe day of humiliation, but also epiphany\n\nOne day in Ms. Kaney\u2019s AP English Lit class, I was sitting in the back doodling. An earbud was dangling under my sweater hood, attached to the CD player (remember those?) sitting in my desk. Because of this auditory distraction, the first time Ms. Kaney called my name, I barely noticed. I definitely heard her the second time, when she didn\u2019t call my name so much as roar it. I can still remember her five feet frame stomping across the room and grabbing an empty desk. It screamed across the worn tile as she slammed it next to hers. She said, \u201cThis is where you sit now.\u201d My face gets hot just thinking about it.\n\nI gathered my things, including the CD player (which was now impossible to conceal), and made my way up to the newly appointed Seat of Shame. There I sat, with my back to the class, eye-to-eye with Ms. Kaney. From my new vantage point I couldn\u2019t see my friends, or the clock, or the window. All I saw were Ms. Kaney\u2019s eyes, peering at me over her reading glasses while I worked. In addition to this punishment, I was told that from now on, not only would I participate in class discussions, but I would serve detention with her once a week until an undetermined point in the future.\n\nDuring these detentions, Ms. Kaney would give me new books to read, outside the curriculum, and added on to my normal homework. They ranged from classics to modern novels, and she read over my notes on each book. We\u2019d discuss them at length after class, and I grew to value not only our private discussions, but the ones in class as well. After a few weeks, there wasn\u2019t even a question of this being punishment. It was heaven, and I was more productive than ever.\n\nTo the point\n\nPlease excuse this sentimental story. It\u2019s not just about honoring a teacher who cared enough to change my life, it\u2019s really about sharing a lesson. The most valuable education Ms. Kaney gave me had nothing to do with literature. She taught me that I (and perhaps other people who share my special brand of crazy) need to be put in a corner to flourish. When we have physical and mental constraints applied, we accomplish our best work.\n\nFor those of you still reading, now seems like a good time to insert a pre-emptive word of mediation. Many of you, maybe all of you, are self-disciplined enough that you don\u2019t require the rigorous restrictions I use to maximize productivity. Also, I know many people who operate best in a stimulating and open environment. I would advise everyone to seek and execute techniques that work best for them. But, for those of you who share my inclination towards daydreams and digressions, perhaps you\u2019ll find something useful in the advice to follow.\n\nIn which I pretend to be Special Agent Olivia Dunham\n\nNow that I\u2019m an adult, and no longer have Ms. Kaney to reign me in, I have to find ways to put myself in the corner. By rejecting distraction and shaping an environment designed for intense focus, I\u2019m able to achieve improved productivity.\n\nLately I\u2019ve been obsessed with the TV show Fringe, a sci-fi series about an FBI agent and her team of genius scientists who save the world (no, YOU\u2019RE a nerd). There\u2019s a scene in the show where the primary character has to delve into her subconscious to do extraordinary things, and she accomplishes this by immersing herself in a sensory deprivation tank. The premise is this: when enclosed in a space devoid of sound, smell, or light, she will enter a new plane of consciousness wherein she can tap into new levels of perception.\n\nThis might sound a little nuts, but to me this premise has some real-world application. When I am isolated from distraction, and limited to only the task at hand, I\u2019m able to be productive on a whole new level. Since I can\u2019t actually work in an airtight iron enclosure devoid of input, I find practical ways to create an interruption-free environment.\n\nSince I work from home, many of my methods for coping with distractions wouldn\u2019t be necessary for my office-bound counterpart. However for some of you 9-to-5-ers, the principles will still apply.\n\nConsider your visual input\n\nFirst, I have to limit my scope to the world I can (and need to) affect. In the largest sense, this means closing my curtains to the chaotic scene of traffic, birds, the post office, a convenience store, and generally lovely weather that waits outside my window. When the curtains are drawn and I\u2019m no longer surrounded by this view, my sphere is reduced to my desk, my TV, and my cat. Sometimes this step alone is enough to allow me to focus. \n\nBut, my visual input can be whittled down further still. For example, the desk where I usually keep my laptop is littered with twelve owl figurines, a globe, four books, a three-pound weight, and various nerdy paraphernalia (hard drives, Wacom tablets, unnecessary bluetooth accessories, and so on). It\u2019s not so much a desk as a dumping ground for wacky flea market finds and impulse technology buys. Therefore, in addition to this Official Desk, I have an adult version of Ms. Kaney\u2019s Seat of Shame. It\u2019s a rusty old student\u2019s desk I picked up at the Salvation Army, almost an exact replica of the model Ms. Kaney dragged across the classroom all those years ago. This tiny reproduction Seat of Shame is literally in a corner, where my only view is a blank wall. When I truly need to focus, this is where I take refuge, with only a notebook and a pencil (and occasionally an iPad).\n\nFind out what works for your ears\n\nEven from my limited sample size of two people, I know there are lots of different ways to cope with auditory distraction. I prefer silence when focused on independent work, and usually employ some form of a white noise generator. I\u2019ve yet to opt for the fancy \u2018real\u2019 white noise machines; instead, I use a desktop fan or our allergy filter machine. This is usually sufficient to block out the sounds of the dishwasher and the cat, which allows me to think only about the task of hand.\n\nMy boyfriend, the other half of my extensive survey, swears by another method. He calls it The Wall of Sound, and it\u2019s basically an intense blast of raucous music streamed directly into his head. The outcome of his technique is really the same as mine; he\u2019s blocking out unexpected auditory input. If you can handle the grating sounds of noisy music while working, I suggest you give The Wall of Sound a try.\n\nDon\u2019t count the minutes\n\nWhen I sat in the original Seat of Shame in lit class, I could no longer see the big classroom clock slowly ticking away the seconds until lunch. Without the marker of time, the class period often flew by. The same is true now when I work; the less aware of time I am, the less it feels like time is passing too quickly or slowly, and the more I can focus on the task (not how long it takes). \n\nNowadays, to assist in my effort to forget the passing of time, I sometimes put a sticky note over the clock on my monitor. If I\u2019m writing, I\u2019ll use an app like WriteRoom, which blocks out everything but a simple text editor. \n\nThere are situations when it\u2019s not advisable to completely lose track of time. If I\u2019m working on a project with an hourly rate and a tight scope, or if I need to be on time to a meeting or call, I don\u2019t want to lose myself in the expanse of the day. In these cases, I\u2019ll set an alarm that lets me know it\u2019s time to reign myself back in (or on some days, take a shower).\n\nPut yourself in a mental corner, too\n\nWhen Ms. Kaney took action and forced me to step up my game, she had the insight to not just change things physically, but to challenge me mentally as well. She assigned me reading material outside the normal coursework, then upped the pressure by requiring detailed reports of the material. While this additional stress was sometimes uncomfortable, it pushed me to work harder than I would have had there been less of a demand. Just as there can be freedom in the limitations of a distraction-free environment, I\u2019d argue there is liberty in added mental constraints as well.\n\nDeadlines as a constraint\n\nMuch has been written about the role of deadlines in the creative process, and they seem to serve different functions in different cases. I find that deadlines usually act as an important constraint and, without them, it would be nearly impossible for me to ever consider a project finished. There are usually limitless ways to improve upon the work I do and, if there\u2019s no imperative for me to be done at a certain point, I will revise ad infinitum. (Hence, the personal site redesign that will never end \u2013 Coming Soon, Forever!). But if I have a clear deadline in mind, there\u2019s a point when the obsessive tweaking has to stop. I reach a stage where I have to gather up the nerve to launch the thing.\n\nPutting the pro in procrastination\n\nSometimes I\u2019ve found that my tendency to procrastinate can help my productivity. (Ducks, as half the internet throws things at her.) I understand the reasons why procrastination can be harmful, and why it\u2019s usually a good idea to work diligently and evenly towards a goal. I try to divide my projects up in a practical way, and sometimes I even pull it off. But for those tasks where you work aimlessly and no focus comes, or you find that every other to-do item is more appealing, sometimes you\u2019re forced to bring it together at the last moment. And sometimes, this environment of stress is a formula for magic. Often when I\u2019m down to the wire and have no choice but to produce, my mind shifts towards a new level of clarity. There\u2019s no time to endlessly browse for inspiration, or experiment with convoluted solutions that lead nowhere.\n\nObviously a life lived perpetually on the edge of a deadline would be a rather stressful one, so it\u2019s not a state of being I\u2019d advocate for everyone, all the time. But every now and then, the work done when I\u2019m down to the wire is my best.\n\nKeep one toe outside your comfort zone\n\nWhen I\u2019m choosing new projects to take on, I often seek out work that involves an element of challenge. Whether it\u2019s a design problem that will require some creative thinking, or a coding project that lends itself to using new technology like HTML5, I find a manageable level of difficulty to be an added bonus. The tension that comes from learning a new skill or rethinking an old standby is a useful constraint, as it keeps the work interesting, and ensures that I continue learning.\n\nThere you have it\n\nWell, I think I\u2019ve spilled most of my crazy secrets for forcing my easily distracted brain to focus. As with everything we web workers do, there are an infinite number of ways to encourage productivity. I hope you\u2019ve found a few of these to be helpful, and please share your personal techniques in the comments. Have a happy and productive new year!", "year": "2010", "author": "Meagan Fisher", "author_slug": "meaganfisher", "published": "2010-12-20T00:00:00+00:00", "url": "https://24ways.org/2010/put-yourself-in-a-corner/", "topic": "process"} {"rowid": 250, "title": "Build up Your Leadership Toolbox", "contents": "Leadership. It can mean different things to different people and vary widely between companies. Leadership is more than just a job title. You won\u2019t wake up one day and magically be imbued with all you need to do a good job at leading. If we don\u2019t have a shared understanding of what a Good Leader looks like, how can we work on ourselves towards becoming one? How do you know if you even could be a leader? Can you be a leader without the title?\nWhat even is it?\nI got very frustrated way back in my days as a senior developer when I was given \u201cadvice\u201d about my leadership style; at the time I didn\u2019t have the words to describe the styles and ways in which I was leading to be able to push back. I heard these phrases a lot:\n\nyou need to step up\nyou need to take charge\nyou need to grab the bull by its horns\nyou need to have thicker skin\nyou need to just be more confident in your leading\nyou need to just make it happen\n\nI appreciate some people\u2019s intent was to help me, but honestly it did my head in. WAT?! What did any of this even mean. How exactly do you \u201cstep up\u201d and how are you evaluating what step I\u2019m on? I am confident, what does being even more confident help achieve with leading? Does that not lead you down the path of becoming an arrogant door knob? >___<\nWhile there is no One True Way to Lead, there is an overwhelming pattern of people in positions of leadership within tech industry being held by men. It felt a lot like what people were fundamentally telling me to do was to be more like an extroverted man. I was being asked to demonstrate more masculine associated qualities (#notallmen). I\u2019ll leave the gendered nature of leadership qualities as an exercise in googling for the reader.\nI\u2019ve never had a good manager and at the time had no one else to ask for help, so I turned to my trusted best friends. Books.\nI <3 books\nI refused to buy into that style of leadership as being the only accepted way to be. There had to be room for different kinds of people to be leaders and have different leadership styles.\nThere are three books that changed me forever in how I approach and think about leadership.\n\nPrimal leadership, by Daniel Goleman, Richard Boyatzis and Annie McKee\nQuiet, by Susan Cain\nDaring Greatly - How the Courage to be Vulnerable transforms the way we live, love, parent and Lead, by Bren\u00e9 Brown\n\nI recommend you read them. Ignore the slightly cheesy titles and trust me, just read them.\nPrimal leadership helped to give me the vocabulary and understanding I needed about the different styles of leadership there are, how and when to apply them.\nQuiet really helped me realise how much I was being undervalued and misunderstood in an extroverted world. If I\u2019d had managers or support from someone who valued introverts\u2019 strengths, things would\u2019ve been very different. I would\u2019ve had someone telling others to step down and shut up for a change rather than pushing on me to step up and talk louder over everyone else. It\u2019s OK to be different and needing different things like time to recharge or time to think before speaking. It also improved my ability to work alongside my more extroverted colleagues by giving me an understanding of their world so I could communicate my needs in a language they would get.\nBren\u00e9 Brown\u2019s book I am forever in debt to. Her work gave me the courage to stand up and be my own kind of leader. Even when no-one around me looked or sounded like me, I found my own voice.\nIt takes great courage to be vulnerable and open about what you can and can\u2019t do. Open about your mistakes. Vocalise what you don\u2019t know and asking for help. In some lights, these are seen as weaknesses and many have tried to use them against me, to pull me down and exclude me for talking about them. Dear reader, it did not work, they failed. The truth is, they are my greatest strengths. The privileges I have, I use for good as best and often as I can.\nJust like gender, leadership is not binary\nIf you google for what a leader is, you\u2019ll get many different answers. I personally think Bren\u00e9\u2019s version is the best as it is one that can apply to a wider range of people, irrespective of job title or function.\n\nI define a leader as anyone who takes responsibility for finding potential in people and processes, and who has the courage to develop that potential.\nBren\u00e9 Brown\n\nBeing a leader isn\u2019t about being the loudest in a room, having veto power, talking over people or ignoring everyone else\u2019s ideas. It\u2019s not about \u201ctelling people what to do\u201d. It\u2019s not about an elevated status that you\u2019re better than others. Nor is it about creating a hand wavey far away vision and forgetting to help support people in how to get there.\nBeing a Good Leader is about having a toolbox of leadership styles and skills to choose from depending on the situation. Knowing how and when to apply them is part of the challenge and difficulty in becoming good at it. It is something you will have to continuously work on, forever. There is no Done.\nLeaders are Made, they are not Born.\nBe flexible in your leadership style\n\nTypically, the best, most effective leaders act according to one or more of six distinct approaches to leadership and skillfully switch between the various styles depending on the situation.\n\nFrom the book, Primal Leadership, it gives a summary of 6 leadership styles which are:\n\nVisionary\nCoaching\nAffiliative\nDemocratic\nPacesetting\nCommanding\n\nVisionary, moves people toward a shared dream or future. When change requires a new vision or a clear direction is needed, using a visionary style of leadership helps communicate that picture. By learning how to effectively communicate a story you can help people to move in that direction and give them clarity on why they\u2019re doing what they\u2019re doing.\nCoaching, is about connecting what a person wants and helping to align that with organisation\u2019s goals. It\u2019s a balance of helping someone improve their performance to fulfil their role and their potential beyond.\nAffiliative, creates harmony by connecting people to each other and requires effective communication to aid facilitation of those connections. This style can be very impactful in healing rifts in a team or to help strengthen connections within and across teams. During stressful times having a positive and supportive connection to those around us really helps see us through those times.\nDemocratic, values people\u2019s input and gets commitment through participation. Taking this approach can help build buy-in or consensus and is a great way to get valuable input from people. The tricky part about this style, I find, is that when I gather and listen to everyone\u2019s input, that doesn\u2019t mean the end result is that I have to please everyone.\nThe next two, sadly, are the ones wielded far too often and have the greatest negative impact. It\u2019s where the \u201ctelling people what to do\u201d comes from. When used sparingly and in the right situations, they can be a force for good. However, they must not be your default style.\nPacesetting, when used well, it is about meeting challenging and exciting goals. When you need to get high-quality results from a motivated and well performing team, this can be great to help achieve real focus and drive. Sadly it is so overused and poorly executed it becomes the \u201cjust make it happen\u201d and driver of unrealistic workload which contributes to burnout.\nCommanding, when used appropriately soothes fears by giving clear direction in an emergency or crisis. When shit is on fire, you want to know that your leadership ability can help kick-start a turnaround and bring clarity. Then switch to another style. This approach is also required when dealing with problematic employees or unacceptable behaviour.\nCommanding style seems to be what a lot of people think being a leader is, taking control and commanding a situation. It should be used sparingly and only when absolutely necessary.\nBe responsible for the power you wield\nIf reading through those you find yourself feeling a bit guilty that maybe you overuse some of the styles, or overwhelmed that you haven\u2019t got all of these down and ready to use in your toolbox\u2026\nTake a breath. Take responsibility. Take action.\nNo one is perfect, and it\u2019s OK. You can start right now working on those. You can have a conversation with your team and try being open about how you\u2019re going to try some different styles. You can be vulnerable and own up to mistakes you might\u2019ve made followed with an apology. You can order those books and read them. Those books will give you more examples on those leadership styles and help you to find your own voice.\nThe impact you can have on the lives of those around you when you\u2019re a leader, is huge. You can help be that positive impact, help discover and develop potential in someone.\n\nTime spent understanding people is never wasted.\nCate Huston.\n\nI believe in you. <3 Mazz.", "year": "2018", "author": "Mazz Mosley", "author_slug": "mazzmosley", "published": "2018-12-10T00:00:00+00:00", "url": "https://24ways.org/2018/build-up-your-leadership-toolbox/", "topic": "business"} {"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": 274, "title": "Adaptive Images for Responsive Designs", "contents": "So you\u2019ve been building some responsive designs and you\u2019ve been working through your checklist of things to do:\n\n\n\tYou started with the content and designed around it, with mobile in mind first.\n\tYou\u2019ve gone liquid and there\u2019s nary a px value in sight; % is your weapon of choice now.\n\tYou\u2019ve baked in a few media queries to adapt your layout and tweak your design at different window widths.\n\tYou\u2019ve made your images scale to the container width using the fluid Image technique.\n\tYou\u2019ve even done the same for your videos using a nifty bit of JavaScript.\n\n\nYou\u2019ve done a good job so pat yourself on the back. But there\u2019s still a problem and it\u2019s as tricky as it is important: image resolutions.\n\nHTML has an problem\n\nCSS is great at adapting a website design to different window sizes \u2013 it allows you not only to tweak layout but also to send rescaled versions of the design\u2019s images. And you want to do that because, after all, a smartphone does not need a 1,900-pixel background image1.\n\nHTML is less great. In the same way that you don\u2019t want CSS background images to be larger than required, you don\u2019t want that happening with s either. A smartphone only needs a small image but desktop users need a large one. Unfortunately s can\u2019t adapt like CSS, so what do we do?\n\nWell, you could just use a high resolution image and the fluid image technique would scale it down to fit the viewport; but that\u2019s sending an image five or six times the file size that\u2019s really needed, which makes it slow to download and unpleasant to use. Smartphones are pretty impressive devices \u2013 my ancient iPhone 3G is more powerful in every way than my first proper computer \u2013 but they\u2019re still terribly slow in comparison to today\u2019s desktop machines. Sending a massive image means it has to be manipulated in memory and redrawn as you scroll. You\u2019ll find phones rapidly run out of RAM and slow to a crawl.\n\nWell, OK. You went mobile first with everything else so why not put in mobile resolution s too? Because even though mobile devices are rapidly gaining share in your analytics stats, they\u2019re still not likely to be the major share of your user base. I don\u2019t think desktop users would be happy with pokey little mobile resolution images, do you? What we need are adaptive images.\n\nAdaptive image techniques\n\nThere are a number of possible solutions, each with pros and cons, and it\u2019s not as simple to find a graceful solution as you might expect.\n\nYour first thought might be to use JavaScript to trawl through the markup and rewrite the source attribute. That\u2019ll get you the right end result, but it\u2019ll have done it in a way you absolutely don\u2019t want. That\u2019s because of the way browsers load resources. It starts to load the HTML and builds the page on-the-fly; as soon as it finds an element it immediately asks the server for that image. After the HTML has finished loading, the JavaScript will run, change the src attribute, and then the browser will request that new image too. Not instead of, but as well as. Not good: that\u2019s added more bloat instead of cutting it.\n\nPlain JavaScript is out then, which is a problem, because what other tools do we have to work with as web designers? Let\u2019s ignore that for now and I\u2019ll outline another issue with the concept of serving different resolution images for different window widths: a basic file management problem. To request a different image, that image has to exist on the server. How\u2019s it going to get there? That\u2019s not a trivial problem, especially if you have non-technical users that update content through a CMS. Let\u2019s say you solve that \u2013 do you plan on a simple binary switch: big image|little image? Is that really efficient or future-proof? What happens if you have an archive of existing content that needs to behave this way? Can you apply such a solution to existing content or markup?\n\nThere\u2019s a detailed round-up of potential techniques for solving the adaptive images problem over at the Cloud Four blog if you fancy a dig around exploring all the options currently available. But I\u2019m here to show you what I think is the most flexible and easy to implement solution, so here we are.\n\nAdaptive Images\n\nAdaptive Images aims to mitigate most of the issues surrounding the problems of bringing the venerable tag into the 21st century. And it works by leaving that tag completely alone \u2013 just add that desktop resolution image into the markup as you\u2019ve been doing for years now. We\u2019ll fix it using secret magic techniques and bottled pixie dreams. Well, fine: with one .htaccess file, one small PHP file and one line of JavaScript. But you\u2019re killing the mystique with that kind of talk.\n\nSo, what does this solution do?\n\n\n\tIt allows s to adapt to the same break points you use in your media queries, giving granular control in the same way you get with your CSS.\n\tIt installs on your server in five minutes or less and after that is automatic and you don\u2019t need to do anything.\n\tIt generates its own rescaled images on the server and doesn\u2019t require markup changes, so you can apply it to existing web content.\n\tIf you wish, it will make all of your images go mobile-first (just in case that\u2019s what you want if JavaScript and cookies aren\u2019t available).\n\n\nSound good? I hope so. Here\u2019s what you do.\n\nSetting up and rolling out\n\nI\u2019ll assume you have some basic server knowledge along with that wealth of front-end wisdom exploding out of your head: that you know not to overwrite any existing .htaccess file for example, and how to set file permissions on your server. Feeling up to it? Excellent.\n\n\n\tDownload the latest version of Adaptive Images either from the website or from the GitHub repository.\n\tUpload the included .htaccess and adaptive-images.php files into the root folder of your website.\n\tCreate a directory called ai-cache and make sure the server can write to it (CHMOD 755 should do it).\n\tAdd the following line of JavaScript into the of your site:\n\n\n\n\nThat\u2019s it, unless you want to tweak the default settings. You likely do, but essentially you\u2019re already up and running.\n\nHow it works\n\nAdaptive Images does a number of things depending on the scenario the script has to handle, but here\u2019s a basic overview of what it does when you load a page running it:\n\n\n\tA session cookie is written with the value of the visitor\u2019s screen size in pixels.\n\tThe HTML encounters an tag and sends a request to the server for that image. It also sends the cookie, because that\u2019s how browsers work.\n\tApache sits on the server and receives the request for the image. Apache then has a look in the .htaccess file to see if there are any special instructions for files in the requested URL.\n\tThere are! The .htaccess says \u201cHey, server! Any request you get for a JPG, GIF or PNG file just send to the adaptive-images.php file instead.\u201d\n\tThe PHP file then does some intelligent thinking which can cover a number of scenarios, but I\u2019ll illustrate one path that can happen:\n\n\n\t\n\t\tThe PHP file looks for the cookie and finds out that the user has a maximum screen width of 480px.\n\t\tThe PHP has a look at the available media query sizes that were configured and decides which one matches the user\u2019s device.\n\t\tIt then has a look inside the /ai-cache/480/ folder to see if a rescaled image already exists there.\n\t\tWe\u2019ll pretend it doesn\u2019t \u2013 the PHP then goes to the actual requested URI and finds that the original file does exist.\n\t\tIt has a look to see how wide that image is. If it\u2019s already smaller than the user\u2019s screen width it sends it along and stops there. But, let\u2019s pretend the image is 1,000px wide.\n\t\tThe PHP then resizes the image and saves it into the /ai-cache/480 folder ready for the next time someone needs it.\n\t\n\nIt also does a few other things when needs arise, for example:\n\n\n\tIt sends images with a cache header field that tells proxies not to cache the image, while telling browsers they should. This avoids problems with proxy servers and network caching systems grabbing the wrong image and storing it.\n\tIt handles cases where there isn\u2019t a cookie set, and you can choose whether to then send the mobile version or the largest configured media query size.\n\tIt compares timestamps between the source image and the generated cache image \u2013 to ensure that if the source image gets updated, the old cached file won\u2019t be sent.\n\n\nCustomizing\n\nThere are a few options you can customize if you don\u2019t like the default values. By looking in the PHP\u2019s configuration section at the top of the file, you can:\n\n\n\tSet the resolution breakpoints to match your media query break points.\n\tChange the name and location of the ai-cache folder.\n\tChange the quality level any generated JPG images are saved at.\n\tHave it perform a subtle sharpen on rescaled images to help keep detail.\n\tToggle whether you want it to compare the files in the cache folder with the source ones or not.\n\tSet how long the browser should cache the images for.\n\tSwitch between a mobile-first or desktop-first approach when a cookie isn\u2019t found.\n\n\nMore importantly, you probably want to omit a few folders from the AI behaviour. You don\u2019t need or want it resizing the images you\u2019re using in your CSS, for example. That\u2019s fine \u2013 just open up the .htaccess file and follow the instructions to list any directories you want AI to ignore. Or, if you\u2019re a dab hand at RewriteRules you can remove the exclamation mark at the start of the rule and it\u2019ll only apply AI behaviour to a given list of folders.\n\nCaveats\n\nAs I mentioned, I think this is one of the most flexible, future-proof, retrofittable and easy to use solutions available today. But, there are problems with this approach as there are with all of the ones I\u2019ve seen so far.\n\nThis is a PHP solution\n\nI wish I was smarter and knew some fancy modern languages the cool kids discuss at parties, but I don\u2019t. So, you need PHP on your server. That said, Adaptive Images has a Creative Commons licence2 and I would welcome anyone to contribute a port of the code3. \n\nContent delivery networks\n\nAdaptive Images relies on the server being able to: intercept requests for images; do some logic; and send one of a given number of responses. Content delivery networks are generally dumb caches, and they won\u2019t allow that to happen. Adaptive Images will not work if you\u2019re using a CDN to deliver your website.\n\nA minor but interesting cookie issue.\n\nAs Yoav Weiss pointed out in his article Preloaders, cookies and race conditions, there is no way to guarantee that a cookie will be set before images are requested \u2013 even though the JavaScript that sets the cookie is loaded by the browser before it finds any tags. That could mean images being requested without a cookie being available. Adaptive Images has a two-fold mechanism to avoid this being a problem:\n\n\n\tThe $mobile_first toggle allows you to choose what to send to a browser if a cookie isn\u2019t set. If FALSE then it will send the highest configured resolution; if TRUE it will send the lowest.\n\tEven if set to TRUE, Adaptive Images checks the User Agent String. If it discovers the user is on a desktop environment, it will override $mobile_first and set it to FALSE.\n\n\nThis means that if $mobile_first is set to TRUE and the user was unlucky (their browser didn\u2019t write the cookie fast enough), mobile devices will be supplied with the smallest image, and desktop devices will get the largest.\n\nThe best way to get a cookie written is to use JavaScript as I\u2019ve explained above, because it\u2019s the fastest way. However, for those that want it, there is a JavaScript-free method which uses CSS and a bogus PHP \u2018image\u2019 to set the cookie. A word of caution: because it requests an external file, this method is slower than the JavaScript one, and it is very likely that the cookie won\u2019t be set until after images have been requested.\n\nThe future\n\nFor today, this is a pretty good solution. It works, and as it doesn\u2019t interfere with your markup or source material in any way, the process is non-destructive. If a future solution is superior, you can just remove the Adaptive Images files and you\u2019re good to go \u2013 you\u2019d never know AI had been there.\n\nHowever, this isn\u2019t really a long-term solution, not least because of the intermittent problem of the cookie and image request race condition. What we really need are a number of standardized ways to handle this in the future.\n\nFirst, we could do with browsers sending far more information about the user\u2019s environment along with each HTTP request (device size, connection speed, pixel density, etc.), because the way things work now is no longer fit for purpose. The web now is a much broader entity used on far more diverse devices than when these technologies were dreamed up, and we absolutely require the server to have better knowledge about device capabilities than is currently possible. Relying on cookies to do this job doesn\u2019t cut it, and the User Agent String is a complete mess incapable of fulfilling the various purposes we are forced to hijack it for.\n\nSecondly, we need a W3C-backed markup level solution to supply semantically different content at different resolutions, not just rescaled versions of the same content as Adaptive Images does.\n\nI hope you\u2019ve found this interesting and will find Adaptive Images useful.\n\nFootnotes\n\n1 While I\u2019m talking about preventing smartphones from downloading resources they don\u2019t need: you should be careful of your media query construction if you want to stop WebKit downloading all the images in all of the CSS files.\n\n2 Adaptive Images has a very broad Creative Commons licence and I warmly welcome feedback and community contributions via the GitHub repository. \n\n3 There is a ColdFusion port of an older version of Adaptive Images. I do not have anything to do with ported versions of Adaptive Images.", "year": "2011", "author": "Matt Wilcox", "author_slug": "mattwilcox", "published": "2011-12-04T00:00:00+00:00", "url": "https://24ways.org/2011/adaptive-images-for-responsive-designs/", "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": 268, "title": "Getting the Most Out of Google Analytics", "contents": "Something a bit different for today\u2019s 24 ways article. For starters, I\u2019m not a designer or a developer. I\u2019m an evil man who sells things to people on the internet. Second, this article will likely be a little more nebulous than you\u2019re used to, since it covers quite a number of points in a relatively short space. \n\nThis isn\u2019t going to be the complete Google Analytics Conversion University IQ course compressed into a single article, obviously. What it will be, however, is a primer on setting up and using Google Analytics in real life, and a great deal of what I\u2019ve learned using Google Analytics nearly every working day for the past six (crikey!) years.\n\nAlso, to be clear, I\u2019ll be referencing new Google Analytics here; old Google Analytics is for loooosers (and those who want reliable e-commerce conversion data per site search term, natch).\n\nYou may have been running your Analytics account for several years now, dipping in and out, checking traffic levels, seeing what\u2019s popular\u2026 and that\u2019s about it. Google Analytics provides so much more than that, but the number of reports available can often intimidate users, and documentation and case studies on their use are minimal at best. \n\nLet\u2019s start! Setting up your Analytics profile\n\nBefore we plough on, I just want to run through a quick checklist that some basic settings have been enabled for your profile. If you haven\u2019t clicked it, click the big cog on the top-right of Google Analytics and we\u2019ll have a poke about.\n\n\n\tIf you have an e-commerce site, e-commerce tracking has been enabled\u2028\n\tIf your site has a search function, site search tracking has been enabled.\n\tQuery string parameters that you do not want tracked as separate pages have been excluded (for example, any parameters needed for your platform to function, otherwise you\u2019ll get multiple entries for the same page appearing in your reports)\n\tFilters have been enabled on your main profile to exclude your office IP address and any IPs of people who frequently access the site for work purposes. In decent numbers they tend to throw data off a tad.\u2028\n\tYou may also find the need to set up multiple profiles prefiltered for specific audience segments. For example, at Lovehoney we have seventeen separate profiles that allow me quick access to certain countries, devices and traffic sources without having to segment first. You\u2019ll also find load time for any complex reports much improved. Use the same filter screen as above to set up a series of profiles that only include, say, mobile visits, or UK visitors, so you can quickly analyse important segments.\n\n\nMatt, what\u2019s a segment?\n\nA segment is a subsection of your visitor base, which you define and then call on in reports to see specific data for that subsection. For example, in this report I\u2019ve defined two segments, the first for IE6 users and the second for IE7.\n\n\n\nSegments are easily created by clicking the Advanced Segments tabs at the top of any report and clicking +New Custom Segment.\n\n\n\nWhat does your site do?\n\nUnderstanding the goals of your site is an oft-covered topic, but it\u2019s necessary not just to form a better understand of your business and prioritize your time. Understanding what you wish visitors to do on your site translates well into a goal-driven analytics package like Google Analytics. \n\nEvery site exists essentially to sell something, either financially through e-commerce, or to sell an idea or impart information, get people to download a CV or enquire about service, or to sell space on that website to advertisers. If the site did not provide a positive benefit to its owners, it would not have a reason for being. \n\nOnce you have understood the reason why you have a site, you can map that reason on to one of the three goal types Google Analytics provides. \n\nE-commerce \n\nThis conversion type registers transactions as part of a sales process which requires a monetary value, what products have been bought, an SKU (stock keeping unit), affiliation (if you\u2019re then attributing the sale to a third party or franchise) and so on.\n\nThe benefit of e-commerce tracking is not only assigning non-arbitrary monetary value to behaviour of visitors on your site, as well as being able to see ancillary costs such as shipping, but seeing product-level information, like which products are preferred from various channels, popular categories, and so on.\n\n\n\nHowever, I find the e-commerce tracking options also useful for non-e-commerce sites. For example, if you\u2019re offering downloads or subscriptions and having an email address or user\u2019s details is worth something to you, you can set up e-commerce tracking to understand how much value your site is bringing. For example, an email address might be worth 20p to you, but if it also includes a name it\u2019s worth 50p. A contact telephone number is worth \u00a32, and so on.\n\nPage goals\n\nPage goals, unsurprisingly, track a visit to a page (often with a sequence of pages leading up to that page). This is what\u2019s referred to as a goal funnel, and is generally used to track how visitors behave in a multistep checkout. \n\n\n\nInterestingly, the page doesn\u2019t have to actually exist. For example, if you have a single page checkout, you can register virtual page views using trackPageview() when a visitor clicks into a particular section of the checkout or other form. If your site is geared towards getting someone to a particular page, but where there isn\u2019t a transaction (for example, a subscription page) this is for you.\n\nThere are also behavioural goals, such as time on site and number of pages viewed, which are geared towards sites that make money from advertising.\n\nBut, going back to the page goals, these can be abstracted using regular expressions, meaning that you can define a funnel based on page type rather than having to set individual folders.\n\n\n\nIn this example, I\u2019ve created regexes for the main page types on my site, so I can create a wide funnel that captures visitors from where they enter through to checkout.\n\nEvents\n\nEvent tracking registers a predefined event, such as playing a video, or some interaction that can trigger JavaScript, such as a Tweet This button. Events can then be triggered using the trackEvent() call. If you want someone to complete watching a video, you would code your player to fire trackEvent() upon completion. \n\nWhile I don\u2019t use events as goals, I use events elsewhere to see how well a video play aids to conversion. This not only helps me justify the additional spend on creating video content, but also quickly highlights which videos are underperforming as sales tools.\n\n\n\nWhat a visitor can tell you\n\n\u2028Now you have some proper goals set up, we can start to see how changes in content (on-site and external) affect those goals. \n\nUltimately, when a visitor comes to your site, they bring information with them:\n\n\n\twhere they came from (a search engine \u2013 including: keyword searched for; a referral; direct; affiliate; or ad campaign)\n\tdemographics (country; whether they\u2019re new or returning, within thirty days)\n\ttechnical information (browser; screen size; device; bandwidth)\n\tsite-specific information (landing page; next click; previous values assigned to them as custom variables*)\n\n\n * A note about custom variables. There\u2019s no hope in hell that I can cover custom variables in this article. Go research them. Custom variables are the single best way to hack Google Analytics and bend it to your will. Custom variables allow you to record anything you want about a visitor, which that visitor will then carry around with them between visits. It\u2019s also great for plugging other services into Google Analytics (as shown by the marvelous way Visual Website Optimizer allows you to track and segment tests within the GA interface). Just make sure not to breach the terms of service, eh?\n\nCSI your website\n\nPolice procedural TV shows are all the same: the investigators are called to a crime and come across a clue; there\u2019s then an autopsy; new evidence leads them to a new location; they find a new clue; they put two and two together; they solve the mystery.\n\nThis is your life now. Exciting!\n\nSo, now you\u2019re gathering a wealth of information about what sort of people visit your site, what they do when they\u2019re there, and what eventually gets them to drive value to you. It\u2019s now your job to investigate all these little clues to see which types of people drive the most value, and what you can change to improve it.\n\nMaybe not that exciting.\n\nHowever, Google Analytics comes pre-armed with extensive reports for you to delve into. As an e-commerce guy (as opposed to a page goal guy) my day pretty much follows the pattern below.\n\n\n\tLook at e-commerce conversion rate by traffic source compared to the same day in the previous week and previous month. As ours is an e-commerce site, we have weekly and monthly trends. A big spike on Sundays and Mondays, and payday towards the end of the month is always good; on the third week of a month there tends to be a lull. Spend time letting your Google Analytics data brew, understand your own trends and patterns, and you\u2019ll start to get a feel for when something isn\u2019t quite right.\n\t\n\t\tTraffic Sources \u2192 Sources \u2192 All Traffic\n\t\n\tLook at the conversion rate by landing page for any traffic source that feels significantly different to what\u2019s expected. Check bounce rates, drill down to likely landing pages and check search keyword or referral site to see if it\u2019s a particular subset of visitor. You can do this by clicking Secondary Dimension and choosing Keyword or Source. If it\u2019s direct, choose Visitor Type to break down by new or returning visitor.\n\t\n\t\tContent \u2192 Site Content \u2192 Landing Pages\n\t\n\tI then tend to flip into Content Drilldown to see what the next clicks were from those landing pages, and whether they changed significantly to the date I\u2019m comparing with. If they have, that\u2019s usually an indicator of changed content (or its relevancy). Remember, if a bunch of people have found their way to your page via a method you\u2019re not expecting (such as a mention on a Spanish radio station \u2013 this actually happened to me once), while the content hasn\u2019t changed, the relevancy of it to the audience may have.\n\t\n\t\tContent \u2192 Site Content \u2192 Content Drilldown\n\t\n\tOnce I have an idea of what content was consumed, and whether it was relevant to the user, I then look at the visitor specifics, such as browser or demographic data, to see again whether the change was limited to a specific subset. Site speed, for example, is normally a good factor towards bounce rate, so compare that with previous data as well.\n\n\nNow, to be investigating at this level you still need a serious amount of data, in order to tell what\u2019s a significant change or not. If you\u2019re struggling with a small number of visitors, you might find reporting on a weekly or fortnightly basis more appropriate. \n\nHowever, once you\u2019ve looked into the basics of why changes happen to the value of your site, you\u2019ll soon find yourself limited by the reports offered in Standard Reporting. So, it\u2019s time to build your own. Hooray!\n\nCustom reporting\n\nGoogle Analytics provides the tools to build reports specific to the types of investigations you frequently perform. \n\n\n\nWelcome to my world.\n\nCustom reports are quite simple to build: first, you determine the metric you want the report to cover (number of visitors, bounce rate, conversion rate, and so on), then choose a set of dimensions that you\u2019d like to segment the report by (say, the source of the traffic, and whether they were new or returning users). You can filter the report, including or excluding particular dimension values, and you can assign the report to any of the profiles you created earlier. \n\nIn the example below, I\u2019ve created a report that shows me visits and conversion rate for any Google traffic that landed directly only on a product page. I can then drill down on each product page to see the complete phrases use to search. I can use this information in two ways:\n\n\n\tI can see which products aren\u2019t converting, which shows me where I need to work harder on merchandising.\n\tI can give this information to my content team, showing them the actual phrases visitors used to reach our product content, helping them write better targeted product descriptions.\n\n\n\n\nThe possibilities here are nearly endless, but here are a few examples of reports I find useful:\n\n\n\tNon-brand inbound search\nBy creating a report that shows inbound search traffic which doesn\u2019t include your brand, you can see more clearly the behaviour of visitors most likely to be unfamiliar with your site and brand values, without having to rely on the clumsy new or returning demographic date.\n\tTraffic/conversion/sales by hour\nThis is pure stats porn, but actually more useful than real-time data. By seeing this data broken down at an hourly level, you can not only compare the current day to previous days, but also see the best performing times for email broadcasts and tweets.\n\tVisits, load time, conversion and sales by page and browser\nPage speed can often kill conversion rates, but it\u2019s difficult to prove the value of focusing on speed in monetary terms. Having this report to hand helps me drive Operation Greenbelt, our effort to get into the sub-1.5 second band in Google Webmaster Tools.\n\n\nUseful things you can\u2019t do in custom reporting\n\nIf you have a search function on your website, then Conversion Rate and Products Bought by Site Search Term is an incredibly useful report that allows you to measure the effectiveness of your site\u2019s search engine at returning products and content related to the search term used. By including the products actually bought by visitors who searched for each term, you can use this information to better searchandise these results, escalating high propensity and high value products to the top of the results.\n\nHowever, it\u2019s not possible to get this information out of new Google Analytics. \n\nTry it, select the following in the report builder:\n\n\n\tMetrics: total unique searches; e-commerce or goal conversion rate\n\tDimensions: search term; product\n\n\nYou\u2019ll see that the data returned is a little nonsensical, though a 2,000% conversion rate would be nice. However, you can get more accurate information using advanced segments. By creating individual segments to define users who have searched for a particular term, you can run the sales performance and product performance reports as normal. It\u2019s laborious, but it teaches a good lesson: data that seems inaccessible can normally be found another way!\n\nReporting infrastructure\n\nNow that you have a series of reports that you can refer to on a daily or weekly basis, it\u2019s time to put together a regular reporting infrastructure. \n\nEven if you\u2019re not reporting to someone, having a set of key performance indicators that you can use to see how your performance is improving over time allows you to set yourself business goals on a monthly and annual basis.\n\nFor my own reporting, I take some high-level metrics (such as visitors, conversion rate and average order value), and segment them by traffic source and, separately, landing page. These statistics I record weekly and report:\n\n\n\tcurrent week compared with previous week\n\tsame week previous year (if available)\n\t4 week average\n\t13 week average\n\t52 week average (if available)\n\n\nThis takes into account weekly, monthly, seasonal and annual trends, and gives you a much clearer view of your performance.\n\nGetting data in other ways\n\nIf you\u2019re using Google Analytics frequently, with any large site you\u2019ll come to a couple of conclusions:\n\n\n\tDoing any kind of practical comparative analysis is unwieldy.\n\tBoy, Google Analytics is slow!\n\n\nAs you work with bigger datasets and put together more complex queries, you\u2019ll see the loading graphic more than you\u2019ll see actual data. So when you reach that level, there are ways to completely bypass the Google Analytics interface altogether, and get data into your own spreadsheet application for manipulation.\n\nData Feed Query Explorer\n\nIf you just want to pull down some quick statistics but still use complex filters and exotic metric and dimension combinations, the Data Feed Query Explorer is the quickest way of doing so. Authenticate with your Google Analytics account, select a profile, and you can start selecting metrics and dimensions to be generated in a handy, selectable tabulated format.\n\nGoogle Analytics API\n\nIf you\u2019re feeling clever, you can bypass having to copy and paste data by pulling in directly into Excel, Google Docs or your own application using the Google Analytics API. There are several scripts and plugins available to do this. I use Automate Analytics Google Docs code (there\u2019s also a paid version that simplifies setup and creates some handy reports for you).\n\nNew shiny things\n\nWell, now that that\u2019s over, I can show you some cool stuff. Well, at least it\u2019s cool to me. Google Analytics is being constantly improved and new functionality is introduced nearly every month. Here are a couple of my favourites.\n\nMultichannel attribution\n\nNot every visitor converts on your site on the first visit. They may not even do so on the second visit, or third. If they convert on the fourth visit, but each time they visit they do so via a different channel (for example, Search PPC, Search Organic, Direct, Email), which channel do you attribute the conversion to? The last channel, or the first? Dilemma! \n\nGoogle now has a Multichannel Attribution report, available in the Conversion category, which shows how each channel assists in converting, the overlap between channels, and where in the process that channel was important. \n\n\n\nFor example, you may have analysed your blog traffic from Twitter and become disheartened that not many people were subscribing after visiting from Twitter links, but instead your high-value subscribers were coming from natural search. On the face of it, you\u2019d spend less time tweeting, but a multichannel report may tell you that visitors first arrived via a Twitter link and didn\u2019t subscribe, but then came back later after searching for your blog name on Google, after which they did. Don\u2019t pack Twitter in yet!\n\nVisitor and goal flow\n\nVisitor and goal flow are amazing reports that help you visualize the flow of traffic through your site and, ultimately, into your checkout funnel or similar goal path. Flow reports are perfect for understanding drop-off points in your process, as well as what the big draws are on each page. \n\n\n\nPreviously, if you wanted to visualize this data you had to set up several abstracted microgoals and chain them together in custom reports. Frankly, it was a pain in the arse and burned through your precious and limited goal allocation.\n\nVisitor flow bypasses all that and produces the report in an interactive flow diagram. While it doesn\u2019t show you the holy grail of conversion likelihood by each path, you can segment visitor flow so that you can see very specifically how different segments of your visitor base behave.\n\nGo play with it now!", "year": "2011", "author": "Matt Curry", "author_slug": "mattcurry", "published": "2011-12-18T00:00:00+00:00", "url": "https://24ways.org/2011/getting-the-most-out-of-google-analytics/", "topic": "business"} {"rowid": 310, "title": "Fairytale of new Promise", "contents": "There are only four good Christmas songs.\nI know, yeah, JavaScript or whatever. We\u2019ll get to that in a minute, I promise.\nFirst\u2014and I cannot stress this enough\u2014 there are four good Christmas songs. You\u2019re free to disagree with me here, of course, but please try to understand that you will be wrong.\nThey don\u2019t all have the most safe-for-work titles; I can\u2019t list all of them here, but if you choose to let your fingers do the walkin\u2019 to your nearest search engine, I will say that one was released by the band FEAR way back in 1982 and one was on Run the Jewels\u2019 self-titled debut album. The lyrics are a hell of a lot worse than the titles, so maybe wait until you get home from work before you queue them up. Wear headphones, if you\u2019ve got thin walls.\nFor my money, though, the two I can reference by name are the top of that small heap: Tom Waits\u2019 Christmas Card from a Hooker in Minneapolis, and The Pogues\u2019 Fairytale of New York. The former once held the honor of being the only good Christmas song\u2014about which which I was also unequivocally correct, right up until I changed my mind. It\u2019s not the song up for discussion today, but feel free to familiarize yourself just the same\u2014I\u2019ll wait.\nFairytale of New York\u2014the top of the list\u2014starts out by hinting at some pretty standard holiday fare; dreams and cheer and whatnot. Typical seasonal stuff, so long as you ignore that the story seems to be recounted as a drunken flashback in a jail cell. You can probably make a few guesses at the underlying spirit of the song based on that framing: following a lucky break, our bright-eyed protagonists move to New York in search of fame and fortune, only to quickly descend into bad decisions, name-calling, and vaguely festive chaos.\nThis song speaks to me on a couple of levels, not the least of which is as a retelling of my day-to-day interactions with JavaScript. Each day\u2019s melody might vary a little bit, granted, but the lyrics almost always follow a pretty clear arc toward \u201cPARENTAL ADVISORY: EXPLICIT CONTENT.\u201d You might have heard a similar tune yourself; it goes a little somethin\u2019 like setTimeout(function() { console.log( \"this should be happening last\" ); }, 1000); . Callbacks are calling callbacks calling callbacks and something is happening somewhere, as the JavaScript interpreter plods through our code start-to-finish, line-by-line, step-by-step. If we need to take actions based on the results of something that could take its sweet time resolving, well, we\u2019d better fiddle with the order of things to make sure those actions don\u2019t happen too soon.\n\u201cBut I can see a better time,\u201d as the song says, \u201cwhen all our dreams come true.\u201d So, with that Pogues brand of holiday spirit squarely in mind\u2014by which I mean that your humble narrator is almost certainly drunk, and may be incarcerated at the time of publication\u2014gather \u2019round for a story of hope, of hardships, of semi-asynchronous JavaScript programming, and ultimately: of Promise unfulfilled.\nThe Main Thread\nJavaScript is single-minded, in a manner of speaking. Anything we tell the JavaScript runtime to do goes into a single-file queue; you\u2019ll see it referred to as the \u201cmain thread,\u201d or \u201cUI thread.\u201d That thread can be shared by a number of critical browser processes, like rendering and re-rendering parts of the page, and user interactions ranging from the simple\u2014say, highlighting text\u2014to the more complex\u2014interacting with form elements.\nIf that sounds a little scary to you, well, that\u2019s because it is. The more complex our scripts, the more we\u2019re cramming into that single-file main thread, to be processed along with\u2014say\u2014some of our CSS animations. Too much JavaScript clogging up the main thread means a lot of user-facing performance jankiness. Getting away from that single thread is a big part of all the excitement around Web Workers, which allow us to offload entire scripts into their own dedicated background threads\u2014though not without limitations of their own. Outside of Web Workers, that everything-thread is the only game in town: scripts executed one thing at a time, functions calling functions calling functions, taking numbers and crowding up the same deli counter as a user\u2019s interactions\u2014which, in this already strained metaphor, would be ham, I guess?\nAsynchronous JavaScript\nNow, those queued actions may include asynchronous things. For example: AJAX callbacks, setTimeout/setInterval, and addEventListener won\u2019t block the main thread while we\u2019re waiting for a request to come back, a timer to tick away, or an event to trigger. Once those things do kick in, though, the actions they\u2019re meant to perform will get shuffled right back into that single-thread queue.\nThere are a couple of places you might have written asynchronously-fired JavaScript, even if you\u2019re not super familiar with the overarching concept: XMLHttpRequest\u2014\u201cAJAX,\u201d if ya nasty\u2014or just kicking off a function once a user triggers a click or mouseenter event. Event-driven development is writ a little larger, with the overall flow of the script dictated by events, both internal and external. Writing event-driven JavaScript applications is a step in the right direction for sure\u2014it won\u2019t cure what ails the main thread, but it does work with the medium in a reasonable way. Event-driven development allows us to manage our use of the main thread in a way that makes sense. If any of this rings a bell for you, the motivation for Promises should feel familiar.\nFor example, a custom init event might kick things off, and fire a create event that applies our classes and restructures our markup which, on completion, fires a bindEvents event to handle all the event listeners for user interaction. There might not sound like much difference between that and one big function that kicks off, manipulates the DOM, and binds our events line-by-line\u2014but in a script of sufficient size and complexity we\u2019re not only provided with a decoupled flow through the script, but obvious touchpoints for future updates and a predictable structure for ongoing maintenance. \nThis pattern falls apart a little where we were still creating, binding, and listening for events in the same top-to-bottom, one-item-at-a-time way\u2014we had to set a listener on a given object before the event fires, or nothing would happen:\n// Create the event:\nvar event = document.createEvent( \"Event\" );\n\n// Name the event:\nevent.initEvent( \"doTheStuff\", true, true );\n\n// Listen for the custom `doTheStuff` event on `window`:\nwindow.addEventListener( \"doTheStuff\", initializeEverything );\n\n// Fire the custom event\nwindow.dispatchEvent( event );\nThis example is a little contrived, and this stuff is a lot more manageable for sure with the addition of a framework, but that\u2019s the basic gist: create and name the event, add a listener for the event, and\u2014after setting our listener\u2014dispatch the event.\nEvents and callbacks aren\u2019t the only game in town for weaving our way in and out of the main thread, though\u2014at least, not anymore. \nPromises\nA Promise is, at the risk of sounding sentimental, pure potential\u2014an empty container into which a value eventually results. A Promise can exist in several states: \u201cpending,\u201d while the computation they contain is being performed or \u201cresolved\u201d once that computation is complete. Once resolved, a Promise is \u201cfulfilled\u201d if it gave us back something we expect, or \u201crejected\u201d if it didn\u2019t.\nThe Promise constructor accepts a callback with two arguments: resolve and reject. We perform an action\u2014asynchronous or otherwise\u2014within that callback. If everything in there has gone according to plan, we call resolve. If something has gone awry, we call reject\u2014with an error, conventionally. To illustrate, let\u2019s tack something together with a pretty decent chance of doing what we don\u2019t want: a promise meant only to give us the number 1, but has a chance of giving us back a 2. No reasonable person would ever do this, of course, but I wouldn\u2019t necessarily put it past me.\nvar promisedOne = new Promise( function( resolve, reject ) {\n var coinToss = Math.floor( Math.random() * 2 ) + 1;\n\n if( coinToss === 1 ) {\n resolve( coinToss );\n } else {\n reject( new Error( \"That ain\u2019t a one.\" ) );\n }\n});\nThere\u2019s nothing too surprising in there, after you boil it all down. It\u2019s a little return-y, with the exception that we\u2019re flagging results as \u201cas expected\u201d or \u201csomething went wrong.\u201d\nTapping into that Promise uses another new keyword: then\u2014and as someone who attempts to make sense of JavaScript by breaking it down to plain ol\u2019 human-language, I\u2019m a big fan of this syntax. then is tacked onto our Promise identifier, and does just what it says on the tin: once the Promise is resolved, then do one of two things, both supplied as callbacks: the first in the case of a fulfilled promise, and the second in the case of a rejected one. Those two callbacks will have, as arguments, the results we specified with resolve orreject, respectively. It sounds like a lot in prose, but in code it\u2019s a pretty simple pattern:\npromisedOne.then( function( result ) {\n console.log( result );\n}, function( error ) {\n console.error( error );\n});\nIf you\u2019ve spent any time working with AJAX\u2014jQuery-wise, in particular\u2014you\u2019ve seen something like this pattern before: a success callback and an error callback. The state of a promise, once fulfilled or rejected, cannot be changed\u2014any reference we make to promisedOne will have a single, fixed result.\nIt may not look like too much the way I\u2019m using it here, but it\u2019s powerful stuff\u2014a pattern for asynchronously resolving anything. I\u2019ve recently used Promises alongside a script that emulates Font Load Events, to apply webfonts asynchronously and avoid a potential performance hit. Font Face Observer allows us to, as the name implies, determine when the files referenced by our @font-face rules have finished loading. \nvar fontObserver = new FontFaceObserver( \"Fancy Font\" );\n\nfontObserver.check().then(function() {\n document.documentElement.className += \" fonts-loaded\";\n}, function( error ) {\n console.error( error );\n});\nfontObserver.check() gives us back a Promise, allowing us to chain on a then containing our callbacks for success and failure. We use the fulfilled callback to bolt a class onto the page once the font file has been fully transferred. We don\u2019t bother including an argument in the first function, since we don\u2019t care about the result itself so much as we care that the promise resolved without error\u2014we\u2019re not doing anything with the resolved value, just adding a class to the page. We do include the error argument, since we\u2019ll want to know what happened should something go wrong.\nNow, this isn\u2019t the tidiest syntax around\u2014at least to my eyes\u2014with those two functions just kinda floating in a then. Luckily there\u2019s an similar alternative syntax; one that I find a bit easier to parse at-a-glance:\nfontObserver.check()\n .then(function() {\n document.documentElement.className += \" fonts-loaded\";\n })\n .catch(function( error ) {\n console.log( error );\n });\nThe first callback inside then provides us with our success state, while the catch provides us with a single, explicit \u201csomething went wrong\u201d callback. The two syntaxes aren\u2019t completely identical in all situations, but for a simple case like this, I find it a little neater.\nThe Common Thread\nI guess I still owe you an explanation, huh. Not about the JavaScript-whatever; I think I\u2019ve explained that plenty. No, I mean Fairytale of New York, and why it\u2019s perched up there at the top of the four (4) song heap.\nFairytale is a sad song, ostensibly. If you follow the main thread\u2014start to finish, line-by-line, step by step\u2014 Fairytale is a sad song. And I can see you out there, visions of Die Hard dancing in your heads: \u201cbut is it a Christmas song?\u201d\nWell, for my money, nothing says \u201cholidays\u201d quite like unreliable narration.\nShane MacGowan, the song\u2019s author, has placed the first verse about \u201cChristmas Eve in the drunk tank\u201d as happening right after the \u201clucky one, came in eighteen-to-one\u201d\u2014not at the chronological end of the story. That means the song might not be mostly drunken flashback, but all of it a single, overarching flashback including a Christmas Eve in protective custody. It could be that the man and woman are, together, recounting times long past\u2014good times and bad times\u2014maybe not even in chronological order. Hell, the \u201cNYPD Choir\u201d mentioned in the chorus? There\u2019s no such thing.\nWe\u2019re not big Christmas folks, my family and I. But just the same, every year, the handful of us get together, and every year\u2014like clockwork\u2014there\u2019s a lull in conversation, there\u2019s a sharp exhale, and Ma says \u201cwe all made it.\u201d Not to a house, not to a dinner, but through another year, to another Christmas. At this point, without fail, someone starts telling a story\u2014and one begets another, and so on. Sometimes the stories are happy, sometimes they\u2019re sad, more often than not they\u2019re both. Some are about things we were lucky to walk away from, some are about a time when another one of us didn\u2019t.\nStart-to-finish, line-by-line, step-by-step, the main thread through the year doesn\u2019t change, and maybe there isn\u2019t a whole lot we can do to change it. But by carefully weaving our way in and out of that thread\u2014stories all out of sync and resolving one way or the other, with the results determined by questionably reliable narrators\u2014we can change the way we interact with it and, little by little, we can start making sense of it.", "year": "2016", "author": "Mat Marquis", "author_slug": "matmarquis", "published": "2016-12-19T00:00:00+00:00", "url": "https://24ways.org/2016/fairytale-of-new-promise/", "topic": "code"} {"rowid": 143, "title": "Marking Up a Tag Cloud", "contents": "Everyone\u2019s doing it. \n\nThe problem is, everyone\u2019s doing it wrong. \n\nHarsh words, you might think. But the crimes against decent markup are legion in this area. You see, I\u2019m something of a markup and semantics junkie. So I\u2019m going to analyse some of the more well-known tag clouds on the internet, explain what\u2019s wrong, and then show you one way to do it better. \n\ndel.icio.us \n\nI think the first ever tag cloud I saw was on del.icio.us. Here\u2019s how they mark it up. \n\n
\n\t.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": 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": 72, "title": "Designing with Contrast", "contents": "When an appetite for aesthetics over usability becomes the bellwether of user interface design, it\u2019s time to reconsider who we\u2019re designing for.\nOver the last few years, we have questioned the signifiers that gave obvious meaning to the function of interface elements. Strong textures, deep shadows, gradients \u2014 imitations of physical objects \u2014 were discarded. And many, rightfully so. Our audiences are now more comfortable with an experience that feels native to the technology, so we should respond in kind.\nYet not all of the changes have benefitted users. Our efforts to simplify brought with them a trend of ultra-minimalism where aesthetics have taken priority over legibility, accessibility and discoverability. The trend shows no sign of losing popularity \u2014 and it is harming our experience of digital content.\n\nA thin veneer\nWe are in a race to create the most subdued, understated interface. Visual contrast is out. In its place: the thinnest weights of a typeface and white text on bright color backgrounds. Headlines, text, borders, backgrounds, icons, form controls and inputs: all grey.\nWhile we can look back over the last decade and see minimalist trends emerging on the web, I think we can place a fair share of the responsibility for the recent shift in priorities on Apple. The release of iOS 7 ushered in a radical change to its user interface. It paired mobile interaction design to the simplicity and eloquence of Apple\u2019s marketing and product design. It was a catalyst. We took what we saw, copied and consumed the aesthetics like pick-and-mix.\nNew technology compounds this trend. Computer monitors and mobile devices are available with screens of unprecedented resolutions. Ultra-light type and subtle hues, difficult to view on older screens, are more legible on these devices. It would be disingenuous to say that designers have always worked on machines representative of their audience\u2019s circumstances, but the gap has never been as large as it is now. We are running the risk of designing VIP lounges where the cost of entry is a Mac with a Retina display.\nMinimalist expectations\nLike progressive enhancement in an age of JavaScript, many good and sensible accessibility practices are being overlooked or ignored. We\u2019re driving unilateral design decisions that threaten accessibility. We\u2019ve approached every problem with the same solution, grasping on to the integrity of beauty, focusing on expression over users\u2019 needs and content. \nSomeone once suggested to me that a client\u2019s website should include two states. The first state would be the ideal experience, with low color contrast, light font weights and no differentiation between links and text. It would be the default. The second state would be presented in whatever way was necessary to meet accessibility standards. Users would have to opt out of the default state via a toggle if it wasn\u2019t meeting their needs. A sort of first-class, upper deck cabin equivalent of graceful degradation. That this would divide the user base was irrelevant, as the aesthetics of the brand were absolute. \nIt may seem like an unusual anecdote, but it isn\u2019t uncommon to see this thinking in our industry. Again and again, we place the burden of responsibility to participate in a usable experience on others. We view accessibility and good design as mutually exclusive. Taking for granted what users will tolerate is usually the forte of monopolistic services, but increasingly we apply the same arrogance to our new products and services.\n\nImitation without representation\nAll of us are influenced in one way or another by one another\u2019s work. We are consciously and unconsciously affected by the visual and audible activity around us. This is important and unavoidable. We do not produce work in a vacuum. We respond to technology and culture. We channel language and geography. We absorb the sights and sounds of film, television, news. To mimic and copy is part and parcel of creating something an audience of many can comprehend and respond to. Our clients often look first to their competitors\u2019 products to understand their success.\nHowever, problems arise when we focus on style without context; form without function; mimicry as method. Copied and reused without any of the ethos of the original, stripped of deliberate and informed decision-making, the so-called look and feel becomes nothing more than paint on an empty facade.\nThe typographic and color choices so in vogue today with our popular digital products and services have little in common with the brands they are meant to represent.\n\nFor want of good design, the message was lost\nThe question to ask is: does the interface truly reflect the product? Is it an accurate characterization of the brand and organizational values? Does the delivery of the content match the tone of voice?\nThe answer is: probably not. Because every organization, every app or service, is unique. Each with its own personality, its own values and wonderful quirks. Design is communication. We should do everything in our role as professionals to use design to give voice to the message. Our job is to clearly communicate the benefits of a service and unreservedly allow access to information and content. To do otherwise, by obscuring with fashionable styles and elusive information architecture, does a great disservice to the people who chose to engage with and trust our products.\nWe can achieve hierarchy and visual rhythm without resorting to extreme reduction. We can craft a beautiful experience with fine detail and curiosity while meeting fundamental standards of accessibility (and strive to meet many more).\nStandards of excellence\nIt isn\u2019t always comfortable to step back and objectively question our design choices. We get lost in the flow of our work, using patterns and preferences we\u2019ve tried and tested before. That our decisions often seem like second nature is a gift of experience, but sometimes it prevents us from finding our blind spots.\nI was first caught out by my own biases a few years ago, when designing an interface for the Bank of England. After deciding on the colors for the typography and interactive elements, I learned that the site had to meet AAA accessibility standards. My choices quickly fell apart. It was eye-opening. I had to start again with restrictions and use size, weight and placement instead to construct the visual hierarchy.\nEven now, I make mistakes. On a recent project, I used large photographs on an organization\u2019s website to promote their products. Knowing that our team had control over the art direction, I felt confident that we could compose the photographs to work with text overlays. Despite our best effort, the cropped images weren\u2019t always consistent, undermining the text\u2019s legibility. If I had the chance to do it again, I would separate the text and image.\nSo, what practical things can we consider to give our users the experience they deserve?\nPut guidelines in place\n\nThink about your brand values. Write down keywords and use them as a framework when choosing a typeface. Explore colors that convey the organization\u2019s personality and emotional appeal.\nDefine a color palette that is web-ready and meets minimum accessibility standards. Note which colors are suitable for use with text. Only very dark hues of grey are consistently legible so keep them for non-essential text (for example, as placeholders in form inputs).\nFind which background colors you can safely use with white text, and consider integrating contrast checks into your workflow.\nUse roman and medium weights for body copy. Reserve lighter weights of a typeface for very large text. Thin fonts are usually the first to break down because of aliasing differences across platforms and screens.\nCheck that the size, leading and length of your type is always legible and readable. Define lower and upper limits. Small text is best left for captions and words in uppercase.\nAvoid overlaying text on images unless it\u2019s guaranteed to be legible. If it\u2019s necessary to optimize space in the layout, give the text a container. Scrims aren\u2019t always reliable: the text will inevitably overlap a part of the photograph without a contrasting ground.\n\nTest your work\n\nReview legibility and contrast on different devices. It\u2019s just as important as testing the layout of a responsive website. If you have a local device lab, pay it a visit.\nFind a computer monitor near a window when the sun is shining. Step outside the studio and try to read your content on a mobile device with different brightness levels. \nAsk your friends and family what they use at home and at work. It\u2019s one way of making sure your feedback isn\u2019t always coming from a closed loop.\n\nPush your limits\n\nYou define what the user sees. If you\u2019ve inherited brand guidelines, question them. If you don\u2019t agree with the choices, make the case for why they should change.\nExperiment with size, weight and color to find contrast. Objects with low contrast appear similar to one another and undermine the visual hierarchy. Weak relationships between figure and ground diminish visual interest. A balanced level of contrast removes ambiguity and creates focal points. It captures and holds our attention.\nIf you\u2019re lost for inspiration, look to graphic design in print. We have a wealth of history, full of examples that excel in using contrast to establish visual hierarchy.\nEmbrace limitations. Use boundaries as an opportunity to explore possibilities.\n\nMore than just a facade\nDesigning with standards encourages legibility and helps to define a strong visual hierarchy. Design without exclusion (through neither negligence or intent) gets around discussions of demographics, speaks to a larger audience and makes good business sense. Following the latest trends not only weakens usability but also hinders a cohesive and distinctive brand.\nUsers will make means when they need to, by increasing browser font sizes or enabling system features for accessibility. But we can do our part to take as much of that burden off of the user and ask less of those who need it most.\nIn architecture, it isn\u2019t buildings that mimic what is fashionable that stand the test of time. Nor do we admire buildings that tack on separate, poorly constructed extensions to meet a bare minimum of safety regulations. We admire architecture that offers well-considered, remarkable, usable spaces with universal access.\nPerhaps we can take inspiration from these spaces. Let\u2019s give our buildings a bold voice and make sure the doors are open to everyone.", "year": "2015", "author": "Mark Mitchell", "author_slug": "markmitchell", "published": "2015-12-13T00:00:00+00:00", "url": "https://24ways.org/2015/designing-with-contrast/", "topic": "design"} {"rowid": 6, "title": "Run Ragged", "contents": "You care about typography, right? Do you care about words and how they look, read, and are understood? If you pick up a book or magazine, you notice the moment something is out of place: an orphan, rivers within paragraphs of justified prose, or caps masquerading as small caps. So why, I ask you, is your stance any different on the web?\n\nWe\u2019re told time and time again that as a person who makes websites we have to get comfortable with our lack of control. On the web, this is a feature, not a bug. But that doesn\u2019t mean we have to lower our standards, or not strive for the same amount of typographic craft of our print-based cousins. We shouldn\u2019t leave good typesetting at the door because we can\u2019t control the line length.\n\nWhen I typeset books, I\u2019d spend hours manipulating the text to create a pleasurable flow from line to line. A key aspect of this is manicuring the right rag \u2014 the vertical line of words on ranged-left text. Maximising the space available, but ensuring there are no line breaks or orphaned words that disrupt the flow of reading. Setting a right rag relies on a bunch of guidelines \u2014 or as I was first taught to call them, violations! \n\nViolation 1. Never break a line immediately following a preposition\n\nPrepositions are important, frequently used words in English. They link nouns, pronouns and other words together in a sentence. And links should not be broken if you can help it. Ending a line on a preposition breaks the join from one word to another and forces the reader to work harder joining two words over two lines.\n\nFor example: \n\n\n\tThe container is for the butter\n\n\nThe preposition here is for and shows the relationship between the butter and the container. If this were typeset on a line and the line break was after the word for, then the reader would have to carry that through to the next line. The sentence would not flow.\n\nThere are lots of prepositions in English \u2013 about 150 \u2013 but only 70 or so in use.\n\nViolation 2. Never break a line immediately following a dash\n\nA dash \u2014 either an em-dash or en-dash \u2014 can be used as a pause in the reading, or as used here, a point at which you introduce something that is not within the flow of the sentence. Like an aside. Ending with a pause on the end of the line would have the same effect as ending on a preposition. It disrupts the flow of reading.\n\nViolation 3. No small words at the end of a line\n\nDon\u2019t end a line with small words. Most of these will actually be covered by violation \u21161. But there will be exceptions. My general rule of thumb here is not to leave words of two or three letters at the end of a line.\n\nViolation 4. Hyphenation\n\nIn print, hyphens are used at the end of lines to join words broken over a line break. Mostly, this is used in justified body text, and no doubt you will be used to seeing it in newspapers or novels. A good rule of thumb is to not allow more than two consecutive lines to end with a hyphen.\n\nOn the web, of course, we can use the CSS hyphens property. It\u2019s reasonably supported with the exception of Chrome. Of course, it works best when combined with justified text to retain the neat right margin.\n\nViolation 5. Don\u2019t break emphasised phrases of three or fewer words\n\nIf you have a few words emphasised, for example:\n\n\n\tHe calls this problem definition escalation\n\n\n\u2026then try not to break the line among them. It\u2019s important the reader reads through all the words as a group.\n\nHow do we do all of that on the web?\n\nAll of those guidelines are relatively easy to implement in print. But what about the web? Where content is poured into a template from a CMS? Well, there are things we can do. Meet your new friend, the non-breaking space, or as you may know them: \u00a0.\n\nThe guidelines above are all based on one decision for the typesetter: when should the line break? \n\nWe can simply run through a body of text and add the \u00a0 based on these sets of questions:\n\n\n\tAre there any prepositions in the text? If so, add a \u00a0 after them.\n\tAre there any dashes? If so, add a \u00a0 after them.\n\tAre there any words of fewer than three characters that you haven\u2019t already added spaces to? If so, add a \u00a0 after them.\n\tAre there any emphasised groups of words either two or three words long? If so, add a \u00a0 in between them.\n\n\nFor a short piece of text, this isn\u2019t a big problem. But for longer bodies of text, this is a bit arduous. Also, as I said, lots of websites use a CMS and just dump the text into a template. What then? We can\u2019t expect our content creators to manually manicure a right rag based on these guidelines. In this instance, we really need things to be automatic.\n\nThere isn\u2019t any reason why we can\u2019t just pass the question of when to break the line straight to the browser by way of a script which compares the text against a set of rules. In plain English, this script could be to scan the text for:\n\n\n\tPrepositions. If found, add \u00a0 after them.\n\tDashes. If found, add \u00a0 after them.\n\tWords fewer than three characters long that aren\u2019t prepositions. If found, add \u00a0 after them.\n\tEmphasised phrases of up to three words in length. If found, add \u00a0 between all of the words.\n\n\nAnd there we have it.\n\nA note on fluidity\n\nAn important consideration of this script is that it doesn\u2019t scan the text to see what is at the end of a line. It just looks for prepositions, dashes, words fewer than three characters long, and emphasised words within paragraphs and applies the \u00a0 accordingly regardless of where the thing lives. This is because in a fluid layout a word might appear in the beginning, middle or the end of a line depending on the width of the browser. And we want it to behave in the right way when it does find itself at the end.\n\nSee it in action!\n\nMy friend and colleague, Nathan Ford, has written a small JavaScript called Ragadjust that does all of this automatically. The script loops through a webpage, compares the text against the conditions, and then inserts \u00a0 in the places that violate the conditions above.\n\nYou can get the script from GitHub and see it in action on my own website.\n\nSome caveats\n\nAs my friend Jon Tan says, \u201cThere are no rules in typography, just good or bad decisions\u201d, and typesetting the right rag is no different. \n\n\n\tThe guidelines for the violations above are useful for justified text, too. But we need to be careful here. Too stringent adherence to these violations could lead to ugly gaps in our words \u2014 called rivers \u2014 as the browser forces justification.\n\tThe violation regarding short words at the end of sentences is useful for longer line lengths, or measures, of text. When the measure gets shorter, maybe five or six words, then we need to be more forgiving as to what wraps to the next line and what doesn\u2019t. In fact, you can see this happening on my site where I\u2019ve not included a check on the size of the browser window (purposefully, for this demo, of course. Ahem).\n\tThis article is about applying these guidelines to English. Some of them will, no doubt, cross over to other languages quite well. But for those languages, like German for instance, where longer words tend to be in more frequent use, then some of the rules may result in a poor right rag.\n\n\nMarginal gains\n\nIn 2007, I spoke with Richard Rutter at SXSW on web typography. In that talk, Richard and I made a point that good typographic design \u2014 on the web, in print; anywhere, in fact \u2014 relies on small, measurable improvements across an entire body of work. From heading hierarchy to your grid system, every little bit helps. In and of themselves, these little things don\u2019t really mean that much. You may well have read this article, shrugged your shoulders and thought, \u201cHuh. So what?\u201d But these little things, when added up, make a difference. A difference between good typographic design and great typographic design.\n\n \n\nAppendix\n\nPreposition whitelist\n\naboard\nabout\nabove\nacross\nafter\nagainst\nalong\namid\namong\nanti\naround\nas\nat\nbefore\nbehind\nbelow\nbeneath\nbeside\nbesides\nbetween\nbeyond\nbut\nby\nconcerning\nconsidering\ndespite\ndown\nduring\nexcept\nexcepting\nexcluding\nfollowing\nfor\nfrom\nin\ninside\ninto\nlike\nminus\nnear\nof\noff\non\nonto\nopposite\noutside\nover\npast\nper\nplus\nregarding\nround\nsave\nsince\nthan\nthrough\nto\ntoward\ntowards\nunder\nunderneath\nunlike\nuntil\nup\nupon\nversus\nvia\nwith\nwithin\nwithout", "year": "2013", "author": "Mark Boulton", "author_slug": "markboulton", "published": "2013-12-24T00:00:00+00:00", "url": "https://24ways.org/2013/run-ragged/", "topic": "design"} {"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": 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": 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": 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": 24, "title": "Kill It With Fire! What To Do With Those Dreaded FAQs", "contents": "In the mid-1640s, a man named Matthew Hopkins attempted to rid England of the devil\u2019s influence, primarily by demanding payment for the service of tying women to chairs and tossing them into lakes.\n\nUnsurprisingly, his methods garnered criticism. Hopkins defended himself\u00a0in The Discovery of Witches\u00a0in 1647, subtitled \u201cCertaine Queries answered, which have been and are likely to be objected against MATTHEW HOPKINS, in his way of finding out Witches.\u201d\n\nEach \u201cquerie\u201d was written in the voice of an imagined detractor, and answered in the voice of an imagined defender (always referring to himself as \u201cthe discoverer,\u201d or \u201chim\u201d):\n\n\n\tQuer. 14.\n\n\tAll that the witch-finder doth is to fleece the country of their money, and therefore rides and goes to townes to have imployment, and promiseth them faire promises, and it may be doth nothing for it, and possesseth many men that they have so many wizzards and so many witches in their towne, and so hartens them on to entertaine him.\n\n\tAns.\n\n\tYou doe him a great deale of wrong in every of these particulars.\n\n\nHopkins\u2019 self-defense was an early modern English FAQ.\n\nDigital beginnings\n\nQuestion and answer formatting certainly isn\u2019t new, and stretches back much further than witch-hunt days. But its most modern, most notorious, most reviled incarnation is the internet\u2019s frequently asked questions page.\n\nFAQs began showing up on pre-internet mailing lists\u00a0as a way for list members to answer and pre-empt newcomers\u2019 repetitive questions:\n\n\n\tThe presumption was that new users would download archived past messages through ftp. In practice, this rarely happened and the users tended to post questions to the mailing list instead of searching its archives. Repeating the \u201cright\u201d answers becomes tedious\u2026\n\n\nWhen all the users of a system can hear all the other users, FAQs make a lot of sense: the conversation needs to be managed and manageable. FAQs were a stopgap for the technological limitations of the time.\n\nBut the internet moved past mailing lists. Online information can be stored, searched, filtered, and muted; we choose and control our conversations. New users no longer rely on the established community to answer their questions for them.\n\nAnd yet, FAQs are still around. They\u2019re a content anti-pattern, replicated from site to site to solve a problem we no longer have.\n\nWhat we hate when we hate FAQs\n\nAs someone who creates and structures online content \u2013 always with the goal of making that content as useful as possible to people \u2013 FAQs drive me absolutely batty. Almost universally, FAQs represent the opposite of useful. A brief list of their sins:\n\n\nDouble trouble\nDuplicated content is practically a given with FAQs. They\u2019re written as though they\u2019ll be accessed in a vacuum \u2013 but search results, navigation patterns, and curiosity ensure that users will seek answers throughout the site. Is our goal to split their focus? To make them uncertain of where to look? To divert them to an isolated microcosm of the website? Duplicated content means user confusion (to say nothing of the duplicated workload for maintaining content).\nLeaving the job unfinished\nMany FAQs fail before they\u2019re even out of the gate, presenting a list of questions that\u2019s incomplete (too short and careless to be helpful) or irrelevant (avoiding users\u2019 real concerns in favor of soundbites). Alternately, if the right questions are there, the answers may be convoluted, jargon-heavy, or otherwise difficult to understand.\nLong lists of not-my-question\nGetting a single answer often means sifting through a haystack of questions. For each potential question, the user must read, comprehend, assess, move on, rinse, repeat. That\u2019s a lot of legwork for little reward \u2013 and a lot of opportunity for mistakes. Users may miss their question, or they may fail to recognize a differently worded version of their question, or they may not notice when their sought-after answer appears somewhere they didn\u2019t expect.\nThe ventriloquist act\nFAQs shift the point of view. While websites speak on behalf of the organization (\u201cour products,\u201d \u201cour services,\u201d \u201cyou can call us for assistance,\u201d etc.), FAQs speak as the user \u2013 \u201cI can\u2019t find my password\u201d or \u201cHow do I sign up?\u201d Both voices are written from the first-person perspective, but speak for different entities, which is disorienting: it breaks the tone and messaging across the website. It\u2019s also presumptuous: why do you get to speak for the user?\n\n\nThese all underscore FAQs\u2019 fatal flaw: they are content without context, delivered without regard for the larger experience of the website. You can hear the absurdity in the name itself: if users are asking the same questions so frequently, then there is an obvious gulf between their needs and the site content. (And if not, then we have a labeling problem.)\n\nInstead of sending users to a jumble of maybe-it\u2019s-here-maybe-it\u2019s-not questions, the answers to FAQs should be found naturally throughout a website. They are not separated, not isolated, not other. They are\u00a0the content.\n\nTo present it otherwise is to create a runaround, and users know it. Jay Martel\u2019s parody, \u201cF.A.Q.s about F.A.Q.s\u201d\u00a0captures the silliness and frustration of such a system:\n\n\n\tQ: Why are you so rude?\n\n\tA: For that answer, you would have to consult an F.A.Q.s about F.A.Q.s about F.A.Q.s. But your time might be better served by simply abandoning your search for a magic answer and taking responsibility for your own profound ignorance.\n\n\nFAQs aren\u2019t magic answers. They don\u2019t resolve a content dilemma or even help users. Yet they keep cropping up, defiant, weedy, impossible to eradicate.\n\nWhere are they all coming from?\n\nBlame it on this: writing is hard. When generating content, most of us do whatever it takes to get some words on the screen. And the format of question and answer makes it easy: a reactionary first stab at content development.\n\nAfter all, the point of website content is to answer users\u2019 questions. So this \u2013 to give everyone credit \u2013 is a really good move. Content creators who think in terms of questions and answers are actually thinking of their users, particularly first-time users, trying to anticipate their needs and write towards them.\n\nIt\u2019s a good start. But it\u2019s scaffolding: writing that helps you get to the writing you\u2019re supposed to be doing. It supports you while you write your way to the heart of your content. And once you get there, you have to look back and take the scaffolding down.\n\nLeaving content in the Q&A format that helped you develop it is missing the point. You\u2019re not there to build scaffolding. You have to see your content in its naked purpose and determine the best method for communicating that purpose \u2013 and it usually won\u2019t be what got you there.\n\nThe goal (to borrow a lesson from content management systems) is to separate the content from its presentation, to let the meaning of the content inform its display.\n\nThis is, of course, a nice theory.\n\nAn occasionally necessary evil\n\nI have a lot of clients who adore FAQs. They\u2019ve developed their content over a long period of time. They\u2019ve listened to the questions their users are asking. And they\u2019ve answered them all on a page that I simply cannot get them to part with.\n\nWhich means I\u2019ve had to consider that there may be occasions where an FAQ page is appropriate.\n\nAs an example: one of my clients is a financial office in a large institution. Because this office manages several third-party systems that serve a range of niche audiences, they had developed FAQs that addressed hyper-specific instances of dysfunction within systems for different users \u2013 \u00e0 la \u201cI\u2019m a financial director and my employee submitted an expense report in such-and-such system and it returned such-and-such error. What do I do?\u201d\n\nYes, this content could be removed from the question format and rewritten. But I\u2019m not sure it would be an improvement. It won\u2019t necessarily resolve concerns about length and searchability, and the different audiences may complicate the delivery. And since the work of rewriting it didn\u2019t fit into the client workflow (small team, no writers, pressed for time), I didn\u2019t recommend the change.\n\nI\u2019ve had to make peace with not being to torch all the FAQs on the internet. Some content, like troubleshooting information or complex procedures, may be better in that format. It may be the smartest way for a particular client to handle that particular information.\n\nOf course, this has to be determined on a case-by-case basis, taking into account the amount of content, the subject matter, the skill levels of the content creators, the publishing workflow, and the search habits of the users.\n\nIf you determine that an FAQ page is the only way to go, ask yourself:\n\n\n\tIs there a better label or more specific term for the page (support, troubleshooting, product concerns, etc.)?\n\tIs there way to structure the page, categorize the questions, or otherwise make it easier for users to navigate quickly to the answer they need?\n\tIs a question and answer format absolutely the best way to communicate this information?\n\n\nForm follows function\n\nJust as a question and answer format isn\u2019t necessarily required to deliver the content, neither is it an inappropriate method in and of itself. Content professionals have developed a knee-jerk reaction:\u00a0It\u2019s an FAQ page! Quick, burn it! Buuuuurn it!\n\nBut there\u2019s no inherent evil in questions and answers. Framing content in an interrogatory construct is no more a deal with the devil than subheads and paragraphs, or narrative arcs, or bullet points.\n\nYes, FAQs are riddled with communication snafus. They deserve, more often than not, to be tied to a chair and thrown into a lake. But that wouldn\u2019t fix our content problems. FAQs are a shiny and obvious target for our frustration, but they\u2019re not unique in their flaws. In any format, in any display, in any kind of page, weak content can rear its ugly, poorly written head.\n\nIt\u2019s not the Q&A that\u2019s to blame, it\u2019s bad content. Content without context will always fail users. That\u2019s the real witch in our midst.", "year": "2013", "author": "Lisa Maria Martin", "author_slug": "lisamariamartin", "published": "2013-12-08T00:00:00+00:00", "url": "https://24ways.org/2013/what-to-do-with-faqs/", "topic": "content"} {"rowid": 251, "title": "The System, the Search, and the Food Bank", "contents": "Imagine a warehouse, half the length of a football field, with a looped conveyer belt down the center. \nOn the belt are plastic bins filled with assortments of shelf-stable food\u2014one may have two bags of potato chips, seventeen pudding cups, and a box of tissues; the next, a dozen cans of beets. The conveyer belt is ringed with large, empty cardboard boxes, each labeled with categories like \u201cBottled Water\u201d or \u201cCereal\u201d or \u201cCandy.\u201d \nSuch was the scene at my local food bank a few Saturdays ago, when some friends and I volunteered for a shift sorting donated food items. Our job was to fill the labeled cardboard boxes with the correct items nabbed from the swiftly moving, randomly stocked plastic bins.\nI could scarcely believe my good fortune of assignments. You want me to sort things? Into categories? For several hours? And you say there\u2019s an element of time pressure? Listen, is there some sort of permanent position I could be conscripted into.\nLook, I can\u2019t quite explain it: I just know that I love sorting, organizing, and classifying things\u2014groceries at a food bank, but also my bookshelves, my kitchen cabinets, my craft supplies, my dishwasher arrangement, yes I am a delight to live with, why do you ask?\nThe opportunity to create meaning from nothing is at the core of my excitement, which is why I\u2019ve tried to build a career out of organizing digital content, and why I brought a frankly frightening level of enthusiasm to the food bank. \u201cI can\u2019t believe they\u2019re letting me do this,\u201d I whispered in awe to my conveyer belt neighbor as I snapped up a bag of popcorn for the Snacks box with the kind of ferocity usually associated with birds of prey.\nThe jumble of donated items coming into the center need to be sorted in order for the food bank to be able to quantify, package, and distribute the food to those who need it (I sense a metaphor coming on). It\u2019s not just a nice-to-have that we spent our morning separating cookies from carrots\u2014it\u2019s a crucial step in the process. Organization makes the difference between chaos and sense, between randomness and usefulness, whether we\u2019re talking about donated groceries or\u2014there it is\u2014web content.\nThis happens through the magic of criteria matching. In order for us to sort the food bank donations correctly, we needed to know not only the categories we were sorting into, but also the criteria for each category. Does canned ravioli count as Canned Soup? Does enchilada sauce count as Tomatoes? Do protein bars count as Snacks? (Answers: yes, yes, and only if they are under 10 grams of protein or will expire within three months.) \nIs X a Y? was the question at the heart of our food sorting\u2014but it\u2019s also at the heart of any information-seeking behavior. When we are organizing, or looking for, any kind of information, we are asking ourselves:\n\nWhat is the criteria that defines Y?\nDoes X meet that criteria?\n\nWe don\u2019t usually articulate it so concretely because it\u2019s a background process, only leaping to consciousness when we encounter a stumbling block. If cans of broth flew by on the conveyer belt, it didn\u2019t require much thought to place them in the Canned Soup box. Boxed broth, on the other hand, wasn\u2019t allowed, causing a small cognitive hiccup\u2014this X is NOT a Y\u2014that sometimes meant having to re-sort our boxes.\nOn the web, we\u2019re interested\u2014I would hope\u2014in reducing cognitive hiccups for our users. We are interested in making our apps easy to use, our websites easy to navigate, our information easy to access. After all, most of the time, the process of using the internet is one of uniting a question with an answer\u2014Is this article from a trustworthy source? Is this clothing the style I want? Is this company paying their workers a living wage? Is this website one that can answer my question? Is X a Y?\nWe have a responsibility, therefore, to make information easy for our users to find, understand, and act on. This means\u2014well, this means a lot of things, and I\u2019ve got limited space here, so let\u2019s focus on these three lessons from the food bank:\n\n\nUse plain, familiar language. This advice seems to be given constantly, but that\u2019s because it\u2019s solid and it\u2019s not followed enough. Your menu labels, page names, and headings need to reflect the word choice of your users. Think how much harder it would have been to sort food if the boxes were labeled according to nutritional content, grocery store aisle number, or Latin name. How much would it slow sorting down if the Tomatoes box were labeled Nightshades? It sounds silly, but it\u2019s not that different from sites that use industry jargon, company lingo, acronyms (oh, yes, I\u2019ve seen it), or other internally focused language when trying to provide wayfinding for users. Choose words that your audience knows\u2014not only will they be more likely to spot what they\u2019re looking for on your site or app, but you\u2019ll turn up more often in search results.\n\n\nCreate consistency in all things. Missteps in consistency look like my earlier chicken broth example\u2014changing up how something looks, sounds, or functions creates a moment of cognitive dissonance, and those moments add up. The names of products, the names of brands, the names of files and forms and pages, the names of processes and procedures and concepts\u2014these all need to be consistently spelled, punctuated, linked, and referenced, no matter what section or level the user is in. If submenus are visible in one section, they should be visible in all. If calls-to-action are a graphic button in one section, they are the same graphic button in all. Every affordance, every module, every design choice sets up user expectations; consistency keeps those expectations afloat, making for a smoother experience overall.\n\nMake the system transparent. By this, I do not mean that every piece of content should be elevated at all times. The horror. But I do mean that we should make an effort to communicate the boundaries of the digital space from any given corner within. Navigation structures operate just as much as a table of contents as they do a method of moving from one place to another. Page hierarchies help explain content relationships, communicating conceptual relevancy and relative importance. Submenus illustrate which related concepts may be found within a given site section. Take care to show information that conveys the depth and breadth of the system, rather than obscuring it.\n\nThis idea of transparency was perhaps the biggest challenge we experienced in food sorting. Imagine us volunteers as users, each looking for a specific piece of information in the larger system. Like any new visitor to a website, we came into the system not knowing the full picture. We didn\u2019t know every category label around the conveyer belt, nor what criteria each category warranted. \nThe system wasn\u2019t transparent for us, so we had to make it transparent as we went. We had to stop what we were doing and ask questions. We\u2019d ask staff members. We\u2019d ask more seasoned volunteers. We\u2019d ask each other. We\u2019d make guesses, and guess wrongly, and mess up the boxes, and correct our mistakes, and learn.\nThe more we learned, the easier the sorting became. That is, we were able to sort more quickly, more efficiently, more accurately. The better we understood the system, the better we were at interacting with it.\nThe same is true of our users: the better they understand digital spaces, the more effective they are at using them. But visitors to our apps and websites do not have the luxury of learning the whole system. The fumbling trial-and-error method that I used at the food bank can, on a website, drive users away\u2014or, worse, misinform or hurt them. \nThis is why we must make choices that prioritize transparency, consistency, and familiarity. Our users want to know if X is a Y\u2014well-sorted content can give them the answer.", "year": "2018", "author": "Lisa Maria Martin", "author_slug": "lisamariamartin", "published": "2018-12-16T00:00:00+00:00", "url": "https://24ways.org/2018/the-system-the-search-and-the-food-bank/", "topic": "content"} {"rowid": 291, "title": "Information Literacy Is a Design Problem", "contents": "Information literacy, wrote Dr. Carol Kulthau in her 1987 paper \u201cInformation Skills for an Information Society,\u201d is \u201cthe ability to read and to use information essential for everyday life\u201d\u2014that is, to effectively navigate a world built on \u201ccomplex masses of information generated by computers and mass media.\u201d\nNearly thirty years later, those \u201ccomplex masses of information\u201d have only grown wilder, thornier, and more constant. We call the internet a firehose, yet we\u2019re loathe to turn it off (or even down). The amount of information we consume daily is staggering\u2014and yet our ability to fully understand it all remains frustratingly insufficient. \nThis should hit a very particular chord for those of us working on the web. We may be developers, designers, or strategists\u2014we may not always be responsible for the words themselves\u2014but we all know that communication is much more than just words. From fonts to form fields, every design decision that we make changes the way information is perceived\u2014for better or for worse.\nWhat\u2019s more, the design decisions that we make feed into larger patterns. They don\u2019t just affect the perception of a single piece of information on a single site; they start to shape reader expectations of information anywhere. Users develop cumulative mental models of how websites should be: where to find a search bar, where to look at contact information, how to filter a product list. \nAnd yet: our models fail us. Fundamentally, we\u2019re not good at parsing information, and that\u2019s troubling. Our experience of an \u201cinformation society\u201d may have evolved, but the skills Dr. Kuhlthau spoke of are even more critical now: our lives depend on information literacy.\nPatterns from words\nLet\u2019s start at the beginning: with the words. Our choice of words can drastically alter a message, from its emotional resonance to its context to its literal meaning. Sometimes we can use word choice for good, to reinvigorate old, forgotten, or unfairly besmirched ideas.\nOne time at a wedding bbq we labeled the coleslaw BRASSICA MIXTA so people wouldn\u2019t skip it based on false hatred.\u2014 Eileen Webb (@webmeadow) November 27, 2016\n\nWe can also use clever word choice to build euphemisms, to name sensitive or intimate concepts without conjuring their full details. This trick gifts us with language like \u201cthe beast with two backs\u201d (thanks, Shakespeare!) and \u201csurfing the crimson wave\u201d (thanks, Cher Horowitz!).\nBut when we grapple with more serious concepts\u2014war, death, human rights\u2014this habit of declawing our language gets dangerous. Using more discrete wording serves to nullify the concepts themselves, euphemizing them out of sight and out of mind.\nThe result? Politicians never lie, they just \u201cmisspeak.\u201d Nobody\u2019s racist, but plenty of people are \u201ceconomically anxious.\u201d Nazis have rebranded as \u201calt-right.\u201d \nI\u2019m not an asshole, I\u2019m just alt-nice.\u2014 Andi Zeisler (@andizeisler) November 22, 2016\n\nThe problem with euphemisms like these is that they quickly infect everyday language. We use the words we hear around us. The more often we see \u201calt-right\u201d instead of \u201cNazi,\u201d the more likely we are to use that phrase ourselves\u2014normalizing the term as well as the terrible ideas behind it.\nPatterns from sentences\nThat process of normalization gets a boost from the media, our main vector of information about the world outside ourselves. Headlines control how we interpret the news that follows\u2014even if the story contradicts it in the end. We hear the framing more clearly than the content itself, coloring our interpretation of the news over time.\nEven worse, headlines are often written to encourage clicks, not to convey critical information. When headline-writing is driven by sensationalism, it\u2019s much, much easier to build a pattern of misinformation. Take this CBS News headline: \u201cDonald Trump: \u2018Millions\u2019 voted illegally for Hillary Clinton.\u201d The headline makes no indication that this an objectively false statement; instead, this word choice subtly suggestions that millions did, in fact, illegally vote for Hillary Clinton.\nHeadlines like this are what make lying a worthwhile political strategy. https://t.co/DRjGeYVKmW\u2014 Binyamin Appelbaum (@BCAppelbaum) November 27, 2016\n\nThis is a deeply dangerous choice of words when headlines are the primary way that news is conveyed\u2014especially on social media, where it\u2019s much faster to share than to actually read the article. In fact, according to a study from the Media Insight Project, \u201croughly six in 10 people acknowledge that they have done nothing more than read news headlines in the past week.\u201d \nIf a powerful person asserts X there are 2 responsible ways to cover:1. \u201cX is true\u201d2. \u201cPerson incorrectly thinks X\u201dNever \u201cPerson says X\u201d\u2014 Helen Rosner (@hels) November 27, 2016\n\nEven if we do, in fact, read the whole article, there\u2019s no guarantee that we\u2019re thinking critically about it. A study conducted by Stanford found that \u201c82 percent of students could not distinguish between a sponsored post and an actual news article on the same website. Nearly 70 percent of middle schoolers thought they had no reason to distrust a sponsored finance article written by the CEO of a bank, and many students evaluate the trustworthiness of tweets based on their level of detail and the size of attached photos.\u201d \nFriends: our information literacy is not very good. Luckily, we\u2014workers of the web\u2014are in a position to improve it.\nSentences into design\nConsider the presentation of those all-important headlines in social media cards, as on Facebook. The display is a combination of both the card\u2019s design and the article\u2019s source code, and looks something like this:\n\nA large image, a large headline; perhaps a brief description; and, at the bottom, in pale gray, a source and an author\u2019s name. \nThose choices convey certain values: specifically, they suggest that the headline and the picture are the entire point. The source is so deemphasized that it\u2019s easy to see how fake news gains a foothold: daily exposure to this kind of hierarchy has taught us that sources aren\u2019t important. \nAnd that\u2019s the message from the best-case scenario. Not every article shows every piece of data. Take this headline from the BBC: \u201cWisconsin receives request for vote recount.\u201d \n\nWith no image, no description, and no author, there\u2019s little opportunity to signal trust or provide nuance. There\u2019s also no date\u2014ever\u2014which presents potentially misleading complications, especially in the context of \u201cbreaking news.\u201d \nAnd lest you think dates don\u2019t matter in the light-speed era of social media, take the headline, \u201cMaryland sidesteps electoral college.\u201d Shared into my feed two days after the US presidential election, that\u2019s some serious news with major historical implications. But since there\u2019s no date on this card, there\u2019s no way for readers to know that the \u201cTuesday\u201d it refers to was in 2007. Again, a design choice has made misinformation far too contagious.\n\nMore recently, I posted my personal reaction to the death of Fidel Castro via a series of twenty tweets. Wanting to share my thoughts with friends and family who don\u2019t use Twitter, I then posted the first tweet to Facebook. The card it generated was less than ideal:\n\nThe information hierarchy created by this approach prioritizes the name of the Twitter user (not even the handle), along with the avatar. Not only does that create an awkward \u201cheadline\u201d (at least when you include a full stop in your name), but it also minimizes the content of the tweet itself\u2014which was the whole point. \nThe arbitrary elevation of some pieces of content over others\u2014like huge headlines juxtaposed with minimized sources\u2014teaches readers that these values are inherent to the content itself: that the headline is the news, that the source is irrelevant. We train readers to stop looking for the information we don\u2019t put in front of them. \nThese aren\u2019t life-or-death scenarios; they are just cases where design decisions noticeably dictate the perception of information. Not every design decision makes so obvious an impact, but the impact is there. Every single action adds to the pattern.\nDesign with intention\nWe can\u2019t necessarily teach people to read critically or vet their sources or stop believing conspiracy theories (or start believing facts). Our reach is limited to our roles: we make websites and products for companies and colleges and startups.\nBut we have more reach there than we might realize. Every decision we make influences how information is presented in the world. Every presentation adds to the pattern. No matter how innocuous our organization, how lowly our title, how small our user base\u2014every single one of us contributes, a little bit, to the way information is perceived.\nAre we changing it for the better?\nWhile it\u2019s always been crucial to act ethically in the building of the web, our cultural climate now requires dedicated, individual conscientiousness. It\u2019s not enough to think ourselves neutral, to dismiss our work as meaningless or apolitical. Everything is political. Every action, and every inaction, has an impact.\nAs Chappell Ellison put it much more eloquently than I can:\nEvery single action and decision a designer commits is a political act. The question is, are you a conscious actor?\u2014 Chappell Ellison\ud83e\udd14 (@ChappellTracker) November 28, 2016\n\nAs shapers of information, we have a responsibility: to create clarity, to further understanding, to advance truth. Every single one of us must choose to treat information\u2014and the society it builds\u2014with integrity.", "year": "2016", "author": "Lisa Maria Martin", "author_slug": "lisamariamartin", "published": "2016-12-14T00:00:00+00:00", "url": "https://24ways.org/2016/information-literacy-is-a-design-problem/", "topic": "content"} {"rowid": 308, "title": "How to Make a Chrome Extension to Delight (or Troll) Your Friends", "contents": "If you\u2019re like me, you grew up drawing mustaches on celebrities. Every photograph was subject to your doodling wrath, and your brilliance was taken to a whole new level with computer programs like Microsoft Paint. The advent of digital cameras meant that no one was safe from your handiwork, especially not your friends. And when you finally got your hands on Photoshop, you spent hours maniacally giggling at your artistic genius. \nBut today is different. You\u2019re a serious adult with important things to do and a reputation to uphold. You keep up with modern web techniques and trends, and have little time for fun other than a random Giphy on Slack\u2026 right? \nNope. \nIf there\u2019s one thing 2016 has taught me, it\u2019s that we\u2014the self-serious, world-changing tech movers and shakers of the universe\u2014haven\u2019t changed one bit from our younger, more delightable selves.\nHow do I know? This year I created a Chrome extension called Tabby Cat and watched hundreds of thousands of people ditch productivity for randomly generated cats. Tabby Cat replaces your new tab page with an SVG cat featuring a silly name like \u201cStinky Dinosaur\u201d or \u201cTiny Potato\u201d. Over time, the cats collect goodies that vary in absurdity from fishbones to lawn flamingos to Raybans. Kids and adults alike use this extension, and analytics show the majority of use happens Monday through Friday from 9-5. The popularity of Tabby Cat has convinced me there\u2019s still plenty of room in our big, grown-up hearts for fun.\n\n\nToday, we\u2019re going to combine the formula behind Tabby Cat with your intrinsic desire to delight (or troll) your friends, and create a web app that generates your friends with random objects and environments of your choosing. You can publish it as a Chrome extension to replace your new tab, or simply host it as a website and point to it with the New Tab Redirect extension. \nHere\u2019s a sneak peek at my final result featuring my partner, my cat, and I in cheerfully weird accessories. Your result will look however you want it to.\n\nAlong the way, we\u2019ll cover how to build a Chrome extension that replaces the new tab page, and explore ways to program randomness into your work to create something truly delightful. \nWhat you\u2019ll need\n\nAdobe Illustrator (or a similar illustration program to export PNG)\nSome images of your friends\nA text editor\n\nNote: This can be as simple or as complex as you want it to be. Most of the application is pre-built so you can focus on kicking back and getting in touch with your creative side. If you want to dive in deeper, you\u2019ll find ways to do it.\nGetting started\n\nDownload a local copy of the boilerplate for today\u2019s tutorial here, and open it in a text editor. Inside, you\u2019ll find a simple web app that you can run in Chrome. \nOpen index.html in Chrome. You should see a grey page that says \u201cNoname\u201d.\nOpen template.pdf in Adobe Illustrator or a similar program that can export PNG. The file contains an artboard measuring 800px x 800px, with a dotted blue outline of a face. This is your template.\n\nNote: We\u2019re using Google Chrome to build and preview this application because the end-result is a Chrome extension. This means that the application isn\u2019t totally cross-browser compatible, but that\u2019s okay.\nStep 1: Gather your friends\nThe first thing to do is choose who your muses are. Since the holidays are upon us, I\u2019d suggest finding inspiration in your family.\nCreate your artwork\nFor each person, find an image where their face is pointed as forward as possible. Place the image onto the Artwork layer of the Illustrator file, and line up their face with the template. Then, rename the artboard something descriptive like face_bob. Here\u2019s my crew:\nAs you can see, my use of the word \u201cfamily\u201d extends to cats. There\u2019s no judgement here.\nNotice that some of my photos don\u2019t completely fill the artboard\u2013that\u2019s fine. The images will be clipped into ovals when they\u2019re rendered in the application.\nNow, export your images by following these steps:\n\nTurn the Template layer off and export the images as PNGs. \nIn the Export dialog, tick the \u201cUse Artboards\u201d checkbox and enter the range with your faces. \nExport at 72ppi to keep things running fast. \nSave your images into the images/ folder in your project.\n\nAdd your images to config.js\nOpen scripts/config.js. This is where you configure your extension. \nAdd key value pairs to the faces object. The key should be the person\u2019s name, and the value should be the filepath to the image.\nfaces: {\n leslie: 'images/face_leslie.png',\n kyle: 'images/face_kyle.png',\n beep: 'images/face_beep.png'\n}\nThe application will choose one of these options at random each time you open a new tab. This pattern is used for everything in the config file. You give the application groups of choices, and it chooses one at random each time it loads. The only thing that\u2019s special about the faces object is that person\u2019s name will also be displayed when their face is chosen.\nNow, when you refresh the project in Chrome, you should see one of your friends along with their name, like this:\n\nCongrats, you\u2019re off and running!\nStep 2: Add adjectives\nNow that you\u2019ve loaded your friends into the application, it\u2019s time to call them names. This step definitely yields the most laughs for the least amount of effort.\nAdd a list of adjectives into the prefixes array in config.js. To get the words flowing, I took inspiration from ways I might describe some of my relatives during a holiday gathering\u2026\nprefixes: [\n 'Loving',\n 'Drunk',\n 'Chatty',\n 'Merry',\n 'Creepy',\n 'Introspective',\n 'Cheerful',\n 'Awkward',\n 'Unrelatable',\n 'Hungry',\n ...\n]\nWhen you refresh Chrome, you should see one of these words prefixed before your friend\u2019s name. Voila!\n\nStep 3: Choose your color palette\nReal talk: I\u2019m bad at choosing color palettes, so I have a trick up my sleeve that I want to share with you. If you\u2019ve been blessed with the gift of color aptitude, skip ahead.\nHow to choose colors\nTo create a color palette, I start by going to a Coolors.co, and I hit the spacebar until I find a palette that I like. We need a wide gamut of hues for our palette, so lock down colors you like and keep hitting the spacebar until you find a nice, full range. You can use as many or as few colors as you like.\nCopy these colors into your swatches in Adobe Illustrator. They\u2019ll be the base for any illustrations you create later.\nNow you need a set of background colors. Here\u2019s my trick to making these consistent with your illustration palette without completely blending in. Use the \u201cAdjust Palette\u201d tool in Coolors to dial up the brightness a few notches, and the saturation down just a tad to remove any neon effect. These will be your background colors.\n\nAdd your background colors to config.js\nCopy your hex codes into the bgColors array in config.js.\nbgColors: [\n '#FFDD77',\n '#FF8E72',\n '#ED5E84',\n '#4CE0B3',\n '#9893DA',\n ...\n]\nNow when you go back to Chrome and refresh the page, you\u2019ll see your new palette!\n\nStep 4: Accessorize\nThis is the fun part. We\u2019re going to illustrate objects, accessories, lizards\u2014whatever you want\u2014and layer them on top of your friends.\nYour objects will be categorized into groups, and one option from each group will be randomly chosen each time you load the page. Think of a group like \u201chats\u201d or \u201cglasses\u201d. This will allow combinations of accessories to show at once, without showing two of the same type on the same person.\nCreate a group of accessories\nTo get started, open up Illustrator and create a new artboard out of the template. Think of a group of objects that you can riff on. I found hats to be a good place to start. If you don\u2019t feel like illustrating, you can use cut-out images instead.\n\nNext, follow the same steps as you did when you exported the faces. Here they are again:\n\nTurn the Template layer off and export the images as PNGs. \nIn the Export dialog, tick the \u201cUse Artboards\u201d checkbox and enter the range with your hats. \nExport at 72ppi to keep things running fast. \nSave your images into the images/ folder in your project.\n\nAdd your accessories to config.js\nIn config.js, add a new key to the customProps object that describes the group of accessories that you just created. Its value should be an array of the filepaths to your images. This is my hats array:\ncustomProps: {\n hats: [ \n 'images/hat_crown.png',\n 'images/hat_santa.png',\n 'images/hat_tophat.png',\n 'images/hat_antlers.png'\n ]\n}\nRefresh Chrome and behold, accessories!\n\nCreate as many more accessories as you want\nRepeat the steps above to create as many groups of accessories as you want. I went on to make glasses and hairstyles, so my final illustrator file looks like this:\n\nThe last step is adding your new groups to the config object. List your groups in the order that you want them to be stacked in the DOM. My final output will be hair, then hats, then glasses:\ncustomProps: {\n hair: [ \n 'images/hair_bowl.png',\n 'images/hair_bob.png'\n ], \n hats: [ \n 'images/hat_crown.png',\n 'images/hat_santa.png',\n 'images/hat_tophat.png',\n 'images/hat_antlers.png'\n ],\n glasses: [\n 'images/glasses_aviators.png',\n 'images/glasses_monacle.png'\n ]\n}\nAnd, there you have it! Randomly generated friends with random accessories. \n\nFeel free to go much crazier than I did. I considered adding a whole group of animals in celebration of the new season of Planet Earth, or even adding Sir David Attenborough himself, or doing a bit of role reversal and featuring the animals with little safari hats! But I digress\u2026\nStep 5: Publish it\nIt\u2019s time to put this in your new tabs! You have two options:\n\nPublish it as a Chrome extension in the Chrome Web Store.\nHost it as a website and point to it with the New Tab Redirect extension.\n\nToday, we\u2019re going to cover Option #1 because I want to show you how to make the simplest Chrome extension possible. However, I recommend Option #2 if you want to keep your project private. Every Chrome extension that you publish is made publicly available, so unless your friends want their faces published to an extension that anyone can use, I\u2019d suggest sticking to Option #2.\nHow to make a simple Chrome extension to replace the new tab page\nAll you need to do to make your project into a Chrome extension is add a manifest.json file to the root of your project with the following contents. There are plenty of other properties that you can add to your manifest file, but these are the only ones that are required for a new tab replacement:\n{\n \"manifest_version\": 2,\n \"name\": \"Your extension name\",\n \"version\": \"1.0\",\n \"chrome_url_overrides\" : {\n \"newtab\": \"index.html\"\n }\n}\nTo test your extension, you\u2019ll need to run it in Developer Mode. Here\u2019s how to do that:\n\nGo to the Extensions page in Chrome by navigating to chrome://extensions/.\nTick the checkbox in the upper-right corner labelled \u201cDeveloper Mode\u201d.\nClick \u201cLoad unpacked extension\u2026\u201d and select this project.\nIf everything is running smoothly, you should see your project when you open a new tab. If there are any errors, they should appear in a yellow box on the Extensions page.\n\nVoila! Like I said, this is a very light example of a Chrome extension, but Google has tons of great documentation on how to take things further. Check it out and see what inspires you.\nShare the love\nNow that you know how to make a new tab extension, go forth and create! But wield your power responsibly. New tabs are opened so often that they\u2019ve become a part of everyday life\u2013just consider how many tabs you opened today. Some people prefer to-do lists in their tabs, and others prefer cats. \nAt the end of the day, let\u2019s make something that makes us happy. Cheers!", "year": "2016", "author": "Leslie Zacharkow", "author_slug": "lesliezacharkow", "published": "2016-12-08T00:00:00+00:00", "url": "https://24ways.org/2016/how-to-make-a-chrome-extension/", "topic": "code"} {"rowid": 39, "title": "Meet for Learning", "contents": "\u201cI\u2019ve never worked in a place like this,\u201d said one of my direct reports during our daily stand-up meeting.\n\nAnd with that statement, my mind raced to the most important thing about lawyering that I\u2019ve learned from decades of watching lawyers lawyer on TV: don\u2019t ask a question you don\u2019t know the answer to.\n\nBut I couldn\u2019t stop myself. I wanted to learn more. The thought developed in my mind. The words formed in my mouth. And the vocalization occurred: \u201cA place like this?\u201d\n\n\u201cI\u2019ve never worked where people are so honest and transparent about things.\u201d\n\nDesigning a learning-centered culture\n\nBefore we started Center Centre, Jared Spool and I discussed both the larger goals and the smaller details of this new UX design school. We talked about things like user experience, curriculum, and structure.\n\nWe discussed the pattern we saw in our research. Hiring managers told us time and again that great designers have excellent technical and interpersonal skills. But, more importantly, the best designers are lifelong learners\u2014they are willing and able to learn how to do new things. Learning this led us to ask a critical question: how would we intentionally design a learning-centered experience?\n\nTo craft the experience we were aiming for, we knew we had to create a learning-centered culture for our students and our employees. We knew that our staff would need to model the behaviors our students needed to learn. We knew the best way to shape the culture was to work with our direct reports\u2014our directs\u2014to develop the behaviors we wanted them to exemplify.\n\nTo craft the experience we were aiming for, we knew we had to create a learning-centered culture for our students and our employees. We knew that our staff would need to model the behaviors our students needed to learn.\n\nBuilding a learning team\n\nOur learning-centered culture starts with our staff. We believe in transparency. Transparency builds trust. Effective organizations have effective teams who trust each other as individuals.\n\nOne huge way we build that trust and provide opportunities for transparency is in our meetings. (I know, I know\u2014meetings! Yuck!) But seriously, running and participating in effective meetings is a great opportunity to build a learning-centered culture.\n\nMeetings\u2014when done well\u2014allow individuals time to come together, to share, and to listen. These behaviors, executed on a consistent and regular basis, build honest and trusting relationships.\n\nAn effective meeting is one that achieves the desired outcomes of that meeting. While different meetings aim for different results, at Center Centre all meetings have a secondary goal: meet for learning.\n\nA framework for learning-centered meetings\n\nWe\u2019ve developed a framework for our meetings. We use it for all our meetings, which means attendees know what to expect. It also saves us from reinventing the wheel in each meeting.\n\nThese basic steps help our meetings focus on the valuable face-to-face interaction we\u2019re having, and help us truly begin to learn from one another.\n\n An agenda for a staff meeting.\n\nUse effective meeting basics\n\n\n\tPrepare for the meeting before the meeting.\n\tIf you\u2019re running the meeting, prepare a typed agenda and share it before the meeting. Agendas have start times for each item.\n\tStart the meeting on time. Don\u2019t wait for stragglers.\n\tDefine ground rules. Get input from attendees. Recurring meetings don\u2019t have to do this every time.\n\tKeep to the meeting agenda. Put off-topic questions and ideas in a parking lot, a visual document that everyone can see, so you can address the questions and ideas later.\n\tFinish on time. And if you\u2019ve reached the meeting\u2019s goals, finish early.\n\n\n Parking lots where ideas on sticky notes can be posted for later consideration.\n\nFocus to learn\n\n\n\tHave tech-free meetings: no laptops, no phones, no things with notifications.\n\tBring a notebook and a pen.\n\tTake notes by hand. You\u2019re not taking minutes, you\u2019re writing to learn.\n\n\nCome with a learning mindset\n\n\n\tAsk: what are our goals for this meeting? (Hopefully answered by the meeting agenda.)\n\tAsk: what can I learn overall?\n\tAsk: what can I learn from each of my colleagues?\n\tAsk: what can I share that will help the team learn overall?\n\tAsk: what can I share that will help each of my colleagues learn?\n\n\nInvesting in regularly scheduled learning-centered meetings\n\nAt Center Centre, we have two types of recurring all-staff meetings: daily stand-ups and weekly staff meetings. (We are a small organization, so it makes sense to meet as an entire group.)\n\nYes, that means we spend thirty minutes each day in stand-up, for a total of two and a half hours of stand-up meeting time each week. And, yes, we also have a weekly ninety-minute sit-down staff meeting on top of that. This investment in time is an investment in learning.\n\nWe use these meetings to build our transparency, and, therefore, our trust. The regularity of these meetings helps us maintain ongoing, open sharing about our responsibilities, our successes, and our learning.\n\nFor instance, we answer five questions in our stand-up:\n\n\n\tWhat did I get done since the last stand-up (I reported at)?\n\tWhat is my goal to accomplish before the next stand-up?\n\tWhat\u2019s preventing me from getting these things done, if anything?\n\tWhat\u2019s the highest risk or most unknown thing right now about what I\u2019m trying to get done?\n\tWhat is the most important thing I learned since the last time we met and how will what I learned change the way I approach things in the future?\n\n\nEach person writes out their answers to these questions before the meeting. Each person brings their answers printed on paper to the meeting. And each person brings a pen to jot down notes.\n\n Notes compiled for a stand-up meeting.\n\nDuring the stand-up, each person shares their answers to the five questions. To sustain a learning-centered culture, the fifth question is the most important question to answer. It allows individual reflection focused on learning. Sometimes this isn\u2019t an easy question to answer. It makes us stretch. It makes us think.\n\nBy sharing our individual answers to the fifth question, we open ourselves up to the group. When we honestly share what we\u2019ve learned, we openly admit that we didn\u2019t know something. Sharing like this would be scary (and even risky) if we didn\u2019t have a learning-centered culture.\n\nWe often share the actual process of how we learned something. By listening, each of us is invited to learn more about the topic at hand, consider what more there is to learn about that topic, and even gain insights into other methods of learning\u2014which can be applied to other topics.\n\nSharing the answers to the fifth question also allows opportunities for further conversations. We often take what someone has individually learned and find ways to apply it for our entire team in support of our organization. We are, after all, learning together.\n\nBuilding individual learners\n\nWe strive to grow together as a team at Center Centre, but we don\u2019t lose sight of the importance of the individuals who form our team. As individuals, we bring our goals, dreams, abilities, and prior knowledge to the team.\n\nTo build learning teams, we must build individual learners. A team made up of lifelong learners, who share their learning and learn from each other, is a team that will continually produce better results.\n\nAs a manager, I need to meet each direct where they are with their current abilities and knowledge. Then, I can help them take their skills and knowledge base to the next levels. This process requires each individual direct to engage in professional development.\n\nWe believe effective managers help their directs engage in behaviors that support growth and development. Effective managers encourage and support learning.\n\n\n\nOur weekly one-on-ones\n\nOne way we encourage learning is through weekly one-on-ones. Each of my directs meets with me, individually, for thirty minutes each week. The meeting is their meeting. It is not my meeting.\n\nMy direct sets the agenda. They talk about what they want to talk about. They can talk about work. They can talk about things outside of work. They can talk about their health, their kids, and even their cat. Whatever is important to them is important to me. I listen. I take notes.\n\nAlthough the direct sets the specific agenda, the meeting has three main parts. Approximately ten minutes for them (the direct), ten minutes for me (the manager), and ten minutes for us to talk about their future within\u2014and beyond\u2014our organization.\n\nCoaching for future performance\n\nThe final third of our one-on-one is when I coach my directs. Coaching looks to the direct\u2019s future performance. It focuses on developing the direct\u2019s skills.\n\nCoaching isn\u2019t hard. It doesn\u2019t take much time. For me, it usually takes less than five minutes a week during a one-on-one.\n\nThe first time I coach one of my directs, I ask them to brainstorm about the skills they want to improve. They usually already have an idea about this. It\u2019s often something they\u2019ve wanted to work on for some time, but didn\u2019t think they had the time or the knowhow to improve.\n\nIf a direct doesn\u2019t know what they want to improve, we discuss their job responsibilities\u2014specifically the aspects of the job that concern them.\n\nCoaching provides an opportunity for me to ask, \u201cIn your job, what are the required skills that you feel like you don\u2019t have (or know well enough, or perform effectively, or use with ease)?\u201d\n\nSometimes I have to remind a direct that it\u2019s okay not to know how to do something (even if it\u2019s a required part of their job). After all, our organization is a learning organization. In a learning organization, no one knows everything but everyone is willing to learn anything.\n\nAfter we review the job responsibilities together, I ask my direct what skill they\u2019d like to work to improve. Whatever they choose, we focus on that skill for coaching\u2014I\u2019ve found my directs work better when they\u2019re internally motivated.\n\nSometimes the first time I talk with a direct about coaching, they get a bit anxious. If this happens, I share a personal story about my professional learning journey. I say something like:\n\n\n\tI didn\u2019t know how to make a school before we started to make Center Centre.\n\n\tI didn\u2019t know how to manage an entire team of people\u2014day in and day out\u2014until I started managing a team of people every day.\n\n\tWhen I realized that I was the boss\u2014and that the success of the school would hinge, at least in part, on my skills as a manager\u2014I was a bit terrified. I was missing an important skill set that I needed to know (and I needed to know well).\n\n\tWhen I first understood this, I felt bad\u2014like I should have already known how to be a great manager. But then I realized, I\u2019d never faced this situation. I\u2019d never needed to know how to use this skill set in this way.\n\n\tI worked through my anxiety about feeling inadequate. I decided I\u2019d better learn how to be an effective manager because the school needed me to be one. You needed me to be one.\n\n\tEvery day, I work to improve my management skills. You\u2019ve probably noticed that some days I\u2019m better at it than others. I try not to beat myself up about this, although it\u2019s hard\u2014I\u2019d like to be perfect at it. But I\u2019m not.\n\n\tI know that if I make a conscious, daily effort to learn how to be a better manager, I\u2019ll continue to improve. So that\u2019s what I do.\n\n\tEvery day I learn. I learn by doing. I learn how to be better than I was the day before. That\u2019s what I ask of you.\n\n\nOnce we determine the skill the direct wants to learn, we figure out how they can go about learning it. I ask: \u201cHow could you learn this skill?\u201d\n\nWe brainstorm for two or three minutes about this. We write down every idea that comes to mind, and we write it so both of us can easily see the options (both whiteboards and sticky notes on the wall work well for this exercise).\n\n\n\tRead a book. Research online. Watch a virtual seminar. Listen to a podcast. Talk to a mentor. Reach out to an expert. Attend a conference. Shadow someone else while they do the skill. Join a professional organization.\n\n\nThe goal is to get the direct on a path of self-development. I\u2019m coaching their development, but I\u2019m not the main way my direct will learn this new skill.\n\nI ask my direct which path seems like the best place to start. I let them choose whatever option they want (as long as it works with our budget). They are more likely to follow through if they are in control of this process.\n\nNext, we work to break down the selected path into tasks. We only plan one week\u2019s worth of tasks. The tasks are small, and the deadlines are short. My direct reports when each task is completed.\n\nAt our next one-on-one, I ask my direct about their experience learning this new skill.\n\nRinse. Repeat.\n\nThat\u2019s it. I spend five minutes a week talking with each direct about their individual learning. They develop their professional skills, and together we\u2019re creating a learning-centered culture.\n\nAsking questions I don\u2019t know the answer to\n\nWhen my direct said, \u201cI\u2019ve never worked where people are so honest and transparent about things,\u201d it led me to believe that all this is working. We are building a learning-centered culture.\n\nThis week I was reminded that creating a learning-centered culture starts not just with the staff, but with me. When I challenge myself to learn and then share what I\u2019m currently learning, my directs want to learn more about what I\u2019m learning about.\n\nFor example, I decided I needed to improve my writing skills. A few weeks ago, I realized that I was sorely out of practice and I felt like I had lost my voice. So I started to write. I put words on paper. I felt overwhelmed. I felt like I didn\u2019t know how to write anymore (at least not well or effectively).\n\nI bought some books on writing (mostly Peter Elbow\u2019s books like Writing with Power, Writing Without Teachers, and Vernacular Eloquence), and I read them. I read them all. Reading these books was part of my personal coaching. I used the same steps to coach myself as I use with my directs when I coach them.\n\nIn stand-ups, I started sharing what I accomplished (like I completed one of the books) and what I learned by doing\u2014specific things, like engaging in freewriting and an open-ended writing process.\n\nThis week, I went to lunch with one of my directs. She said, \u201cYou\u2019ve been talking about freewriting a lot. You\u2019re really excited about it. Freewriting seems like it\u2019s helping your writing process. Would you tell me more about it?\u201d\n\nSo I shared the details with her. I shared the reasons why I think freewriting is helping. I\u2019m not focused on perfection. Instead, each day I\u2019m focused on spending ten, uninterrupted minutes writing down whatever comes to my mind. It\u2019s opening my writing mind. It\u2019s allowing my words to flow more freely. And it\u2019s helping me feel less self-conscious about my writing.\n\nShe said, \u201cLeslie, when you say you\u2019re self-conscious about your writing, I laugh. Not because it\u2019s funny. But because when I read what you write, I think, \u2018What is there to improve?\u2019 I think you\u2019re a great writer. It\u2019s interesting to know that you think you can be a better writer. I like learning about your learning process. I think I could do freewriting. I\u2019m going to give it a try.\u201d\n\nThere\u2019s something magical about all of this. I\u2019m not even sure I can eloquently put it into words. I just know that our working environment is something very different. I\u2019ve never experienced anything quite like it. Somehow, by sharing that I don\u2019t know everything and that I\u2019m always working to learn more, I invite my directs to be really open about what they don\u2019t know. And they see it\u2019s possible always to learn and grow.\n\nI\u2019m glad I ignore all the lawyering I\u2019ve learned from watching TV. I\u2019m glad I ask the questions I don\u2019t know the answers to. And I\u2019m glad my directs do the same. When we meet for learning, we accelerate and amplify the learning process\u2014building individual learners and learning teams. Embracing the unknown and working toward understanding is what makes our culture a learning-centered culture.\n\nPhotos by Summer Kohlhorst.", "year": "2014", "author": "Leslie Jensen-Inman", "author_slug": "lesliejenseninman", "published": "2014-12-20T00:00:00+00:00", "url": "https://24ways.org/2014/meet-for-learning/", "topic": "process"} {"rowid": 224, "title": "Go Forth and Make Awesomeness", "contents": "We\u2019ve all dreamed of being a superhero: maybe that\u2019s why we\u2019ve ended up on the web\u2014a place where we can do good deeds and celebrate them on a daily basis. \n\nWear your dreams\n\nAt age four, I wore my Wonder Woman Underoos around my house, my grandparents\u2019 house, our neighbor\u2019s house, and even around the yard. I wanted to be a superhero when I grew up. I was crushed to learn that there is no school for superheroes\u2014no place to earn a degree in how to save the world from looming evil. Instead, I\u2014like everyone else\u2014was destined to go to ordinary school to focus on ABCs and 123s. Even still, I want to save the world.\n\nIntend your goodness\n\nRandom acts of kindness make a difference. Books, films, and advertising campaigns tout random acts of kindness and the positive influence they can have on the world. But why do acts of kindness have to be so random? Why can\u2019t we intend to be kind? A true superhero wakes each morning intending to perform selfless acts for the community. Why can\u2019t we do the same thing?\n\nAs a child, my mother taught me to plan to do at least three good deeds each day. And even now, years later, I put on my invisible cape looking for ways to do good.\n\nHere are some examples:\n\n\tslowing down to allow another driver in before me from the highway on-ramp\n\tbringing a co-worker their favorite kind of coffee or tea\n\tsharing my umbrella on a rainy day\n\tholding a door open for someone with full hands\n\tlistening intently when someone shares a story\n\tcomplimenting someone on a job well done\n\tthanking someone for a job well done\n\tleaving a constructive, or even supportive comment on someone\u2019s blog\n\n\nAs you can see, these acts are simple. Doing good and being kind is partially about being aware\u2014aware of the words we speak and the actions we take. Like superheroes, we create our own code of conduct to live by. Hopefully, we choose to put the community before ourselves (within reason) and to do our best not to damage it as we move through our lives.\n\nTake a bite out of the Apple\n\nWith some thought, we can weave this type of thinking and action into our business choices. We can take the simple acts of kindness concept and amplify it a bit. With this amplification, we can be a new kind of superhero.\n\nIn 1997, during a presentation, Steve Jobs stated Apple\u2019s core value in a simple, yet powerful, sentence:\n\n\n\tWe believe that people with passion can change the world for the better.\n\n\nApple fan or not, those are powerful words.\n\nDefine your core\n\nEvery organization must define its core values. Core values help us to frame, recognize, and understand the principles our organization embodies and practices. It doesn\u2019t matter if you\u2019re starting a new organization or you want to define values within an existing organization. Even if you\u2019re a freelancer, defining core values will help guide your decisions and actions.\n\nIf you can, work as a team to define core values. Gather the people who are your support system\u2014your business partners, your colleagues, and maybe even a trusted client\u2014this is now your core value creation team. Have a brainstorming session with your team. Let ideas flow. Give equal weight to the things people say. You may not hear everything you thought you might hear\u2014that\u2019s OK. You want the session to be free-flowing and honest. Ask yourself and your team questions like:\n\n\n\tWhat do you think my/our/your core values are?\n\tWhat do you think my/our/your priorities are?\n\tWhat do you think my/our/your core values should be?\n\tWhat do you think my/our/your priorities should be?\n\tHow do you think I/we should treat customers, clients, and each other?\n\tHow do we want others to treat us?\n\tWhat are my/our/your success stories?\n\tWhat has defined these experiences as successful?\n\n\nFrom this brainstorming session, you will craft your superhero code of conduct. You will decide what you will and will not do. You will determine how you will and will not act. You\u2019re setting the standards that you will live and work by\u2014so don\u2019t take this exercise lightly. Take your time. Use the exercise as a way to open a discussion about values. Find out what you and your team believe in. Set these values and keep them in place. Write them down and share these with your team and with the world. By sharing your core values, you hold yourself more accountable to them. You also send a strong message to the rest of the world about what type of organization you are and what you believe in. Other organizations and people may decide to align or not to align themselves with you because of your core values. This is good. Chances are, you\u2019ll be happier and more profitable if you work with other organizations and people who share similar core values.\n\n Photo: Laura Winn\n\nDuring your brainstorming session, list keywords. Don\u2019t edit. Allow things to take their course. Some examples of keywords might be:\n\nAbility \u00b7 Achievement \u00b7 Adventure \u00b7 Ambition \u00b7 Altruism \u00b7 Awareness \u00b7 Balance \u00b7 Caring \u00b7 Charity \u00b7 Citizenship \u00b7 Collaboration \u00b7 Commitment \u00b7 Community \u00b7 Compassion \u00b7 Consideration \u00b7 Cooperation \u00b7 Courage \u00b7 Courtesy \u00b7 Creativity \u00b7 Democracy \u00b7 Dignity \u00b7 Diplomacy \u00b7 Discipline \u00b7 Diversity \u00b7 Education \u00b7 Efficiency \u00b7 Energy \u00b7 Equality \u00b7 Excellence \u00b7 Excitement \u00b7 Fairness \u00b7 Family \u00b7 Freedom \u00b7 Fun \u00b7 Goodness \u00b7 Gratefulness \u00b7 Growth \u00b7 Happiness \u00b7 Harmony \u00b7 Helping \u00b7 Honor \u00b7 Hope \u00b7 Humility \u00b7 Humor \u00b7 Imagination \u00b7 Individuality \u00b7 Innovation \u00b7 Integrity \u00b7 Intelligence \u00b7 Joy \u00b7 Justice \u00b7 Kindness \u00b7 Knowledge \u00b7 Leadership \u00b7 Learning \u00b7 Loyalty \u00b7 Meaning \u00b7 Mindfulness \u00b7 Moderation \u00b7 Modesty \u00b7 Nurture \u00b7 Openness \u00b7 Organization \u00b7 Passion \u00b7 Patience \u00b7 Peace \u00b7 Planning \u00b7 Principles \u00b7 Productivity \u00b7 Purpose \u00b7 Quality \u00b7 Reliability \u00b7 Respectfulness \u00b7 Responsibility \u00b7 Security \u00b7 Sensitivity \u00b7 Service \u00b7 Sharing \u00b7 Simplicity \u00b7 Stability \u00b7 Tolerance \u00b7 Transparency \u00b7 Trust \u00b7 Truthfulness \u00b7 Understanding \u00b7 Unity \u00b7 Variety \u00b7 Vision \u00b7 Wisdom\n\nAfter you have a list of keywords, create your core values statement using the themes from your brainstorming session. There are no rules: while above, Steve Jobs summed up Apple\u2019s core values in one sentence, Zappos has ten core values:\n\n\n\tDeliver WOW Through Service\n\tEmbrace and Drive Change\n\tCreate Fun and A Little Weirdness\n\tBe Adventurous, Creative, and Open-Minded\n\tPursue Growth and Learning\n\tBuild Open and Honest Relationships With Communication\n\tBuild a Positive Team and Family Spirit\n\tDo More With Less\n\tBe Passionate and Determined\n\tBe Humble\n\n\nTo see how Zappos\u2019 employees embrace these core values, watch the video they created and posted on their website.\n\nDog food is yummy\n\nAlthough I find merit in every keyword listed, I\u2019ve distilled my core values to their simplest form:\n\nMake awesomeness. Do good.\n\nHow do you make awesomeness and do good? You need ambition, balance, collaboration, commitment, fun, and you need every keyword listed to support these actions. Again, there are no rules: your core values can be one sentence or a bulleted list. What matters is being true to yourself and creating core values that others can understand. Before I start any project I ask myself: is there a way to make awesomeness and to do good? If the answer is \u201cyes,\u201d I embrace the endeavor because it aligns with my core values. If the answer is \u201cno,\u201d I move on to a project that supports my core values.\n\nUnleash your powers\n\nAlthough every organization will craft different core values, I imagine that you want to be a superhero and that you will define \u201cdoing good\u201d (or something similar) as one of your core values. Whether you work by yourself or with a team, you can use the web as a tool to help do good. It can be as simple as giving a free hug, or something a little more complex to help others and help your organization meet the bottom line. Some interesting initiatives that use the web to do good are:\n\n\n\tYahoo!: How Good Grows\n\tDesigual: Happy Hunters\n\tEdge Shave Gel: Anti-irritation campaign\n\n\n\n\nKnowing your underlying desire to return to your Underoos-and-cape-sporting childhood and knowing that you don\u2019t always have the opportunity to develop an entire initiative to \u201cdo good,\u201d remember that as writers, designers, and developers, we can perform superhero acts on a daily basis by making content, design, and development accessible to the greatest number of people. By considering other people\u2019s needs, we are intentionally performing acts of kindness\u2014we\u2019re doing good. There are many ways to write, design, and develop websites\u2014many of which will be discussed in other 24ways.org articles. As we make content, design, and development decisions\u2014as we develop campaigns and initiatives\u2014we need to keep our core values in mind. It\u2019s easy to make a positive difference in the world. Just be the superhero you\u2019ve always wanted to be. Go forth and make awesomeness.\n\nIf you would like to do good today, support The United Nations Children\u2019s Fund, an organization that works for children\u2019s rights, their survival, development and protection, by purchasing this year\u2019s 24 ways Annual 2010 created by Five Simple Steps. All proceeds go to UNICEF.", "year": "2010", "author": "Leslie Jensen-Inman", "author_slug": "lesliejenseninman", "published": "2010-12-04T00:00:00+00:00", "url": "https://24ways.org/2010/go-forth-and-make-awesomeness/", "topic": "business"} {"rowid": 92, "title": "Redesigning the Media Query", "contents": "Responsive web design is showing us that designing content is more important than designing containers. But if you\u2019ve given RWD a serious try, you know that shifting your focus from the container is surprisingly hard to do. There are many factors and\ninstincts working against you, and one culprit is a perpetrator you\u2019d least suspect.\n\nThe media query is the ringmaster of responsive design. It lets us establish the rules of the game and gives us what we need most: control. However, like some kind of evil double agent, the media query is actually working against you.\n\nIts very nature diverts your attention away from content and forces you to focus on the container.\n\nThe very act of choosing a media query value means choosing a screen size.\n\nLook at the history of the media query\u2014it\u2019s always been about the container. Values like screen, print, handheld and tv don\u2019t have anything to do with content. The modern media query lets us choose screen dimensions, which is great because it makes RWD possible. But it\u2019s still the act of choosing something that is completely unpredictable.\n\nContent should dictate our breakpoints, not the container. In order to get our focus back to the only thing that matters, we need a reengineered media query\u2014one that frees us from thinking about screen dimensions. A media query that works for your content, not the window. Fortunately, Sass 3.2 is ready and willing to take on this challenge.\n\nThinking in Columns\n\nFluid grids never clicked for me. I feel so disoriented and confused by their squishiness. Responsive design demands their use though, right?\n\nI was ready to surrender until I found a grid that turned my world upright again. The Frameless Grid by Joni Korpi demonstrates that column and gutter sizes can stay fixed. As the screen size changes, you simply add or remove columns to accommodate. This made sense to me and armed with this concept I was able to give Sass the first component it needs to rewrite the media query: fixed column and gutter size variables.\n\n$grid-column: 60px;\n$grid-gutter: 20px;\n\nWe\u2019re going to want some resolution independence too, so let\u2019s create a function that converts those nasty pixel values into ems.\n\n@function em($px, $base: $base-font-size) {\n\t@return ($px / $base) * 1em;\n}\n\nWe now have the components needed to figure out the width of multiple columns in ems. Let\u2019s put them together in a function that will take any number of columns and return the fixed width value of their size.\n\n@function fixed($col) {\n\t@return $col * em($grid-column + $grid-gutter)\n}\n\nWith the math in place we can now write a mixin that takes a column count as a parameter, then generates the perfect media query necessary to fit that number of columns on the screen. We can also build in some left and right margin for our layout by adding an additional gutter value (remembering that we already have one gutter built into our fixed function).\n\n@mixin breakpoint($min) {\n\t@media (min-width: fixed($min) + em($grid-gutter)) {\n\t\t@content\n\t}\n}\n\nAnd, just like that, we\u2019ve rewritten the media query. Instead of picking a minimum screen size for our layout, we can simply determine the number of columns needed. Let\u2019s add a wrapper class so that we can center our content on the screen.\n\n@mixin breakpoint($min) {\n @media (min-width: fixed($min) + em($grid-gutter)) {\n\t.wrapper {\n\t\twidth: fixed($min) - em($grid-gutter);\n\t\tmargin-left: auto; margin-right: auto;\n\t}\n\t@content\n }\n}\n\nDesigning content with a column count gives us nice, easy, whole numbers to work with. Sizing content, sidebars or widgets is now as simple as specifying a single-digit number.\n\n@include breakpoint(8) {\n\t.main { width: fixed(5); }\n\t.sidebar { width: fixed(3); }\n}\n\nThose four lines of Sass just created a responsive layout for us. When the screen is big enough to fit eight columns, it will trigger a fixed width layout. And give widths to our main content and sidebar. The following is the outputted CSS\u2026\n\n@media (min-width: 41.25em) {\n .wrapper {\n width: 38.75em;\n margin-left: auto; margin-right: auto;\n }\n .main { width: 25em; }\n .sidebar { width: 15em; }\n}\n\nDemo\n\nI\u2019ve created a Codepen demo that demonstrates what we\u2019ve covered so far. I\u2019ve added to the demo some grid classes based on Griddle by Nicolas Gallagher to create a floatless layout. I\u2019ve also added a CSS gradient overlay to help you visualize columns. Try changing the column variable sizes or the breakpoint includes to see how the layout reacts to different screen sizes.\n\nResponsive Images\n\nResponsive images are a serious problem, but I\u2019m excited to see the community talk so passionately about a solution. Now, there are some excellent stopgaps while we wait for something official, but these solutions require you to mirror your breakpoints in JavaScript or HTML. This poses a serious problem for my Sass-generated media queries, because I have no idea what the real values of my breakpoints are anymore. For responsive images to work, JavaScript needs to recognize which media query is active so that proper images can be loaded for that layout.\n\nWhat I need is a way to label my breakpoints. Fortunately, people much smarter than I have figured this out. Jeremy Keith devised a labeling method by using CSS-generated content as the storage method for breakpoint labels. We can use this technique in our breakpoint mixin by passing a label as another argument.\n\n@include breakpoint(8, 'desktop') { /* styles */ }\n\nSass can take that label and use it when writing the corresponding media query. We just need to slightly modify our breakpoint mixin.\n\n@mixin breakpoint($min, $label) {\n @media (min-width: fixed($min) + em($grid-gutter)) {\n\n // label our mq with CSS generated content\n\tbody::before { content: $label; display: none; }\n\n\t.wrapper {\n\t\twidth: fixed($min) - em($grid-gutter);\n\t\tmargin-left: auto; margin-right: auto;\n\t}\n\t@content\n }\n}\n\nThis allows us to label our breakpoints with a user-friendly string. Now that our media queries are defined and labeled, we just need JavaScript to step in and read which label is active.\n\n// get css generated label for active media query\nvar label = getComputedStyle(document.body, '::before')['content'];\n\nJavaScript now knows which layout is active by reading the label in the current media query\u2014we just need to match that label to an image. I prefer to store references to different image sizes as data attributes on my image tag.\n\n\n\n\nThese data attributes have names that match the labels set in my CSS. So while there is some duplication going on, setting a keyword like \u2018tablet\u2019 in two places is much easier than hardcoding media query values. With matching labels in CSS and HTML our script can marry the two and load the right sized image for our layout.\n\n// get css generated label for active media query\nvar label = getComputedStyle(document.body, '::before')['content'];\n\n// select image\nvar $image = $('.responsive-image');\n\n// create source from data attribute\n$image.attr('src', $image.data(label));\n\nDemo\n\nWith some slight additions to our previous Codepen demo you can see this responsive image technique in action. While the above JavaScript will work it is not nearly robust enough for production so the demo uses a jQuery plugin that can accomodate multiple images, reloading on screen resize and fallbacks if something doesn\u2019t match up.\n\nCreating a Framework\n\nThis media query mixin and responsive image JavaScript are the center piece of a front end framework I use to develop websites. It\u2019s a fluid, mobile first foundation that uses the breakpoint mixin to structure fixed width layouts for tablet and desktop. Significant effort was focused on making this framework completely cross-browser. For example, one of the problems with using media queries is that essential desktop structure code ends up being hidden from legacy Internet Explorer. Respond.js is an excellent polyfill, but if you\u2019re comfortable serving a single desktop layout to older IE, we don\u2019t need JavaScript. We simply need to capture layout code outside of a media query and sandbox it under an IE only class name.\n\n// set IE fallback layout to 8 columns\n$ie-support = 8;\n\n// inside of our breakpoint mixin (but outside the media query)\n@if ($ie-support and $min <= $ie-support) {\n\t.lt-ie9 { @content; }\n}\n\nPerspective Regained\n\nThinking in columns means you are thinking about content layout. How big of a screen do you need for 12 columns? Who cares? Having Sass write media queries means you can use intuitive numbers for content layout. A fixed grid means more layout control and less edge cases to test than a fluid grid. Using CSS labels for activating responsive images means you don\u2019t have to duplicate breakpoints across separations of concern. \n\nIt\u2019s a harmonious blend of approaches that gives us something we need\u2014responsive design that feels intuitive. And design that, from the very outset, focuses on what matters most. Just like our kindergarten teachers taught us: It\u2019s what\u2019s inside that counts.", "year": "2012", "author": "Les James", "author_slug": "lesjames", "published": "2012-12-13T00:00:00+00:00", "url": "https://24ways.org/2012/redesigning-the-media-query/", "topic": "code"} {"rowid": 283, "title": "CSS3 Patterns, Explained", "contents": "Many of you have probably seen my CSS3 patterns gallery. It became very popular throughout the year and it showed many web developers how powerful CSS3 gradients really are. But how many really understand how these patterns are created? The biggest benefit of CSS-generated backgrounds is that they can be modified directly within the style sheet. This benefit is void if we are just copying and pasting CSS code we don\u2019t understand. We may as well use a data URI instead.\n\nImportant note\n\nIn all the examples that follow, I\u2019ll be using gradients without a vendor prefix, for readability and brevity. However, you should keep in mind that in reality you need to use all the vendor prefixes (-moz-, -ms-, -o-, -webkit-) as no browser currently implements them without a prefix. Alternatively, you could use -prefix-free and have the current vendor prefix prepended at runtime, only when needed.\n\nThe syntax described here is the one that browsers currently implement. The specification has since changed, but no browser implements the changes yet. If you are interested in what is coming, I suggest you take a look at the dev version of the spec.\n\nIf you are not yet familiar with CSS gradients, you can read these excellent tutorials by John Allsopp and return here later, as in the rest of the article I assume you already know the CSS gradient basics:\n\n\n\tCSS3 Linear Gradients\n\tCSS3 Radial Gradients\n\n\nThe main idea\n\nI\u2019m sure most of you can imagine the background this code generates:\n\nbackground: linear-gradient(left, white 20%, #8b0 80%);\n\nIt\u2019s a simple gradient from one color to another that looks like this:\n\n See this example live\n\nAs you probably know, in this case the first 20% of the container\u2019s width is solid white and the last 20% is solid green. The other 60% is a smooth gradient between these colors. Let\u2019s try moving these color stops closer to each other:\n\nbackground: linear-gradient(left, white 30%, #8b0 70%);\n\n See this example live\n\nbackground: linear-gradient(left, white 40%, #8b0 60%);\n\n See this example live\n\nbackground: linear-gradient(left, white 50%, #8b0 50%);\n\n See this example live\n\nNotice how the gradient keeps shrinking and the solid color areas expanding, until there is no gradient any more in the last example. We can even adjust the position of these two color stops to control where each color abruptly changes into another:\n\nbackground: linear-gradient(left, white 30%, #8b0 30%);\n\n See this example live\n\nbackground: linear-gradient(left, white 90%, #8b0 90%);\n\n See this example live\n\nWhat you need to take away from these examples is that when two color stops are at the same position, there is no gradient, only solid colors. Even without going any further, this trick is useful for a number of different use cases like faux columns or the effect I wanted to achieve in my homepage or the -prefix-free page where the background is only shown on one side and hidden on the other:\n\n\n\nCombining with background-size\n\nWe can do wonders, however, if we combine this with the CSS3 background-size property:\n\nbackground: linear-gradient(left, white 50%, #8b0 50%);\nbackground-size: 100px 100px;\n\n See this example live\n\nAnd there it is. We just created the simplest of patterns: (vertical) stripes. We can remove the first parameter (left) or replace it with top and we\u2019ll get horizontal stripes. However, let\u2019s face it: Horizontal and vertical stripes are kinda boring. Most stripey backgrounds we see on the web are diagonal. So, let\u2019s try doing that.\n\nOur first attempt would be to change the angle of the gradient to something like 45deg. However, this results in an ugly pattern like this: \n\n See this example live\n\nBefore reading on, think for a second: why didn\u2019t this produce the desired result? Can you figure it out?\n\nThe reason is that the gradient angle rotates the gradient inside each tile, not the tiled background as a whole. However, didn\u2019t we have the same problem the first time we tried to create diagonal stripes with an image? And then we learned that every stripe has to be included twice, like so:\n\n\n\nSo, let\u2019s try to create that effect with CSS gradients. It\u2019s essentially what we tried before, but with more color stops:\n\nbackground: linear-gradient(45deg, white 25%,\n #8b0 25%, #8b0 50%, \n white 50%, white 75%, \n #8b0 75%);\nbackground-size:100px 100px;\n\n See this example live\n\nAnd there we have our stripes! An easy way to remember the order of the percentages and colors it is that you always have two of the same in succession, except the first and last color.\n\nNote: Firefox for Mac also needs an additional 100% color stop at the end of any pattern with more than two stops, like so: ..., white 75%, #8b0 75%, #8b0). The bug was reported in February 2011 and you can vote for it and track its progress at Bugzilla.\n\nUnfortunately, this is essentially a hack and we will realize that if we try to change the gradient angle to 60deg:\n\n See this example live\n\nNot that maintainable after all, eh? Luckily, CSS3 offers us another way of declaring such backgrounds, which not only helps this case but also results in much more concise code:\n\nbackground: repeating-linear-gradient(60deg, white, white 35px, #8b0 35px, #8b0 70px);\n\n See this example live\n\nIn this case, however, the size has to be declared in the color stop positions and not through background-size, since the gradient is supposed to cover the entire container. You might notice that the declared size is different from the one specified the previous way. This is because the size of the stripes is measured differently: in the first example we specify the dimensions of the tile itself; in the second, the width of the stripes (35px), which is measured diagonally.\n\nMultiple backgrounds\n\nUsing only one gradient you can create stripes and that\u2019s about it. There are a few more patterns you can create with just one gradient (linear or radial) but they are more or less boring and ugly. Almost every pattern in my gallery contains a number of different backgrounds. For example, let\u2019s create a polka dot pattern:\n\nbackground: radial-gradient(circle, white 10%, transparent 10%),\nradial-gradient(circle, white 10%, black 10%) 50px 50px;\nbackground-size:100px 100px;\n\n See this example live\n\nNotice that the two gradients are almost the same image, but positioned differently to create the polka dot effect. The only difference between them is that the first (topmost) gradient has transparent instead of black. If it didn\u2019t have transparent regions, it would effectively be the same as having a single gradient, as the topmost gradient would obscure everything beneath it.\n\nThere is an issue with this background. Can you spot it?\n\nThis background will be fine for browsers that support CSS gradients but, for browsers that don\u2019t, it will be transparent as the whole declaration is ignored. We have two ways to provide a fallback, each for different use cases. We have to either declare another background before the gradient, like so:\n\nbackground: black;\nbackground: radial-gradient(circle, white 10%, transparent 10%),\nradial-gradient(circle, white 10%, black 10%) 50px 50px;\nbackground-size:100px 100px;\n\nor declare each background property separately:\n\nbackground-color: black;\nbackground-image: radial-gradient(circle, white 10%, transparent 10%),\nradial-gradient(circle, white 10%, transparent 10%);\nbackground-size:100px 100px;\nbackground-position: 0 0, 50px 50px;\n\nThe vigilant among you will have noticed another change we made to our code in the last example: we altered the second gradient to have transparent regions as well. This way background-color serves a dual purpose: it sets both the fallback color and the background color of the polka dot pattern, so that we can change it with just one edit. Always strive to make code that can be modified with the least number of edits. You might think that it will never be changed in that way but, almost always, given enough time, you\u2019ll be proved wrong.\n\nWe can apply the exact same technique with linear gradients, in order to create checkerboard patterns out of right triangles:\n\nbackground-color: white;\nbackground-image: linear-gradient(45deg, black 25%, transparent 25%, transparent 75%, black 75%), \nlinear-gradient(45deg, black 25%, transparent 25%, transparent 75%, black 75%);\nbackground-size:100px 100px;\nbackground-position: 0 0, 50px 50px;\n\n See this example live\n\nUsing the right units\n\nDon\u2019t use pixels for the sizes without any thought. In some cases, ems make much more sense. For example, when you want to make a lined paper background, you want the lines to actually follow the text. If you use pixels, you have to change the size every time you change font-size. If you set the background-size in ems, it will naturally follow the text and you will only have to update it if you change line-height.\n\nIs it possible?\n\nThe shapes that can be achieved with only one gradient are:\n\n\n\tstripes\n\tright triangles\n\tcircles and ellipses\n\tsemicircles and other shapes formed from slicing ellipses horizontally or vertically\n\n\nYou can combine several of them to create squares and rectangles (two right triangles put together), rhombi and other parallelograms (four right triangles), curves formed from parts of ellipses, and other shapes.\n\nJust because you can doesn\u2019t mean you should\n\nTechnically, anything can be crafted with these techniques. However, not every pattern is suitable for it. The main advantages of this technique are:\n\n\n\tno extra HTTP requests\n\tshort code\n\thuman-readable code (unlike data URIs) that can be changed without even leaving the CSS file.\n\n\nComplex patterns that require a large number of gradients are probably better left to SVG or bitmap images, since they negate almost every advantage of this technique:\n\n\n\tthey are not shorter\n\tthey are not really comprehensible \u2013 changing them requires much more effort than using an image editor\n\n\nThey still save an HTTP request, but so does a data URI.\n\nI have included some very complex patterns in my gallery, because even though I think they shouldn\u2019t be used in production (except under very exceptional conditions), understanding how they work and coding them helps somebody understand the technology in much more depth.\n\nAnother rule of thumb is that if your pattern needs shapes to obscure parts of other shapes, like in the star pattern or the yin yang pattern, then you probably shouldn\u2019t use it. In these patterns, changing the background color requires you to also change the color of these shapes, making edits very tedious.\n\nIf a certain pattern is not practicable with a reasonable amount of CSS, that doesn\u2019t mean you should resort to bitmap images. SVG is a very good alternative and is supported by all modern browsers.\n\nBrowser support\n\nCSS gradients are supported by Firefox 3.6+, Chrome 10+, Safari 5.1+ and Opera 11.60+ (linear gradients since Opera 11.10). Support is also coming in Internet Explorer when IE10 is released. You can get gradients in older WebKit versions (including most mobile browsers) by using the proprietary -webkit-gradient(), if you really need them.\n\nEpilogue\n\nI hope you find these techniques useful for your own designs. If you come up with a pattern that\u2019s very different from the ones already included, especially if it demonstrates a cool new technique, feel free to send a pull request to the github repo of the patterns gallery. Also, I\u2019m always fascinated to see my techniques put in practice, so if you made something cool and used CSS patterns, I\u2019d love to know about it!\n\nHappy holidays!", "year": "2011", "author": "Lea Verou", "author_slug": "leaverou", "published": "2011-12-16T00:00:00+00:00", "url": "https://24ways.org/2011/css3-patterns-explained/", "topic": "code"} {"rowid": 1, "title": "Why Bother with Accessibility?", "contents": "Web accessibility (known in other fields as inclusive design or universal design) is the degree to which a website is available to as many people as possible. Accessibility is most often used to describe how people with disabilities can access the web.\n\nHow we approach accessibility\n\nIn the web community, there\u2019s a surprisingly inconsistent approach to accessibility. There are some who are endlessly dedicated to accessible web design, and there are some who believe it so intrinsic to the web that it shouldn\u2019t be considered a separate topic. Still, of those who are familiar with accessibility, there\u2019s an overwhelming number of designers, developers, clients and bosses who just aren\u2019t that bothered.\n\nOver the last few months I\u2019ve spoken to a lot of people about accessibility, and I\u2019ve heard the same reasons to ignore it over and over again. Let\u2019s take a look at the most common excuses.\n\nExcuse 1: \u201cPeople with disabilities don\u2019t really use the web\u201d\n\nAccessibility will make your site available to more people \u2014 the inclusion case\n\nIn the same way that the accessibility of a building isn\u2019t just about access for wheelchair users, web accessibility isn\u2019t just about blind users and screen readers. We can affect positively the lives of many people by making their access to the web easier.\n\nThere are four main types of disability that affect use of the web:\n\n\n\tVisual\n\tBlindness, low vision and colour-blindness\n\tAuditory\n\tProfoundly deaf and hard of hearing\n\tMotor\n\tThe inability to use a mouse, slow response time, limited fine motor control\n\tCognitive\n\tLearning difficulties, distractibility, the inability to focus on large amounts of information\n\n\nNone of these disabilities are completely black and white\n\nExamining deafness, it\u2019s clear from the medical scale that there are many grey areas between full hearing and total deafness:\n\n\n\tmild\n\tmoderate\n\tmoderately severe\n\tsevere\n\tprofound\n\ttotally deaf\n\n\nFor eyesight, and brain conditions that affect what users see, there is a huge range of conditions and challenges:\n\n\n\tastigmatism\n\tcolour blindness\n\takinetopsia (motion blindness)\n\tscotopic visual sensitivity (visual stress related to light)\n\tvisual agnosia (impaired recognition or identification of objects)\n\n\nWhile we might have medical and government-recognised definitions that tell us what makes a disability, day-to-day life is not so straightforward. People experience varying degrees of different conditions, and often one or more conditions at a time, creating a false divide when you view disability in terms of us and them.\n\nImpairments aren\u2019t always permanent\n\nAs we age, we\u2019re more likely to experience different levels of visual, auditory, motor and cognitive impairments. We might have an accident or illness that affects us temporarily. We might struggle more earlier or later in the day. There are so many little physiological factors that affect the way people interact with the web that we can\u2019t afford to make any assumptions based on our own limited experiences.\n\nImpairments might be somewhere between the user and the website\n\nThere are also impairments that aren\u2019t directly related to the user. Environmental factors have a huge effect on the way people interact with the web. These could be:\n\n\n\tLow bandwidth, or intermittent internet connection\n\tBright light, rain, or other weather-based conditions\n\tNoisy environments, or a location where the user doesn\u2019t want to disturb their neighbours with sound\n\tBrowsing with mobile devices, games consoles and other non-desktop devices\n\tBrowsing with legacy browsers or operating systems\n\n\nSuch environmental factors show that it\u2019s not just those with physical impairments who benefit from more accessible websites. We started designing responsive websites so we could be more future-friendly, and with a shared goal of better optimised experiences, accessibility should be at the core of responsive web design.\n\nExcuse 2: \u201cWe don\u2019t want to affect the experience for the majority of our users\u201d\n\nAccessibility will improve your site for all your users \u2014 the usability case\n\nOn a basic level, the different disability groups, as shown in the inclusion case, equate to simple usability goals:\n\n\n\tVisual \u2013 make it easy to read\n\tAuditory \u2013 make it easy to hear\n\tMotor \u2013 make it easy to interact\n\tCognitive \u2013 make it easy to understand and focus\n\n\nTaking care to ensure good usability in these areas will also have an impact on accessibility. Unless your site is catering specifically to a particular disability, where extreme optimisation is most beneficial, taking care to design with accessibility in mind will rarely negatively affect the experience of your wider audience.\n\nExcuse 3: \u201cWe don\u2019t have the budget for accessibility\u201d\n\nAccessibility will make you money \u2014 the business case\n\nBy reducing your audience through ignoring accessibility, you\u2019re potentially excluding the income from those users. Designing with accessibility in mind from the beginning of a project makes it easier to make small inexpensive optimisations as part of the design and development process, rather than bolting on costly updates to increase your potential audience later on.\n\nThe following are excerpts from a white paper about companies that increased the accessibility of their websites to comply with government regulation.\n\n\n\tImprovements in accessibility doubled Legal and General\u2019s life insurance sales online.\n\n\n\n\tImprovements in accessibility increased Tesco\u2019s grocery home delivery sales by \u00a313 million in 2005\u2026 To their surprise they found that many normal visitors preferred the ease of navigation and improved simplicity of the [parallel] accessible site and switched to use it. Tesco have replaced their \u2018normal\u2019 site with their accessible version and expect a further increase in revenues.\n\n\n\n\tImprovements in accessibility increased Virgin.net sales by 68%.\n\n\nStatistics all from WSI white paper: Improve your website\u2019s usability and accessibility to increase sales (PDF).\n\nExcuse 4: \u201cAccessible websites are ugly\u201d\n\nAccessibility won\u2019t stop your site from being beautiful \u2014 the beauty case\n\nMany people use ugly accessible websites as proof that all accessible websites are ugly. This just isn\u2019t the case. I\u2019ve compiled some examples of beautiful and accessible websites with screenshots of how they look through the Color Oracle simulator and how they perform when run through Webaim\u2019s Wave accessibility checker tool.\n\nWhile automated tools are no substitute for real users, they can help you learn more about good practices, and give you guidance on where your site needs improvements to make it more accessible.\n\nAmazon.co.uk\n\nIt may not be a decorated beauty, but Amazon is often first in functional design. It\u2019s a huge website with a lot of interactive content, but it generates just five errors on the Wave test, and is easy to read under a Color Oracle filter.\n\n Screenshot of Amazon website\n Screenshot of Amazon\u2019s Wave results \u2013 five errors\n Screenshot of Amazon through a Color Oracle filter\n\n24 ways\n\nWhen Tim Van Damme redesigned 24 ways back in 2007, it was a striking and unusual design that showed what could be achieved with CSS and some imagination. Despite the complexity of the design, it gets an outstanding zero errors on the Wave test, and is still readable under a Color Oracle filter.\n\n Screenshot of pre-2013 24 ways website design\n Screenshot of 24 ways Wave results \u2013 zero errors\n Screenshot of 24ways through a Color Oracle filter\n\nOpera\u2019s Shiny Demos\n\nDemos and prototypes are notorious for ignoring accessibility, but Opera\u2019s Shiny Demos site shows how exploring new technologies doesn\u2019t have to exclude anyone. It only gets one error on the Wave test, and looks fine under a Color Oracle filter.\n\n Screenshot of Opera\u2019s Shiny Demos website\n Screenshot of Opera\u2019s Shiny Demos Wave results \u2013 1 error\n Screenshot of Opera\u2019s Shiny Demos through a Color Oracle filter\n\nSoundCloud\n\nWhen a site is more app-like, relying on more interaction from the user, accessibility can be more challenging. However, SoundCloud only gets one error on the Wave test, and the colour contrast holds up well under a Color Oracle filter.\n\n Screenshot of SoundCloud website\n Screenshot of SoundCloud\u2019s Wave results \u2013 one error\n Screenshot of SoundCloud through a Color Oracle filter\n\nEducation and balance\n\nAs with most web design, doing accessibility well is about combining your knowledge of accessibility with your project\u2019s context to create a balance that serves your users\u2019 needs. Your types of content and interactions will dictate one set of constraints. Your users\u2019 needs and goals will dictate another. In broad terms, web design as a practice is finding the equilibrium between these constraints.\n\nAnd then there\u2019s just caring. The web as a platform is open, affordable and available to many. Accessibility is our way to ensure that nobody gets shut out.", "year": "2013", "author": "Laura Kalbag", "author_slug": "laurakalbag", "published": "2013-12-10T00:00:00+00:00", "url": "https://24ways.org/2013/why-bother-with-accessibility/", "topic": "design"} {"rowid": 93, "title": "Design Systems", "contents": "The most important part of responsive web design is that, no matter what the viewport width, the content is accessible in an optimum display. The best responsive designs are those that allow you to go from one optimised display to another, but with the feeling that these experiences are part of a greater product whole.\n\nResponsive design: where we\u2019ve been going wrong\n\nResponsive web design was a shock to my web designer system. Those of us who had already been designing sites for mobile probably had the biggest leap to make. We might have been detecting user agents in order to deliver a mobile-specific site, or using the slightly more familiar Bushido technique to deliver sites optimised for device type and viewport size, but either way our focus was on devices. A site was optimised for either a mobile phone or a desktop.\n\nResponsive web design brought us back to pre-table layout fluid sites that expanded or contracted to fit the viewport. This was a big difference to get our heads around when we were so used to designing for fixed-width layouts. Suddenly, an element could be any width or, at least, we needed to consider its maximum and minimum widths. Pixel perfection, while pretty, became wholly unrealistic, and a whole load of designers who prided themselves in detailed and precise designs got a bit scared.\n\nHanging on to our previous processes and typical deliverables led us to continue to optimise our sites for particular devices and provide pixel-perfect mockups for those device widths.\n\nWith all this we were concentrating on devices, not content, deliverables and not process, and making assumptions about users and their devices based on nothing but the width of the viewport.\n\nI don\u2019t think this is a crime, I think it was inevitable.\n\nWe can be up to date with our principles and ideals, but it\u2019s never as easy in practice. That\u2019s why it\u2019s more important than ever to share our successful techniques and processes. Let\u2019s drag each other into modern web design.\n\nDesign systems: the principles\n\nWhat are design systems?\n\nA visual design system is built out of the core components of typography, layout, shape or form, and colour. When considering the design of a whole product, a design system should also include patterns in user flow, content strategy, copy, and tone of voice. These concepts, design decisions or rules, created around the core components are used consistently across your product to create a cohesive feel, whether it\u2019s from one element to another, page to page, or viewport width to viewport width.\n\nResponsive design is one of the most important considerations in the components of a design system. For each component, you must decide what will unite the design across the viewports to maintain that consistent feel, and what parts of the design will differentiate in order to provide a flexible and optimal experience for different viewport sizes.\n\nComponents you might keep the same across viewports\n\n\n\ttypeface\n\tbase unit\n\tcolour\n\tshape/form\n\n\nComponents you might differentiate across viewports\n\n\n\tgrids\n\tlayout\n\tfont size\n\tmeasure (line length)\n\tleading (line height)\n\n\nContent: it must always be the same\n\nThe focus of a design system is the optimum display of content. As Mark Boulton put it, designing \u201ccontent out, not canvas in.\u201d Chris Armstrong puts the emphasis on not designing for viewports but for content \u2013 \u201cwe need to build on what we do know: content.\u201d In order to do this, we must share the same content across all devices and focus on how best to display and represent content through design system components.\n\nThe practical: core visual components\n\nTypography first\n\nWhen you work with a lot of text content, typography is the easiest way to set the visual tone of the design across all viewport widths. It\u2019s likely that you\u2019ll choose one or two typefaces to use across the whole system, but you might change the most legible font size, balanced with the most comfortable measure, as the viewport width changes.\n\nWhere typography meets layout\n\nThe unit on which you choose to base the grid and layout design, font sizes and leading could be based on the typeface, an optimal reading size, or something more arbitrary. Sometimes I\u2019ll choose a unit based on multiples of ten because it makes the maths in the CSS easier. Tim Brown suggests trying a modular scale. Chris Armstrong suggests basing it on your ideal measure, or the width of a fixed item of content such as an ad unit.\n\nGrids and layouts\n\nSensible grid design can be a flexible yet solid foundation for your design system layout component. But you must be wary in responsive design that a grid might not work across all widths: even four columns could make for very cramped content and one-word measures on smaller screens.\n\nMaybe the grid columns are something you differentiate across widths, but you can keep the concept of the grid consistent. If the content has blocks in groups of three, you might decide on a three-column grid which folds down to one column for narrow viewports. If the grid focuses on the idea of symmetry and has a four-column grid on larger viewports, it might fold down to two columns for narrower viewports. These consistencies may seem subtle, not at all obvious to many except the designer, but it\u2019s all these little constants and patterns across the whole of the design system that makes design decisions easier to make (as they adhere to the guiding concepts of your system), and give the product a uniform feel no matter what the device.\n\nShape or form\n\nThe shape or form components are concepts you already use in fixed-width web design for a strong, consistent look and feel. \n\nSince CSS border-radius became widely supported by browsers, a lot of designs feature circle themes. These are very distinctive and can be used across viewport widths giving them the same united feel, even if they\u2019re not used in the same way. This could also apply to border styles, consistent shadows and any number of decorative details and textures. These are the elements that make up the shape or form of a design system.\n\nColour\n\nColour is the most basic way to reinforce a brand and unite experiences across viewports. The same hex colour used system-wide is instantly recognisable, no matter what the viewport width.\n\nThe process\n\nWhile using a design system isn\u2019t necessarily attached to any particular process, it does lend itself to some process ideals.\n\nDetaching design considerations from viewport widths\n\nA design system allows you to focus separately on the components that make up the system, disconnecting the look and feel from the layout. This helps prevent us getting stuck in the rut of the Apple breakpoints (brilliantly coined by Simon Foster) of mobile, tablet and desktop. It also forces us to design for variation in viewport experiences side by side, not one after the other.\n\nDesign in the browser\n\nI can\u2019t start off designing in the browser \u2013 it just doesn\u2019t seem to bring out my creative side (and I\u2019m incredibly envious of you if you can; I just have to start on paper) \u2013 but static mock-ups aren\u2019t the only alternative. Style guides and style tiles are perfect for expressing the concepts of your design system. Pattern libraries could also work well.\n\nMock-ups and breakpoints\n\nAt some point, whether it\u2019s to test your system ideas, or because a client needs help visualising how your system might work, you may end up producing some static mock-ups. It\u2019s not the end of the world, but you must ensure that these consider all the viewports, not just those of the iDevices, or even the devices currently on the market. You need to decide the breakpoints where the states of your design change. The blocks within your content will always have optimum points for their display (based on their hierarchy, density, width, or type of interaction) and so your breakpoints should be based around these points.\n\nThese are probably the ideal points at which to produce static mockups; treat them as snapshots. They\u2019re not necessarily mock-ups, so much as a way of capturing how your design system would be interpreted when frozen at that particular viewport width.\n\nThe future\n\nCreating design systems will give us the flexibility we need for working with the unknown devices of the future. It may be a change in process, but it shouldn\u2019t be too much of a difference in thinking. The pioneers in responsive design have a hard job. Some of these problems may have already been solved in other technologies or industries, but it\u2019s up to the pioneers to find those connections and help us formulate solutions and standards that will make responsive design the best it can possibly be. We need to keep experimenting and communicating, particularly in the area of design, as good user experiences are the true sign of whether our products are a success.", "year": "2012", "author": "Laura Kalbag", "author_slug": "laurakalbag", "published": "2012-12-12T00:00:00+00:00", "url": "https://24ways.org/2012/design-systems/", "topic": "design"} {"rowid": 213, "title": "Accessibility Through Semantic HTML", "contents": "Working on Better, a tracker blocker, I spend an awful lot of my time with my nose in other people\u2019s page sources. I\u2019m mostly there looking for harmful tracking scripts, but often notice the HTML on some of the world\u2019s most popular sites is in a sad state of neglect.\nWhat does neglected HTML look like? Here\u2019s an example of the markup I found on a news site just yesterday. There\u2019s a bit of text, a few links, and a few images. But mostly it\u2019s div elements.\n
\n
\n
\n
\n
\n
\n \n
\n
\n Some text more text\n
\n
\n
\n
\n
\ndivs and spans, why do we use them so much?\nWhile I find tracking scripts completely inexcusable, I do understand why people write HTML like the above. As developers, we like to use divs and spans as they\u2019re generic elements. They come with no associated default browser styles or behaviour except that div displays as a block, and span displays inline. If we make our page up out of divs and spans, we know we\u2019ll have absolute control over styles and behaviour cross-browser, and we won\u2019t need a CSS reset.\nAbsolute control may seem like an advantage, but there\u2019s a greater benefit to less generic, more semantic elements. Browsers render semantic elements with their own distinct styles and behaviours. For example, button looks and behaves differently from a. And ul is different from ol. These defaults are shortcuts to a more usable and accessible web. They provide consistent and well-tested components for common interactions.\nSemantic elements aid usability\nA good example of how browser defaults can benefit the usability of an element is in the as a popover-style menu. On a touchscreen, Safari overlays the same menu over the lower half of the screen as a \u201cpicker view.\u201d\nOption menu in Safari on macOS.\nOption menu picker in Safari on iOS.\nThe iOS picker is a much better experience than struggling to pick from a complicated interface inside the page. The menu is shown more clearly than in the confined space on the page, which makes the options easier to read. The required swipe and tap gestures are consistent with the rest of the operating system, making the expected interaction easier to understand. The whole menu is scaled up, meaning the gestures don\u2019t need such fine motor control. Good usability is good accessibility.\nWhen we choose to use a div or span over a more semantic HTML element, we\u2019re also doing hard work the browser could be doing for us. We don\u2019t need to tie ourselves in knots making a custom div into a keyboard navigable option menu. Using select passes the bulk of the responsibility over to the browser.\u00a0\nLetting the browser do most of the work is also more future-friendly. More devices, with different expected interactions, will be released in the future. When that happens, the devices\u2019 browsers can adapt our sites according to those interactions. Then we can spend our time doing something more fun than rewriting cross-browser JavaScript for each new device.\nHTML\u2019s impact on accessibility\nAssistive technology also uses semantic HTML to understand how best to convey each element to its user.\nFor screen readers\nSemantic HTML gives context to screen readers. Screen readers are a type of assistive technology that reads the content of the screen to the person using it. All sites have a linear page source. Sighted visitors can use visual cues on the page to navigate to their desired content in a non-linear fashion. As screen readers output audio (and sometimes braille), those visual cues aren\u2019t usable in the same way.\nScreen readers provide alternative means of navigation, enabling people to jump between different types of content, such as links, forms, headings, lists, and paragraphs. If all our content is marked up using divs and spans, we\u2019re not giving screen readers a chance to index the valuable content.\nFor keyboard navigation\nKeyboard-only navigation is also aided by semantic HTML. Forms, option menus, navigation, video, and audio are particularly hard for people relying on a keyboard to access. For instance, option menus and navigation can be very fiddly if you need to use a mouse to hover a menu open and move to select the desired item at the same time.\u00a0\nAgain, we can leave much of the interaction to the browser through semantic HTML. Semantic form elements can convey if a check box has been checked, or which label is associated with which input field. These default behaviours can make the difference between a person being able to use a form or leaving the site out of frustration.\nDid I convince you yet? I hope so. Let\u2019s finish with some easy guidelines to follow.\n1. Use the most semantic HTML element for the job\nWhen you reach for a div, first check if there\u2019s a better element to do the job. What is the role of that element? How should a person be interacting with the element?\nAre you using class names like nav, header, or main? There are HTML5 elements for those sections! Using specific elements can also make writing CSS simpler, and ensure a consistent design with minimal effort.\n2. Separate structure and style\nDon\u2019t choose HTML elements based on how they\u2019re styled in your CSS. Nowadays, common practice is to use class names rather than elements for CSS selectors. You\u2019re unlikely to wrap all your page content in an

element because you want all the text to be big and bold. Still, it can be easy to choose an HTML element because it will be the easiest to style. Focusing on content without style will help us choose the most semantic HTML element without that temptation. For example, you could add a class of .btn to a div to make it look like a button. But we all know that only a button will really behave like a button.\n3. Use progressive enhancement for enhanced functionality\nAirbnb and Groupon recently proved we\u2019re not past the laziness of \u201cthis site only works in X browser.\u201d Baffling disregard for the open web aside, making complex interactive experiences work cross-browser and cross-device is not easy. We can use progressive enhancement to layer fancy or unsupported features on top of a baseline \u201cit works\u201d experience.\u00a0\nWe should build the baseline experience on a foundation of accessible, semantic HTML. Then, if you really want to add a specific feature for a proprietary browser, you can layer that on top, without breaking the underlying experience.\n4. Test your work\nValidators are always valuable for checking the browser will be able to correctly interpret your markup. Document outline checkers can be valuable for testing your structure, but be aware that the HTML5 document outline is not actually implemented in browsers.\nOnce you\u2019ve got something resembling a web page, test the experience! Ensure that semantic HTML element you chose looks and behaves in a predictable manner consistent with its use across the web. Test cross-browser, test cross-device, and test with assistive technology. Testing with assistive technology is not as expensive as it used to be, you can even use your smartphone for testing on iOS and Android. Your visitors will thank you!\nFurther reading\n\nAccessibility For Everyone by Laura Kalbag\nHTML5 Doctor\nHTML5 Accessibility\nAn overview of HTML5 Semantics\nHTML reference on MDN\u00a0\nHeydon Pickering\u2019s Inclusive Design Checklist\nThe Paciello Group\u2019s Inclusive Design Principles", "year": "2017", "author": "Laura Kalbag", "author_slug": "laurakalbag", "published": "2017-12-15T00:00:00+00:00", "url": "https://24ways.org/2017/accessibility-through-semantic-html/", "topic": "code"} {"rowid": 56, "title": "Helping VIPs Care About Performance", "contents": "Making a site feel super fast is the easy part of performance work. Getting people around you to care about site speed is a much bigger challenge. How do we keep the site fast beyond the initial performance work? Keeping very important people like your upper management or clients invested in performance work is critical to keeping a site fast and empowering other designers and developers to contribute.\nThe work to get others to care is so meaty that I dedicated a whole chapter to the topic in my book Designing for Performance. When I speak at conferences, the majority of questions during Q&A are on this topic. When I speak to developers and designers who care about performance, getting other people at one\u2019s organization or agency to care becomes the most pressing question.\nMy primary response to folks who raise this issue is the question: \u201cWhat metric(s) do your VIPs care about?\u201d This is often met with blank stares and raised eyebrows. But it\u2019s also our biggest clue to what we need to do to help empower others to care about performance and work on it. Every organization and executive is different. This means that three major things vary: the primary metrics VIPs care about; the language they use about measuring success; and how change is enacted. By clueing in to these nuances within your organization, you can get a huge leg up on crafting a successful pitch about performance work.\nLet\u2019s start with the metric that we should measure. Sure, (most) everybody cares about money - but is that really the metric that your VIPs are looking at each day to measure the success or efficacy of your site? More likely, dollars are the end game, but the metrics or key performance indicators (KPIs) people focus on might be:\n\nrate of new accounts created/signups\ncost of acquiring or retaining a customer\nvisitor return rate\nvisitor bounce rate\nfavoriting or another interaction rate\n\nThese are just a few examples, but they illustrate how wide-ranging the options are that people care about. I find that developers and designers haven\u2019t necessarily investigated this when trying to get others to care about performance. We often reach for the obvious \u2013 money! \u2013 but if we don\u2019t use the same kind of language our VIPs are using, we might not get too far. You need to know this before you can make the case for performance work.\nTo find out these metrics or KPIs, start reading through the emails your VIPs are sending within your company. What does it say on company wikis? Are there major dashboards internally that people are looking at where you could find some good metrics? Listen intently in team meetings or thoroughly read annual reports to see what these metrics could be.\nThe second key here is to pick up on language you can effectively copy and paste as you make the case for performance work. You need to be able to reflect back the metrics that people already find important in a way they\u2019ll be able to hear. Once you know your key metrics, it\u2019s time to figure out how to communicate with your VIPs about performance using language that will resonate with them.\nLet\u2019s start with visit traffic as an example metric that a very important person cares about. Start to dig up research that other people and companies have done that correlates performance and your KPI. For example, cite studies:\n\n\u201cWhen the home page of Google Maps was reduced from 100KB to 70\u201380KB, traffic went up 10% in the first week, and an additional 25% in the following three weeks.\u201d (source).\n\nRead through websites like WPOStats, which collects the spectrum of studies on the impact of performance optimization on user experience and business metrics. Tweet and see if others have done similar research that correlates performance and your site\u2019s main KPI.\nOnce you have collected some research that touches on the same kind of language your VIPs use about the success of your site, it\u2019s time to present it. You can start with something simple, like a qualitative description of the work you\u2019re actively doing to improve the site that translates to improved metrics that your VIPs care about. It can be helpful to append a performance budget to any proposal so you can compare the budget to your site\u2019s reality and how it might positively impact those KPIs folks care about.\nWords and graphs are often only half the battle when it comes to getting others to care about performance. Often, videos appeal to folks\u2019 emotions in a way that is missed when glancing through charts and graphs. On A List Apart I recently detailed how to create videos of how fast your site loads. Let\u2019s say that your VIPs care about how your site loads on mobile devices; it\u2019s time to show them how your site loads on mobile networks.\nOpen video\n\nYou can use these videos to make a number of different statements to your VIPs, depending on what they care about:\n\nLook at how slow our site loads versus our competitor!\nLook at how slow our site loads for users in another country!\nLook at how slow our site loads on mobile networks!\n\nAgain, you really need to know which metrics your VIPs care about and tune into the language they\u2019re using. If they don\u2019t care about the overall user experience of your site on mobile devices, then showing them how slow your site loads on 3G isn\u2019t going to work. This will be your sales pitch; you need to practice and iterate on the language and highlights that will land best with your audience. \nTo make your sales pitch as solid as possible, gut-check your ideas on how to present it with other co-workers to get their feedback. Read up on how to construct effective arguments and deliver them; do some research and see what others have done at your company when pitching to VIPs. Are slides effective? Memos or emails? Hallway conversations? Sometimes the best way to change people\u2019s minds is by mentioning it in informal chats over coffee. Emulate the other leaders in your organization who are successful at this work. \nEvery organization and very important person is different. Learn what metrics folks truly care about, study the language that they use, and apply what you\u2019ve learned in a way that\u2019ll land with those individuals. It may take time to craft your pitch for performance work over time, but it\u2019s important work to do. If you\u2019re able to figure out how to mirror back the language and metrics VIPs care about, and connect the dots to performance for them, you will have a huge leg up on keeping your site fast in the long run.", "year": "2015", "author": "Lara Hogan", "author_slug": "larahogan", "published": "2015-12-08T00:00:00+00:00", "url": "https://24ways.org/2015/helping-vips-care-about-performance/", "topic": "business"} {"rowid": 297, "title": "Public Speaking with a Buddy", "contents": "My book Demystifying Public Speaking focuses on the variety of fears we each have about giving a talk. From presenting to a client, to leading a team standup, to standing on a conference stage, there are lots of things we can do to prepare ourselves for the spotlight and reduce those fears.\nThough it didn\u2019t make it into the final draft, I wanted to highlight how helpful it can be to share that public speaking spotlight with another person, or a few more people. If you have fears about not knowing the answer to a question, fumbling your words, or making a mistake in the spotlight, then buddying up may be for you!\n\nTo some, adding more people to a presentation sounds like a recipe for on-stage disaster. To others, having a friendly face nearby\u2014a partner who can step in if you fumble\u2014is incredibly reassuring. As design director Yesenia Perez-Cruz writes, \u201cWhile public speaking is a deeply personal activity, you don\u2019t have to go it alone. Nothing has helped my speaking career more than turning it into a group effort.\u201d\nCo-presenting can level up a talk in two ways: an additional brain and presentation skill set can improve the content of the talk itself, and you may feel safer with the on-stage safety net of your buddy. \nFor example, when I started giving lengthy workshops about building mobile device labs with my co-worker Destiny Montague, we brought different experience to the table. I was able to talk about the user experience of our lab, and the importance of testing across different screen sizes. Destiny spoke about the hardware aspects of the lab, like power consumption and networking. Our audience benefitted from the spectrum of insight we included in the talk.\nMoreover, Destiny and I kept each other energized and engaging while teaching our audience, having way more fun onstage. Partnering up alleviated the risk (and fear!) of fumbling; where one person makes a mistake, the other person is right there to help. Buddy presentations can be helpful if you fear saying \u201cI don\u2019t know\u201d to a question, as there are other people around you who will be able to help answer it from the stage. By partnering with someone whom I trust and respect, and whose work and knowledge augments my own, it made the experience\u2014and the presentation!\u2014significantly better.\nCo-presenting won\u2019t work if you don\u2019t trust the person you\u2019re onstage with, or if you don\u2019t have good chemistry working together. It might also not work if there\u2019s an imbalance of responsibilities, both in preparing the talk and giving it. Read on for how to make partner talks work to your advantage!\nTrustworthiness\nIf you want to explore co-presenting, make sure that your presentation partner is trustworthy and can carry their weight; it can be stressful if you find yourself trying to meet deadlines and prepare well and your partner isn\u2019t being helpful. We\u2019re all about reducing the fears and stress levels surrounding being in that spotlight onstage; make sure that the person you\u2019re relying on isn\u2019t making the process harder.\nBefore you start working together, sketch out the breakdown of work and timeline you\u2019re each committing to. Have a conversation about your preferred work style so you each have a concrete understanding of the best ways to communicate (in what medium, and how often) and how to check in on each other\u2019s progress without micromanaging or worrying about radio silence. Ask your buddy how they prefer to receive feedback, and give them your own feedback preferences, so neither of you are surprised or offended when someone\u2019s work style or deliverable needs to be tweaked.\nThis should be a partnership in which you both feel supported; it\u2019s healthy to set all these expectations up front, and create a space in which you can each tweak things as the work progresses.\nTalk flow and responsibilities\nThere are a few different ways to organize the structure of your talk with multiple presenters. Start by thinking about the breakdown of the talk content\u2014are there discrete parts you and the other presenters can own or deliver? Or does it feel more appropriate to deliver the entirety of the content together?\nIf you\u2019re finding that you can break down the content into discrete chunks, figure out who should own which pieces, and what ownership means. Will you develop the content together but have only one person present the information? Or will one person research and prepare each content section in addition to delivering it solo onstage?\nRehearse how handoffs will go between sections so it feels natural, rather than stilted. I like breaking a presentation into \u201cchapters\u201d when I\u2019m passionate about particular aspects of a topic and can speak on those, but know that there are other aspects to be shared and there\u2019s someone else who can handle (and enjoy!) talking about them. When Destiny and I rehearsed our \u201cchapter\u201d handoffs, we developed little jingles that we\u2019d both sing together onstage; it indicated to the audience that it was a planned transition in the content, and tied our independent work together into a partnership.\n.embed-container { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; } .embed-container iframe, .embed-container object, .embed-container embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }\n\n\n\nAlternatively, you can give the presentation in a way that\u2019s close to having a rehearsed conversation, rather than independently presenting discrete parts of the talk. In this case, you\u2019ll both be sharing the spotlight at the same time, throughout the duration of the talk. Preparation is key, here, to make sure that you each understand what needs to be communicated, and you have a sense of who will be taking responsibility for communicating those different pieces of information. A poorly-prepared talk like this will look like the co-presenters are talking over each other, or hesitating awkwardly to give the other person more room to speak; the audience will feel how uncomfortable this is, and will probably be distracted from the talk content. Practice the talk the whole way through multiple times so you know what each person is planning on covering and how you want to interact with each other while you\u2019re both holding microphones; also figure out how you\u2019ll be standing in relation to each other. More on that next!\nSharing the stage\nIf you choose to give a talk with a partner, determine ahead of time how you\u2019ll stand (or sit). For example, if you each take \u201cchapters\u201d or major sections of the presentation, ensure that it\u2019s clear who the audience should focus their attention on. You could sit in a chair off to the side (or stand). I recommend placing yourself far enough away that you\u2019re not distracting to the audience; you don\u2019t want them watching you while your partner is speaking. If the audience can still see you, but their focus should be on your buddy, be sure to not look distracted; keep your eyes on your buddy, and don\u2019t just open your laptop and ignore what\u2019s happening! Feel free to smile, laugh, or react how the audience should be reacting as your partner is speaking.\nIf you\u2019re both sharing the spotlight at the same time and having a rehearsed conversation, make sure that your body language engages the audience and you\u2019re not just speaking to each other, ignoring the folks watching. Watch this talk with Guy Podjarny and Assaf Hefetz who have partnered up to talk about security; they have clearly identified roles onstage, and remain engaged with the audience.\n\nConsider whether or not you will share a microphone, or if you will both be mic\u2019d. (Be sure that the event organizer, or the A/V team, has a heads-up well in advance to ensure they have the equipment handy!) Also talk through how you\u2019d like to handle Q&A time during or after the talk, especially if you have clear \u201cchapters\u201d where Q&A might happen naturally during a handoff. The more clarity you and your partner have about who is responsible for which pieces of information sharing, the more you can feel and appear prepared.\nCo-presenting does take a lot of preparation and requires a ton of communication between you and your partner. But the rewards can be awesome: double the brains onstage to help answer questions and communicate information, and a friendly face to help comfort you if you feel nervous.", "year": "2016", "author": "Lara Hogan", "author_slug": "larahogan", "published": "2016-12-06T00:00:00+00:00", "url": "https://24ways.org/2016/public-speaking-with-a-buddy/", "topic": "process"} {"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": 319, "title": "Avoiding CSS Hacks for Internet Explorer", "contents": "Back in October, IEBlog issued a call to action, asking developers to clean up their CSS hacks for IE7 testing. Needless to say, a lot of hubbub ensued\u2026 both on IEBlog and elsewhere. My contribution to all of the noise was to suggest that developers review their code and use good CSS hacks. But what makes a good hack?\n\nTantek \u00c7elik, the Godfather of CSS hacks, gave us the answer by explaining how CSS hacks should be designed. In short, they should (1) be valid, (2) target only old/frozen/abandoned user-agents/browsers, and (3) be ugly. Tantek also went on to explain that using a feature of CSS is not a hack.\n\nNow, I\u2019m not a frequent user of CSS hacks, but Tantek\u2019s post made sense to me. In particular, I felt it gave developers direction on how we should be coding to accommodate that sometimes troublesome browser, Internet Explorer. But what I\u2019ve found, through my work with other developers, is that there is still much confusion over the use of CSS hacks and IE. Using examples from the code I\u2019ve seen recently, allow me to demonstrate how to clean up some IE-specific CSS hacks.\n\nThe two hacks that I\u2019ve found most often in the code I\u2019ve seen and worked with are the star html bug and the underscore hack. We know these are both IE-specific by checking Kevin Smith\u2019s CSS Filters chart. Let\u2019s look at each of these hacks and see how we can replace them with the same CSS feature-based solution.\n\nThe star html bug\n\nThis hack violates Tantek\u2019s second rule as it targets current (and future) UAs. I\u2019ve seen this both as a stand alone rule, as well as an override to some other rule in a style sheet. Here are some code samples:\n\n* html div#header {margin-top:-3px;}\n.promo h3 {min-height:21px;}\n* html .promo h3 {height:21px;}\n\nThe underscore hack\n\nThis hack violates Tantek\u2019s first two rules: it\u2019s invalid (according to the W3C CSS Validator) and it targets current UAs. Here\u2019s an example:\n\nol {padding:0; _padding-left:5px;}\n\nUsing child selectors\n\nWe can use the child selector to replace both the star html bug and underscore hack. Here\u2019s how:\n\n Write rules with selectors that would be successfully applied to all browsers. This may mean starting with no declarations in your rule!\n\ndiv#header {}\n.promo h3 {}\nol {padding:0;}\n\n \nTo these rules, add the IE-specific declarations.\n\ndiv#header {margin-top:-3px;}\n.promo h3 {height:21px;}\nol {padding:0 0 0 5px;}\n\n \nAfter each rule, add a second rule. The selector of the second rule must use a child selector. In this new rule, correct any IE-specific declarations previously made.\n\ndiv#header {margin-top:-3px;}\nbody > div#header {margin-top:0;}\n\n.promo h3 {height:21px;}\n.promo > h3 {height:auto; min-height:21px;}\n\nol {padding:0 0 0 5px;}\nhtml > body ol {padding:0;}\n\n \n\nVoil\u00e0 \u2013 no more hacks! There are a few caveats to this that I won\u2019t go into\u2026 but assuming you\u2019re operating in strict mode and barring any really complicated stuff you\u2019re doing in your code, your CSS will still render perfectly across browsers. And while this may make your CSS slightly heftier in size, it should future-proof it for IE7 (or so I hope). Happy holidays!", "year": "2005", "author": "Kimberly Blessing", "author_slug": "kimberlyblessing", "published": "2005-12-17T00:00:00+00:00", "url": "https://24ways.org/2005/avoiding-css-hacks-for-internet-explorer/", "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": 263, "title": "Securing Your Site like It\u2019s 1999", "contents": "Running a website in the early years of the web was a scary business. The web was an evolving medium, and people were finding new uses for it almost every day. From book stores to online auctions, the web was an expanding universe of new possibilities.\nAs the web evolved, so too did the knowledge of its inherent security vulnerabilities. Clever tricks that were played on one site could be copied on literally hundreds of other sites. It was a normal sight to log in to a website to find nothing working because someone had breached its defences and deleted its database. Lessons in web security in those days were hard-earned.\nWhat follows are examples of critical mistakes that brought down several early websites, and how you can help protect yourself and your team from the same fate.\nBad input validation: Trusting anything the user sends you\nOur story begins in the most unlikely place: Animal Crossing. Animal Crossing was a 2001 video game set in a quaint town, filled with happy-go-lucky inhabitants that co-exist peacefully. Like most video games, Animal Crossing was the subject of many fan communities on the early web.\nOne such unofficial web forum was dedicated to players discussing their adventures in Animal Crossing. Players could trade secrets, ask for help, and share pictures of their virtual homes. This might sound like a model community to you, but you would be wrong.\nOne day, a player discovered a hidden field in the forum\u2019s user profile form. Normally, this page allows users to change their name, their password, or their profile photo. This person discovered that the hidden field contained their unique user ID, which identifies them when the forum\u2019s backend saves profile changes to its database. They discovered that by modifying the form to change the user ID, they could make changes to any other player\u2019s profile.\nNeedless to say, this idyllic online community descended into chaos. Users changed each other\u2019s passwords, deleted each other\u2019s messages, and attacked each-other under the cover of complete anonymity. What happened?\nThere aren\u2019t any official rules for developing software on the web. But if there were, my golden rule would be:\nNever trust user input. Ever.\nAlways ask yourself how users will send you data that isn\u2019t what it seems to be. If the nicest community of gamers playing the happiest game on earth can turn on each other, nowhere on the web is safe.\nMake sure you validate user input to make sure it\u2019s of the correct type (e.g. string, number, JSON string) and that it\u2019s the length that you were expecting. Don\u2019t forget that user input doesn\u2019t become safe once it is stored in your database; any data that originates from outside your network can still be dangerous and must be escaped before it is inserted into HTML.\nMake sure to check a user\u2019s actions against what they are allowed to do. Create a clear access control policy that defines what actions a user may take, and to whose data they are allowed access to. For example, a newly-registered user should not be allowed to change the user profile of a web forum\u2019s owner.\nFinally, never rely on client-side validation. Validating user input in the browser is a convenience to the user, not a security measure. Always assume the user has full control over any data sent from the browser and make sure you validate any data sent to your backend from the outside world.\nSQL injection: Allowing the user to run their own database queries\nA long time ago, my favourite website was a web forum dedicated to the Final Fantasy video game series. Like the users of the Animal Crossing forum, I\u2019d while away many hours arguing with other people on the internet about my favourite characters, my favourite stories, and the greatest controversies of the day.\nOne day, I noticed people were acting strangely. Users were being uncharacteristically nasty and posting in private areas of the forum they wouldn\u2019t normally have access to. Then messages started disappearing, and user accounts for well-respected people were banned.\nIt turns out someone had discovered a way of logging in to any other user account, using a secret password that allowed them to do literally anything they wanted. What was this password that granted untold power to those who wielded it?\n' OR '1'='1\nSQL is a computer language that is used to query databases. When you fill out a login form, just like the one above, your username and your password are usually inserted into an SQL query like this:\n\nSELECT COUNT(*)\nFROM USERS\nWHERE USERNAME='Alice'\nAND PASSWORD='hunter2'\nThis query selects users from the database that match the username Alice and the password hunter2. If there is at least one user matching record, the user will be granted access. Let\u2019s see what happens when we use our magic password instead!\n\nSELECT COUNT(*)\nFROM USERS\nWHERE USERNAME='Admin'\nAND PASSWORD='' OR '1'='1'\nDoes the password look like part of the query to you? That\u2019s because it is! This password is a deliberate attempt to inject our own SQL into the query, hence the term SQL injection. The query is now looking for users matching the username Admin, with a password that is blank, or 1=1. In an SQL query, 1=1 is always true, which makes this query select every single record in the database. As long as the forum software is checking for at least one matching user, it will grant the person logging in access. This password will work for any user registered on the forum!\nSo how can you protect yourself from SQL injection?\nNever build SQL queries by concatenating strings. Instead, use parameterised query tools. PHP offers prepared statements, and Node.JS has the knex package. Alternatively, you can use an ORM tool, such as Propel or sequelize.\nExpert help in the form of language features or software tools is a key ally for securing your code. Get all the help you can!\nCross site request forgery: Getting other users to do your dirty work for you\nDo you remember Netflix? Not the Netflix we have now, the Netflix that used to rent you DVDs by mailing them to you. My next story is about how someone managed to convince Netflix users to send him their DVDs - free of charge.\nHave you ever clicked on a hyperlink, only to find something that you weren\u2019t expecting? If you were lucky, you might have just gotten Rickrolled. If you were unlucky\u2026\nLet\u2019s just say there are older and fouler things than Rick Astley in the dark places of the web.\nWhat if you could convince people to visit a page you controlled? And what if those people were Netflix users, and they were logged in? In 2006, Dave Ferguson did just that. He created a harmless-looking page with an image on it:\n\nDid you notice the source URL of the image? It\u2019s deliberately crafted to add a particular DVD to your queue. Sprinkle in a few more requests to change the user\u2019s name and shipping address, and you could ship yourself DVDs completely free of charge!\nThis attack is possible when websites unconditionally trust a user\u2019s session cookies without checking where HTTP requests come from.\nThe first check you can make is to verify that a request\u2019s origin and referer headers match the location of the website. These headers can\u2019t be programmatically set.\nAnother check you can use is to add CSRF tokens to your web forms, to verify requests have come from an actual form on your website. Tokens are long, unpredictable, unique strings that are generated by your server and inserted into web forms. When users complete a form, the form data sent to the server can be checked for a recently generated token. This is an effective deterrent of CSRF attacks because CSRF tokens aren\u2019t stored in cookies.\nYou can also set SameSite=Strict when setting cookies with the Set-Cookie HTTP header. This communicates to browsers that cookies are not to be sent with cross-site requests. This is a relatively new feature, though it is well supported in evergreen browsers.\nCross site scripting: Someone else\u2019s code running on your website\nIn 2005, Samy Kamkar became famous for having lots of friends. Lots and lots of friends.\nSamy enjoyed using MySpace which, at the time, was the world\u2019s largest social network. Social networks at that time were more limited than today. For instance, MySpace let you upload photos to your photo gallery, but capped the limit at twelve. Twelve photos. At least you didn\u2019t have to wade through photos of avocado toast back then\u2026\nSamy discovered that MySpace also locked down the kinds of content that you could post on your MySpace page. He discovered he could inject and
tags into his headline, but \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": 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": 278, "title": "Going Both Ways", "contents": "It\u2019s that time of the year again: Santa is getting ready to travel the world. Up until now, girls and boys from all over have sent in letters asking for what they want. I hope that Santa and his elves have\u2014unlike me\u2014learned more than just English.\n\nOn the Internet, those girls and boys want to participate in sharing their stories and videos of opening presents and of being with friends and family. Ah, yes, the wonders of user generated content. But more than that, people also want to be able to use sites in the language they know.\n\nWhile you and I might expect the text to read from left to right, not all languages do. Some go from right to left, such as Arabic and Hebrew. (Some also go from top to bottom, but for now, let\u2019s just worry about those first two directions!)\n\nIf we were building a site for girls and boys to send their letters to Santa, we need to consider having the interface in the language and direction that they prefer. On the elves\u2019 side, they may be viewing the site in one direction but reading the user generated content in the other direction. We need to build a site that supports bidirectional (or bidi) text.\n\nLet\u2019s take a look at some things to be aware of when it comes to building bidi interfaces.\n\nSetting the direction of the interface\n\nRight off the bat, we need to tell the browser what direction the text should be going in. To do this, we add the dir attribute to an HTML element and set it to either LTR (for left to right) or RTL (for right to left).\n\n\n\nYou can add the dir attribute to any element and it will set or change the direction for the content within that element. \n\n\n Here is English Content.\n
    \u0627\u0644\u0645\u0648\u0636\u0648\u0639
    \n\n\nYou can also set the direction via CSS.\n\n.rtl {\n direction: rtl;\n }\n\nIt\u2019s generally recommended that you don\u2019t use CSS to set the direction of the text. Text direction is an important part of the content that should be retained even in environments where the CSS may not be available or fails to load.\n\nHow things change with the direction attribute\n\nJust adding the dir attribute tells the browser to render the content within it differently. \n\n\n\nThe text aligns to the right of the page and, interestingly, punctuation appears at the left of the sentence. (We\u2019ll get to that in a little bit.) \n\nScrollbars in most browsers will appear on the left instead of the right. Webkit is the notable exception here which always shows the scrollbar on the right, no matter what the text direction is. Avoid having a design that has an expectation that the scrollbar will be in a specific place (and a specific size).\n\nChanging the order of text mid-way\n\nAs we saw in that previous example, the punctuation appeared at the beginning of the sentence instead of the end, even though the text was English. At Yahoo!, we have an interesting dilemma where the company name has punctuation in it. Therefore, when the name appears in the middle of (for example) Arabic text, the exclamation mark appears at the beginning of the word instead of the end.\n\n\n\nThere are two ways in which this problem can be solved:\n\n1. Use HTML around the left-to-right content, or\n\nTo solve the problem of the Yahoo! name in the midst of Arabic text, we can wrap a span around it and change the direction on that element.\n\n\n\n2. Use a text direction mark in the content.\n\nUnicode has two marks, U+200E and U+200F, that tell the browser that the text is in a particular direction. Placing this right after the punctuation will correct the placement.\n\nUsing the HTML entity:\nYahoo!\u200e\n\nTables\n\nThankfully, the cells of a data table also get reordered from right to left. Equally as nice, if you\u2019re using display:table, the content will still get reordered.\n\n\n\nCSS\n\nSo far, we\u2019ve seen that the dir attribute does a pretty decent job of getting content flowing in the direction that we need it. Unfortunately, there are huge swaths of design that is handled by CSS that the handy dir attribute has zero effect over.\n\nMany properties, like float or absolute positioning with left and right values, are unaffected and must be handled manually. Elements that were floated left must now by floated right. Left margins and paddings must now move to the right and the right margins and paddings must now move to the left.\n\nSince the browser won\u2019t handle this for us, we have a couple approaches that we can use:\n\nCSS Only\n\nWe can take advantage of the attribute selector to target CSS to apply in one direction or another.\n\n[dir=ltr] .module {\n\tfloat: left;\n\tmargin: 0 0 0 20px;\n}\n\n[dir=rtl] .module {\n\tfloat: right;\n\tmargin: 0 20px 0 0;\n}\n\nAs you can see from this example, both of the properties have been modified for the flipped interface. If your interface is rather complicated, you will have to create a lot of duplicate rules to have the site looking good in both directions while serving up a single stylesheet.\n\nCSSJanus\n\nGoogle has a tool called CSSJanus. It\u2019s a Python script that runs over the LTR versions of your CSS files and generates RTL versions. For the RTL version of the site, just serve up those CSS files instead of the LTR versions.\n\nThe script looks for keywords and value combinations and automatically swaps them so you don\u2019t have to. \n\nAt Yahoo!, CSSJanus was a huge help in speeding up our development of a bidi interface. We\u2019ve also made a number of improvements to the script to better handle border radius, background positioning, and gradients. We will be pushing those changes back into the CSSJanus project. \n\n\n\nBackground Images\n\nBackground images, especially for things like CSS sprites, also raise an interesting dilemma. Background images are positioned relative to the left of the element. In a flipped interface, however, we need to position it relative to the right. An icon that would be to the left of some text will now need to appear on the right.\n\n\n\nIf the x position of the background is percentage-based, then it\u2019s fairly easy to swap the values. 0 becomes 100%, 10% becomes 90% and so on. If the x position is pixel-based, then we\u2019re in a bit of a pickle. There\u2019s no way to say that the image should be a certain number of pixels from the right.\n\nTherefore, you\u2019ll need to ensure that any background image that needs to be swapped should be percentage-based. (99.9% of the the time, the background position will need to be 0 so that it can be changed to 100% for RTL.)\n\nIf you\u2019re taking an existing implementation, background positioning will likely be the biggest hurdle you\u2019ll have to overcome in swapping your interface around. If you make sure your x position is always percentage-based from the beginning, you\u2019ll have a much smoother process ahead of you!\n\nFlipping Images\n\nThis is a more subtle point and one where you\u2019ll really want an expert with the region to weigh in on. In RTL interfaces, users may expect certain icons to also be flipped. Pencil icons that skew to the right in LTR interfaces might need to be swapped to skew to the left, instead. Chat bubbles that come from the left will need to come from the right.\n\nThe easiest way to handle this is to create new images. Name the LTR versions with -ltr in the name and name the RTL versions with -rtl in the name. CSSJanus will automatically rename all file references from -ltr to -rtl.\n\nThe Future\n\nThankfully, those within the W3C recognize that CSS should be more agnostic. As a result, they\u2019ve begun introducing new properties that allow the browser to manage the swapping from left to right for us.\n\nThe CSS3 specification for backgrounds allows for the background-position to be relative to other corners other than the top left by specifying keywords before each position.\n\nThis will position the background 5px from the bottom right of the element.\n\nbackground-position: right 5px bottom 5px;\n\nOpera 11.60 is currently the only browser that supports this syntax.\n\nFor margin and padding, we have margin-start and margin-end. In LTR interfaces, margin-start would be the same as margin-left and in RTL interfaces, margin-start would be the same as margin-right. \n\nFirefox and Webkit support these but with vendor prefixes right now:\n\n-webkit-margin-start: 20px;\n-moz-margin-start: 20px;\n\nIn the CSS3 Images working draft specification, there\u2019s an image() property that allows us to specify image fallbacks and whether those fallbacks are for LTR or RTL interfaces.\n\nbackground: image('sprite.png' ltr, 'sprite-rtl.png' rtl);\n\nUnfortunately, no browser supports this yet but it\u2019s nice to be able to dream of how much easier this will be in the future!\n\nHo Ho Ho\n\nHopefully, after all of this, you\u2019re full of cheer knowing that you\u2019re well on your way to creating interfaces that can go both ways!", "year": "2011", "author": "Jonathan Snook", "author_slug": "jonathansnook", "published": "2011-12-19T00:00:00+00:00", "url": "https://24ways.org/2011/going-both-ways/", "topic": "ux"} {"rowid": 321, "title": "Tables with Style", "contents": "It might not seem like it but styling tabular data can be a lot of fun. From a semantic point of view, there are plenty of elements to tie some style into. You have cells, rows, row groups and, of course, the table element itself. Adding CSS to a paragraph just isn\u2019t as exciting.\n\nWhere do I start?\n\nFirst, if you have some tabular data (you know, like a spreadsheet with rows and columns) that you\u2019d like to spiffy up, pop it into a table \u2014 it\u2019s rightful place!\n\nTo add more semantics to your table \u2014 and coincidentally to add more hooks for CSS \u2014 break up your table into row groups. There are three types of row groups: the header (thead), the body (tbody) and the footer (tfoot). You can only have one header and one footer but you can have as many table bodies as is appropriate.\n\nSample table example\n\nInspiration\n\nTable Striping\n\nTo improve scanning information within a table, a common technique is to style alternating rows. Also known as zebra tables. Whether you apply it using a class on every other row or turn to JavaScript to accomplish the task, a handy-dandy trick is to use a semi-transparent PNG as your background image. This is especially useful over patterned backgrounds. \n\ntbody tr.odd td {\n background:transparent url(background.png) repeat top left;\n }\n\n * html tbody tr.odd td {\n background:#C00;\n filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(\n src='background.png', sizingMethod='scale');\n }\n\nWe turn off the default background and apply our PNG hack to have this work in Internet Explorer. \n\nStyling Columns\n\nDid you know you could style a column? That\u2019s right. You can add special column (col) or column group (colgroup) elements. With that you can add border or background styles to the column.\n\n\n \n \n \n ...\n\nCheck out the example.\n\nFun with Backgrounds\n\nPop in a tiled background to give your table some character! Internet Explorer\u2019s PNG hack unfortunately only works well when applied to a cell.\n\nTo figure out which background will appear over another, just remember the hierarchy:\n\n (bottom) Table \u2192 Column \u2192 Row Group \u2192 Row \u2192 Cell (top)\n\nThe Future is Bright\n\nOnce browser-makers start implementing CSS3, we\u2019ll have more power at our disposal. Just with :first-child and :last-child, you can pull off a scalable version of our previous table with rounded corners and all \u2014 unfortunately, only Firefox manages to pull this one off successfully. And the selector the masses are clamouring for, nth-child, will make zebra tables easy as eggnog.", "year": "2005", "author": "Jonathan Snook", "author_slug": "jonathansnook", "published": "2005-12-19T00:00:00+00:00", "url": "https://24ways.org/2005/tables-with-style/", "topic": "code"} {"rowid": 81, "title": "Science!", "contents": "Sometimes we want to capture people\u2019s attention at a glance to communicate something fast. At other times we want to have the interface fade away into the background, letting people paint pictures in their minds with our words (if you\u2019ll forgive a little flowery festive flourish).\n\nI tend to distinguish between these two broad objectives as designing for impact on the one hand, and designing for immersion on the other. What defines them is interruption. Impact needs an attention-grabbing interruption. Immersion requires us to remove interruption from the interface. Careful design deliberately interrupts but doesn\u2019t accidentally disrupt. If that seems to make sense to you, then you\u2019ll find the following snippets of science as useful as I did.\n\nSaccades and fixations\n\nAs you\u2019re reading this your eyes are skipping along the lines in tiny jumps. During each jump everything is blurred. Each jump ends in a small pause so your brain can take a snapshot of the letters. It arranges them into words, and then parses out the meaning \u2014 fast \u2014 in around a quarter of a second.\n\nThe jumps are called saccades. The pauses are called fixations. Sometimes we take regressive saccades, skipping back to reread. There\u2019s a simple example in the excellent little book, Detail in Typography, by Jost Hochuli.\n\n\n\nIf you want to explore the science of reading in much more depth, I recommend the excellent paper, \u201cThe Science of Word Recognition\u201d, by Dr Kevin Larson of Microsoft.\n\nTo design for legibility and readability is to design for saccades and fixations. It\u2019s the craft of making it easy for people\u2019s brains to extract meaning, using techniques like good contrast, font size, spacing and structure, and only interrupting the reading experience deliberately.\n\nScan paths\n\nAt some point when visiting 24 ways you probably scanned the screen to get orientated. The journey your eyes took is known as a scan path. Scan paths are made up of saccades and fixations. Right now you\u2019re following a scan path as you read, along one line, and down to the next. This is a map of the scan paths found by Olivier Le Meur from observing people looking at Rembrandt\u2019s Le\u00e7on d\u2019anatomie:\n\n\n\nFor websites, the scan path is a little different. This is an aggregate scan path of Google from LC Technologies:\n\n\n\nThe average shape of a website scan path becomes clearer in this average scan path taken by forty-six people during research by the Poynter Institute, the Estlow Center for Journalism & New Media, and Eyetools:\n\n\n\nJust like when we read text arranged left to right in a vertical column, scan paths follow a roughly Z-shaped pattern from the top left to bottom right. Sometimes we skip back to reread a word or sentence, or glance again at a specific element, but the Z-shaped scan path persists.\n\nDesigning for scan paths is to organise content to help people move through an interface to get orientated, and to read.\n\nThe elements that are important enough to need impact must interrupt the scan path and clearly call attention to themselves. However, they don\u2019t always need to clip people round the ear from multiple directions at once to get attention. It helps to list elements by importance. That gives us an interruption hierarchy to work with. Elements can then interrupt the design with degrees of contrast to the rest of the content using either positioning, treatment, or both. Ta-da! Impact achieved, but gently. No clips round the ear required.\n\nSwinging mood\n\nHuman beings are resilient. Among the immersion and occasional interruptions, we even like a little disruption, especially if it\u2019s absurd and funny. The Ling\u2019s Cars website proves it. In fact, we\u2019re so resilient that we can work around all kinds of mayhem to get a seemingly simple task done.\n\nIn one study, \u201cThe Aesthetics of Reading\u201d (PDF, 480Kb), Dr Kevin Larson of Microsoft and Dr Rosalind Picard of MIT explored the effect of good typography on mood. Two versions of the New Yorker ePeriodical were created. One was typeset well and the other poorly.\n\n\n\nThey engaged twenty volunteers \u2014 half male, half female \u2014 and showed the good version to half of the participants. The other half saw the poor version.\n\nThe good doctors found that, \u201cthere are important differences between good and poor typography that appear to have little effect on common performance measures such as reading speed and comprehension.\u201d In short, good typography didn\u2019t help people read faster or comprehend better.\n\nOh. On the face of it that seems to invalidate what we designers do. Hold your horses, though! They also found that \u201cthe participants who received the good typography performed better on relative subjective duration and on certain cognitive tasks\u201d, and that \u201cgood typography induces a good mood.\u201d\n\nThis means that even though there were no actual differences in reading speed and comprehension, the people who read the version with good typography thought that it took less time to read, and were induced into a good mood by doing so. Not only that, but by being in a good mood, people were more capable of completing creative tasks faster.\n\nThat was a revelation to me. It means that the study showed there is a positive, measurable, emotional and perceptual benefit to good typography and design. To paraphrase: time and tasks fly when you\u2019re having fun!\n\n\n\nSource: Nationaal Archief of the Netherlands: Cheering man after the first goal, Netherlands vs. Belgium, Amsterdam, 1931.\n\nSo, among all my talk of saccades, fixations, scan paths and typesetting, there is science, and the science helps us qualify our design decisions when we need to, and do our jobs better. The science helps us understand how people will interact with our work, and what the actual benefits are for them, and the products or organisations we serve. Good design equals a subjectively quicker experience, a good mood, objectively faster completion of tasks, and happiness for everyone. Thank you, science!", "year": "2012", "author": "Jon Tan", "author_slug": "jontan", "published": "2012-12-24T00:00:00+00:00", "url": "https://24ways.org/2012/science/", "topic": "design"} {"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": 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": 288, "title": "Displaying Icons with Fonts and Data- Attributes", "contents": "Traditionally, bitmap formats such as PNG have been the standard way of delivering iconography on websites. They\u2019re quick and easy, and it also ensures they\u2019re as pixel crisp as possible. Bitmaps have two drawbacks, however: multiple HTTP requests, affecting the page\u2019s loading performance; and a lack of scalability, noticeable when the page is zoomed or viewed on a screen with a high pixel density, such as the iPhone 4 and 4S.\n\nThe requests problem is normally solved by using CSS sprites, combining the icon set into one (physically) large image file and showing the relevant portion via background-position. While this works well, it can get a bit fiddly to specify all the positions. In particular, scalability is still an issue. A vector-based format such as SVG sounds ideal to solve this, but browser support is still patchy.\n\n\n\nThe rise and adoption of web fonts have given us another alternative. By their very nature, they\u2019re not only scalable, but resolution-independent too. No need to specify higher resolution graphics for high resolution screens! \n\nThat\u2019s not all though:\n\n\n\tBrowser support: Unlike a lot of new shiny techniques, they have been supported by Internet Explorer since version 4, and, of course, by all modern browsers. We do need several different formats, however!\n\tDesign on the fly: The font contains the basic graphic, which can then be coloured easily with CSS \u2013 changing colours for themes or :hover and :focus styles is done with one line of CSS, rather than requiring a new graphic. You can also use CSS3 properties such as text-shadow to add further effects. Using -webkit-background-clip: text;, it\u2019s possible to use gradient and inset shadow effects, although this creates a bitmap mask which spoils the scalability.\n\tSmall file size: specially designed icon fonts, such as Drew Wilson\u2019s Pictos font, can be as little as 12Kb for the .woff font. This is because they contain fewer characters than a fully fledged font. You can see Pictos being used in the wild on sites like Garrett Murray\u2019s Maniacal Rage.\n\n\nAs with all formats though, it\u2019s not without its disadvantages: \n\n\n\tIcons can only be rendered in monochrome or with a gradient fill in browsers that are capable of rendering CSS3 gradients. Specific parts of the icon can\u2019t be a different colour.\n\tIt\u2019s only appropriate when there is an accompanying text to provide meaning. This can be alleviated by wrapping the text label in a tag (I like to use rather than , due to the fact that it\u2019s smaller and isn\u2019 t being used elsewhere) and then hiding it from view with text-indent:-999em.\n\tCreating an icon font can be a complex and time-consuming process. While font editors can carry out hinting automatically, the best results are achieved manually.\n\tUnless you\u2019re adept at creating your own fonts, you\u2019re restricted to what is available in the font. However, fonts like Pictos will cover the most common needs, and icons are most effective when they\u2019re using familiar conventions.\n\n\nThe main complaint about using fonts for icons is that it can mean adding a meaningless character to our markup. The good news is that we can overcome this by using one of two methods \u2013 CSS generated content or the data-icon attribute \u2013 in combination with the :before and :after pseudo-selectors, to keep our markup minimal and meaningful. \n\nOur simple markup looks like this:\n\nView Basket\n\nNote the multiple class attributes. Next, we\u2019ll import the Pictos font using the @font-face web fonts property in CSS:\n\n@font-face {\n font-family: 'Pictos';\n src: url('pictos-web.eot');\n src: local('\u263a'), \n url('pictos-web.woff') format('woff'), \n url('pictos-web.ttf') format('truetype'),\n url('pictos-web.svg#webfontIyfZbseF') format('svg');\n}\n\nThis rather complicated looking set of rules is (at the time of writing) the most bulletproof way of ensuring as many browsers as possible load the font we want. We\u2019ll now use the content property applied to the :before pseudo-class selector to generate our icon. Once again, we\u2019ll use those multiple class attribute values to set common icon styles, then specific styles for .basket. This helps us avoid repeating styles:\n\n.icon {\n font-family: 'Pictos';\n font-size: 22px:\n}\n\n.basket:before {\n content: \"$\";\n}\n\nWhat does the :before pseudo-class do? It generates the dollar character in a browser, even when it\u2019s not present in the markup. Using the generated content approach means our markup stays simple, but we\u2019ll need a new line of CSS, defining what letter to apply to each class attribute for every icon we add.\n\ndata-icon is a new alternative approach that uses the HTML5 data- attribute in combination with CSS attribute selectors. This new attribute lets us add our own metadata to elements, as long as its prefixed by data- and doesn\u2019t contain any uppercase letters. In this case, we want to use it to provide the letter value for the icon. Look closely at this markup and you\u2019ll see the data-icon attribute.\n\nView Basket\n\n\n\nWe could add others, in fact as many as we like.\n\nFavourites\nHistory\nLocation\n\n\n\nThen, we need just one CSS attribute selector to style all our icons in one go:\n\n.icon:before {\n content: attr(data-icon);\n /* Insert your fancy colours here */\n }\n\nBy placing our custom attribute data-icon in the selector in this way, we can enable CSS to read the value of that attribute and display it before the element (in this case, the anchor tag). It saves writing a lot of CSS rules. I can imagine that some may not like the extra attribute, but it does keep it out of the actual content \u2013 generated or not.\n\n\n\n\n\nThis could be used for all manner of tasks, including a media player and large simple illustrations. See the demo for live examples. Go ahead and zoom the page, and the icons will be crisp, with the exception of the examples that use -webkit-background-clip: text as mentioned earlier.\n\nFinally, it\u2019s worth pointing out that with both generated content and the data-icon method, the letter will be announced to people using screen readers. For example, with the shopping basket icon above, the reader will say \u201cdollar sign view basket\u201d. As accessibility issues go, it\u2019s not exactly the worst, but could be confusing. You would need to decide whether this method is appropriate for the audience. Despite the disadvantages, icon fonts have huge potential.", "year": "2011", "author": "Jon Hicks", "author_slug": "jonhicks", "published": "2011-12-12T00:00:00+00:00", "url": "https://24ways.org/2011/displaying-icons-with-fonts-and-data-attributes/", "topic": "code"} {"rowid": 324, "title": "Debugging CSS with the DOM Inspector", "contents": "An Inspector Calls\n\nThe larger your site and your CSS becomes, the more likely that you will run into bizarre, inexplicable problems. Why does that heading have all that extra padding? Why is my text the wrong colour? Why does my navigation have a large moose dressed as Noel Coward on top of all the links? \n\nPerhaps you work in a collaborative environment, where developers and other designers are adding code? In which case, the likelihood of CSS strangeness is higher.\n\nYou need to debug. You need Firefox\u2019s wise-guy know-it-all, the DOM Inspector. \n\nThe DOM Inspector knows where everything is in your layout, and more importantly, what causes it to look the way it does. So without further ado, load up any css based site in your copy of Firefox (or Flock for that matter), and launch the DOM Inspector from the Tools menu.\n\nThe inspector uses two main panels \u2013 the left to show the DOM tree of the page, and the right to show you detail:\n\n\n\nThe Inspector will look at whatever site is in the front-most window or tab, but you can also use it without another window. Type in a URL at the top (A), press \u2018Inspect\u2019 (B) and a third panel appears at the bottom, with the browser view. I find this layout handier than looking at a window behind the DOM Inspector.\n\nStep 1 \u2013 find your node!\n\nEach element on your page \u2013 be it a HTML tag or a piece of text, is called a \u2018node\u2019 of the DOM tree. These nodes are all listed in the left hand panel, with any ID or CLASS attribute values next to them. When you first look at a page, you won\u2019t see all those yet. Nested HTML elements (such as a link inside a paragraph) have a reveal triangle next to their name, clicking this takes you one level further down. \n\nThis can be fine for finding the node you want to look at, but there are easier ways. Say you have a complex rounded box technique that involves 6 nested DIVs? You\u2019d soon get tired of clicking all those triangles to find the element you want to inspect. Click the top left icon \u00a9 \u2013 \u201cFind a node to inspect by clicking on it\u201d and then select the area you want to inspect. Boom! All that drilling down the DOM tree has been done for you! Huzzah!\n\nIf you\u2019re looking for an element that you know has an ID (such as
      ), or a specific HTML tag or attribute, click the binoculars icon (D) for \u201cFinds a node to inspect by ID, tag or attribute\u201d (You can also use Ctrl-F or Apple-F to do this if the DOM Inspector is the frontmost window) :\n\n\n\nType in the name and Bam! You\u2019re there! Pressing F3 will take you to any other instances. Notice also, that when you click on a node in the inspector, it highlights where it is in the browser view with a flashing red border!\n\nNow that we\u2019ve found the troublesome node on the page, we can find out what\u2019s up with it\u2026\n\nStep 2 \u2013 Debug that node!\n\nOnce the node is selected, we move over to the right hand panel. Choose \u2018CSS Style Rules\u2019 from the document menu (E), and all the CSS rules that apply to that node are revealed, in the order that they load:\n\n\n\nYou\u2019ll notice that right at the top, there is a CSS file you might not recognise, with a file path beginning with \u201cresource://\u201d. This is the browsers default CSS, that creates the basic rendering. You can mostly ignore this, especially if use the star selector method of resetting default browser styles. \n\nYour style sheets come next. See how helpful it is? It even tells you the line number where to find the related CSS rules! If you use CSS shorthand, you\u2019ll notice that the values are split up (e.g margin-left, margin-right etc.). \n\nNow that you can see all the style rules affecting that node, the rest is up to you! Happy debugging!", "year": "2005", "author": "Jon Hicks", "author_slug": "jonhicks", "published": "2005-12-22T00:00:00+00:00", "url": "https://24ways.org/2005/debugging-css-with-the-dom-inspector/", "topic": "process"} {"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": 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\n\n
      \n Menu\n ...\n
      \n \n\n\nSee the footer-anchor pattern in action.\n\nBecause it\u2019s nothing more than a hyperlink, this works in just about every browser since the dawn of the web. Following hyperlinks is what web browsers were made to do (hence the name).\n\nStep two: layout as an enhancement\n\nThe footer-anchor pattern is a particularly neat solution on small-screen devices, like mobile phones. Once more screen real estate is available, I can use the magic of CSS to reposition the navigation above the content. I could use position: absolute, flexbox or, in this case, display: table.\n\n@media all and (min-width: 35em) {\n .control {\n display: none;\n }\n body {\n display: table;\n }\n [role=\"navigation\"] {\n display: table-caption;\n columns: 6 15em;\n }\n}\n\nSee the styles for wider screens in action\n\nStep three: enhance!\n\nRight. At this point I\u2019m providing core functionality to everyone, and I\u2019ve got nice responsive styles for wider screens. I could stop here, but the real advantage of progressive enhancement is that I don\u2019t have to. From here on, I can go crazy adding all sorts of fancy enhancements for modern browsers, without having to worry about providing a fallback for older browsers \u2013 the fallback is already in place.\n\nWhat I\u2019d really like is to provide a swish off-canvas pattern for small-screen devices. Here\u2019s my plan:\n\n\n\tPosition the navigation under the main content.\n\tListen out for the .control links being activated and intercept that action.\n\tWhen those links are activated, toggle a class of .active on the body.\n\tIf the .active class exists, slide the content out to reveal the navigation.\n\n\nHere\u2019s the CSS for positioning the content and navigation:\n\n@media all and (max-width: 35em) {\n [role=\"main\"] {\n transition: all .25s;\n width: 100%;\n position: absolute;\n z-index: 2;\n top: 0;\n right: 0;\n }\n [role=\"navigation\"] {\n width: 75%;\n position: absolute;\n z-index: 1;\n top: 0;\n right: 0;\n }\n .active [role=\"main\"] {\n transform: translateX(-75%);\n }\n}\n\nIn my JavaScript, I\u2019m going to listen out for any clicks on the .control links and toggle the .active class on the body accordingly:\n\n(function (win, doc) {\n 'use strict';\n var linkclass = 'control',\n activeclass = 'active',\n toggleClassName = function (element, toggleClass) {\n var reg = new RegExp('(s|^)' + toggleClass + '(s|$)');\n if (!element.className.match(reg)) {\n element.className += ' ' + toggleClass;\n } else {\n element.className = element.className.replace(reg, '');\n }\n },\n navListener = function (ev) {\n ev = ev || win.event;\n var target = ev.target || ev.srcElement;\n if (target.className.indexOf(linkclass) !== -1) {\n ev.preventDefault();\n toggleClassName(doc.body, activeclass);\n }\n };\n doc.addEventListener('click', navListener, false);\n}(this, this.document));\n\nI\u2019m all set, right? Not so fast!\n\nCutting the mustard\n\nI\u2019ve made the assumption that addEventListener will be available in my JavaScript. That isn\u2019t a safe assumption. That\u2019s because JavaScript \u2013 unlike HTML or CSS \u2013 isn\u2019t fault-tolerant. If you use an HTML element or attribute that a browser doesn\u2019t understand, or if you use a CSS selector, property or value that a browser doesn\u2019t understand, it\u2019s no big deal. The browser will just ignore what it doesn\u2019t understand: it won\u2019t throw an error, and it won\u2019t stop parsing the file.\n\nJavaScript is different. If you make an error in your JavaScript, or use a JavaScript method or property that a browser doesn\u2019t recognise, that browser will throw an error, and it will stop parsing the file. That\u2019s why it\u2019s important to test for features before using them in JavaScript. That\u2019s also why it isn\u2019t safe to rely on JavaScript for core functionality.\n\nIn my case, I need to test for the existence of addEventListener:\n\n(function (win, doc) {\n if (!win.addEventListener) {\n return;\n }\n ...\n}(this, this.document));\n\nThe good folk over at the BBC call this kind of feature test cutting the mustard. If a browser passes the test, it cuts the mustard, and so it gets the enhancements. If a browser doesn\u2019t cut the mustard, it doesn\u2019t get the enhancements. And that\u2019s fine because, remember, websites don\u2019t need to look the same in every browser.\n\nI want to make sure that my off-canvas styles are only going to apply to mustard-cutting browsers. I\u2019m going to use JavaScript to add a class of .cutsthemustard to the document:\n\n(function (win, doc) {\n if (!win.addEventListener) {\n return;\n }\n ...\n var enhanceclass = 'cutsthemustard';\n doc.documentElement.className += ' ' + enhanceclass;\n}(this, this.document));\n\nNow I can use the existence of that class name to adjust my CSS:\n\n@media all and (max-width: 35em) {\n .cutsthemustard [role=\"main\"] {\n transition: all .25s;\n width: 100%;\n position: absolute;\n z-index: 2;\n top: 0;\n right: 0;\n }\n .cutsthemustard [role=\"navigation\"] {\n width: 75%;\n position: absolute;\n z-index: 1;\n top: 0;\n right: 0;\n }\n .cutsthemustard .active [role=\"main\"] {\n transform: translateX(-75%);\n }\n}\n\nSee the enhanced mustard-cutting off-canvas navigation. Remember, this only applies to small screens so you might have to squish your browser window.\n\nEnhance all the things!\n\nThis was a relatively simple example, but it illustrates the thinking behind progressive enhancement: once you\u2019re providing the core functionality to everyone, you\u2019re free to go crazy with all the latest enhancements for modern browsers.\n\nProgressive enhancement doesn\u2019t mean you have to provide all the same functionality to everyone \u2013 quite the opposite. That\u2019s why it\u2019s key to figure out early on what the core functionality is, and make sure that it can be provided with the most basic technology. But from that point on, you\u2019re free to add many more features that aren\u2019t mission-critical. You should reward more capable browsers by giving them more of those features, such as animation in CSS, geolocation in JavaScript, and new input types in HTML.\n\nLike I said, progressive enhancement isn\u2019t a technology. It\u2019s a way of thinking. Once you start thinking this way, you\u2019ll be prepared for whatever the next ten years throws at us.", "year": "2014", "author": "Jeremy Keith", "author_slug": "jeremykeith", "published": "2014-12-09T00:00:00+00:00", "url": "https://24ways.org/2014/responsive-enhancement/", "topic": "code"} {"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": 128, "title": "Boost Your Hyperlink Power", "contents": "There are HTML elements and attributes that we use every day. Headings, paragraphs, lists and images are the mainstay of every Web developer\u2019s toolbox. Perhaps the most common tool of all is the anchor. The humble a element is what joins documents together to create the gloriously chaotic collection we call the World Wide Web.\n\nAnatomy of an Anchor\n\nThe power of the anchor element lies in the href attribute, short for hypertext reference. This creates a one-way link to another resource, usually another page on the Web:\n\n\n\nThe href attribute sits in the opening a tag and some descriptive text sits between the opening and closing tags:\n\nDrew McLellan\n\n\u201cWhoop-dee-freakin\u2019-doo,\u201d I hear you say, \u201cthis is pretty basic stuff\u201d \u2013 and you\u2019re quite right. But there\u2019s more to the anchor element than just the href attribute.\n\nThe Theory of relativity\n\nYou might be familiar with the rel attribute from the link element. I bet you\u2019ve got something like this in the head of your documents:\n\n\n\nThe rel attribute describes the relationship between the linked document and the current document. In this case, the value of rel is \u201cstylesheet\u201d. This means that the linked document is the stylesheet for the current document: that\u2019s its relationship.\n\nHere\u2019s another common use of rel:\n\n\n\nThis describes the relationship of the linked file \u2013 an RSS feed \u2013 as \u201calternate\u201d: an alternate view of the current document.\n\nBoth of those examples use the link element but you are free to use the rel attribute in regular hyperlinks. Suppose you\u2019re linking to your RSS feed in the body of your page:\n\nSubscribe to my RSS feed.\n\nYou can add extra information to this anchor using the rel attribute:\n\nSubscribe to my RSS feed.\n\nThere\u2019s no prescribed list of values for the rel attribute so you can use whatever you decide is semantically meaningful. Let\u2019s say you\u2019ve got a complex e-commerce application that includes a link to a help file. You can explicitly declare the relationship of the linked file as being \u201chelp\u201d:\n\nneed help?\n\nElemental Microformats\n\nAlthough it\u2019s completely up to you what values you use for the rel attribute, some consensus is emerging in the form of microformats. Some of the simplest microformats make good use of rel. For example, if you are linking to a license that covers the current document, use the rel-license microformat:\n\nLicensed under a Creative Commons attribution license\n\nThat describes the relationship of the linked document as \u201clicense.\u201d\n\nThe rel-tag microformat goes a little further. It uses rel to describe the final part of the URL of the linked file as a \u201ctag\u201d for the current document:\n\nLearn more about semantic markup\n\nThis states that the current document is being tagged with the value \u201cMicroformats.\u201d\n\nXFN, which stands for XHTML Friends Network, is a way of describing relationships between people:\n\nDrew McLellan\n\nThis microformat makes use of a very powerful property of the rel attribute. Like the class attribute, rel can take multiple values, separated by spaces:\n\nDrew McLellan\n\nHere I\u2019m describing Drew as being a friend, someone I\u2019ve met, and a colleague (because we\u2019re both Web monkies).\n\nYou Say You Want a revolution\n\nWhile rel describes the relationship of the linked resource to the current document, the rev attribute describes the reverse relationship: it describes the relationship of the current document to the linked resource. Here\u2019s an example of a link that might appear on help.html:\n\ncontinue shopping\n\nThe rev attribute declares that the current document is \u201chelp\u201d for the linked file.\n\nThe vote-links microformat makes use of the rev attribute to allow you to qualify your links. By using the value \u201cvote-for\u201d you can describe your document as being an endorsement of the linked resource:\n\nI agree with Richard Dawkins.\n\nThere\u2019s a corresponding vote-against value. This means that you can link to a document but explicitly state that you don\u2019t agree with it.\n\nI agree with Richard Dawkins\nabout those creationists. \n\nOf course there\u2019s nothing to stop you using both rel and rev on the same hyperlink:\n\nRichard Dawkins\n\nThe Wisdom of Crowds\n\nThe simplicity of rel and rev belies their power. They allow you to easily add extra semantic richness to your hyperlinks. This creates a bounty that can be harvested by search engines, aggregators and browsers. Make it your New Year\u2019s resolution to make friends with these attributes and extend the power of hypertext.", "year": "2006", "author": "Jeremy Keith", "author_slug": "jeremykeith", "published": "2006-12-18T00:00:00+00:00", "url": "https://24ways.org/2006/boost-your-hyperlink-power/", "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": 258, "title": "Mistletoe Offline", "contents": "It\u2019s that time of year, when we gather together as families to celebrate the life of the greatest person in history. This man walked the Earth long before us, but he left behind words of wisdom. Those words can guide us every single day, but they are at the forefront of our minds during this special season.\nI am, of course, talking about Murphy, and the golden rule he gave unto us:\n\nAnything that can go wrong will go wrong.\n\nSo true! I mean, that\u2019s why we make sure we\u2019ve got nice 404 pages. It\u2019s not that we want people to ever get served a File Not Found message, but we acknowledge that, despite our best efforts, it\u2019s bound to happen sometime. Murphy\u2019s Law, innit?\nBut there are some Murphyesque situations where even your lovingly crafted 404 page won\u2019t help. What if your web server is down? What if someone is trying to reach your site but they lose their internet connection? These are all things than can\u2014and will\u2014go wrong.\nI guess there\u2019s nothing we can do about those particular situations, right?\nWrong!\nA service worker is a Murphy-battling technology that you can inject into a visitor\u2019s device from your website. Once it\u2019s installed, it can intercept any requests made to your domain. If anything goes wrong with a request\u2014as is inevitable\u2014you can provide instructions for the browser. That\u2019s your opportunity to turn those server outage frowns upside down. Take those network connection lemons and make network connection lemonade.\nIf you\u2019ve got a custom 404 page, why not make a custom offline page too?\nGet your server in order\nStep one is to make \u2026actually, wait. There\u2019s a step before that. Step zero. Get your site running on HTTPS, if it isn\u2019t already. You won\u2019t be able to use a service worker unless everything\u2019s being served over HTTPS, which makes sense when you consider the awesome power that a service worker wields.\nIf you\u2019re developing locally, service workers will work fine for localhost, even without HTTPS. But for a live site, HTTPS is a must.\nMake an offline page\nAlright, assuming your site is being served over HTTPS, then step one is to create an offline page. Make it as serious or as quirky as is appropriate for your particular brand. If the website is for a restaurant, maybe you could put the telephone number and address of the restaurant on the custom offline page (unsolicited advice: you could also put this on the home page, you know). Here\u2019s an example of the custom offline page for this year\u2019s Ampersand conference.\nWhen you\u2019re done, publish the offline page at suitably imaginative URL, like, say /offline.html.\nPre-cache your offline page\nNow create a JavaScript file called serviceworker.js. This is the script that the browser will look to when certain events are triggered. The first event to handle is what to do when the service worker is installed on the user\u2019s device. When that happens, an event called install is fired. You can listen out for this event using addEventListener:\naddEventListener('install', installEvent => {\n// put your instructions here.\n}); // end addEventListener\nIn this case, you want to make sure that your lovingly crafted custom offline page is put into a nice safe cache. You can use the Cache API to do this. You get to create as many caches as you like, and you can call them whatever you want. Here, I\u2019m going to call the cache Johnny just so I can refer to it as JohnnyCache in the code:\naddEventListener('install', installEvent => {\n installEvent.waitUntil(\n caches.open('Johnny')\n .then( JohnnyCache => {\n JohnnyCache.addAll([\n '/offline.html'\n ]); // end addAll\n }) // end open.then\n ); // end waitUntil\n}); // end addEventListener\nI\u2019m betting that your lovely offline page is linking to a CSS file, maybe an image or two, and perhaps some JavaScript. You can cache all of those at this point:\naddEventListener('install', installEvent => {\n installEvent.waitUntil(\n caches.open('Johnny')\n .then( JohnnyCache => {\n JohnnyCache.addAll([\n '/offline.html',\n '/path/to/stylesheet.css',\n '/path/to/javascript.js',\n '/path/to/image.jpg'\n ]); // end addAll\n }) // end open.then\n ); // end waitUntil\n}); // end addEventListener\nMake sure that the URLs are correct. If just one of the URLs in the list fails to resolve, none of the items in the list will be cached.\nIntercept requests\nThe next event you want to listen for is the fetch event. This is probably the most powerful\u2014and, let\u2019s be honest, the creepiest\u2014feature of a service worker. Once it has been installed, the service worker lurks on the user\u2019s device, waiting for any requests made to your site. Every time the user requests a web page from your site, a fetch event will fire. Every time that page requests a style sheet or an image, a fetch event will fire. You can provide instructions for what should happen each time:\naddEventListener('fetch', fetchEvent => {\n// What happens next is up to you!\n}); // end addEventListener\nLet\u2019s write a fairly conservative script with the following logic:\n\nWhenever a file is requested,\nFirst, try to fetch it from the network,\nBut if that doesn\u2019t work, try to find it in the cache,\nBut if that doesn\u2019t work, and it\u2019s a request for a web page, show the custom offline page instead.\n\nHere\u2019s how that translates into JavaScript:\n// Whenever a file is requested\naddEventListener('fetch', fetchEvent => {\n const request = fetchEvent.request;\n fetchEvent.respondWith(\n // First, try to fetch it from the network\n fetch(request)\n .then( responseFromFetch => {\n return responseFromFetch;\n }) // end fetch.then\n // But if that doesn't work\n .catch( fetchError => {\n // try to find it in the cache\n caches.match(request)\n .then( responseFromCache => {\n if (responseFromCache) {\n return responseFromCache;\n // But if that doesn't work\n } else {\n // and it's a request for a web page\n if (request.headers.get('Accept').includes('text/html')) {\n // show the custom offline page instead\n return caches.match('/offline.html');\n } // end if\n } // end if/else\n }) // end match.then\n }) // end fetch.catch\n ); // end respondWith\n}); // end addEventListener\nI am fully aware that I may have done some owl-drawing there. If you need a more detailed breakdown of what\u2019s happening at each point in the code, I\u2019ve written a whole book for you. It\u2019s the perfect present for Murphymas.\nHook up your service worker script\nYou can publish your service worker script at /serviceworker.js but you still need to tell the browser where to look for it. You can do that using JavaScript. Put this in an existing JavaScript file that you\u2019re calling in to every page on your site, or add this in a script element at the end of every page\u2019s HTML:\nif (navigator.serviceWorker) {\n navigator.serviceWorker.register('/serviceworker.js');\n}\nThat tells the browser to start installing the service worker, but not without first checking that the browser understands what a service worker is. When it comes to JavaScript, feature detection is your friend.\nYou might already have some JavaScript files in a folder like /assets/js/ and you might be tempted to put your service worker script in there too. Don\u2019t do that. If you do, the service worker will only be able to handle requests made to for files within /assets/js/. By putting the service worker script in the root directory, you\u2019re making sure that every request can be intercepted.\nGo further!\nNicely done! You\u2019ve made sure that if\u2014no, when\u2014a visitor can\u2019t reach your website, they\u2019ll get your hand-tailored offline page. You have temporarily defeated the forces of chaos! You have briefly fought the tide of entropy! You have made a small but ultimately futile gesture against the inevitable heat-death of the universe!\nThis is just the beginning. You can do more with service workers.\nWhat if, every time you fetched a page from the network, you stored a copy of that page in a cache? Then if that person tries to reach that page later, but they\u2019re offline, you could show them the cached version.\nOr, what if instead of reaching out the network first, you checked to see if a file is in the cache first? You could serve up that cached version\u2014which would be blazingly fast\u2014and still fetch a fresh version from the network in the background to pop in the cache for next time. That might be a good strategy for images.\nSo many options! The hard part isn\u2019t writing the code, it\u2019s figuring out the steps you want to take. Once you\u2019ve got those steps written out, then it\u2019s a matter of translating them into JavaScript.\nInevitably there will be some obstacles along the way\u2014usually it\u2019s a misplaced curly brace or a missing parenthesis. Don\u2019t be too hard on yourself if your code doesn\u2019t work at first. That\u2019s just Murphy\u2019s Law in action.", "year": "2018", "author": "Jeremy Keith", "author_slug": "jeremykeith", "published": "2018-12-04T00:00:00+00:00", "url": "https://24ways.org/2018/mistletoe-offline/", "topic": "code"} {"rowid": 280, "title": "Conditional Loading for Responsive Designs", "contents": "On the eighteenth day of last year\u2019s 24 ways, Paul Hammond wrote a great article called Speed Up Your Site with Delayed Content. He outlined a technique for loading some content \u2014 like profile avatars \u2014 after the initial page load. This gives you a nice performance boost.\n\nThere\u2019s another situation where this kind of delayed loading could be really handy: mobile-first responsive design.\n\nResponsive design combines three techniques:\n\n\n\ta fluid grid\n\tflexible images\n\tmedia queries\n\n\nAt first, responsive design was applied to existing desktop-centric websites to allow the layout to adapt to smaller screen sizes. But more recently it has been combined with another innovative approach called mobile first.\n\nRather then starting with the big, bloated desktop site and then scaling down for smaller devices, it makes more sense to start with the constraints of the small screen and then scale up for larger viewports. Using this approach, your layout grid, your large images and your media queries are applied on top of the pre-existing small-screen design. It\u2019s taking progressive enhancement to the next level.\n\nOne of the great advantages of the mobile-first approach is that it forces you to really focus on the core content of your page. It might be more accurate to think of this as a content-first approach. You don\u2019t have the luxury of sidebars or multiple columns to fill up with content that\u2019s just nice to have rather than essential.\n\nBut what happens when you apply your media queries for larger viewports and you do have sidebars and multiple columns? Well, you can load in that nice-to-have content using the same kind of Ajax functionality that Paul described in his article last year. The difference is that you first run a quick test to see if the viewport is wide enough to accommodate the subsidiary content. This is conditional delayed loading.\n\nConsider this situation: I\u2019ve published an article about cats and I\u2019d like to include relevant cat-related news items in the sidebar \u2026but only if there\u2019s enough room on the screen for a sidebar.\n\nI\u2019m going to use Google\u2019s News API to return the search results. This is the ideal time to use delayed loading: I don\u2019t want a third-party service slowing down the rendering of my page so I\u2019m going to fire off the request after my document has loaded.\n\nHere\u2019s an example of the kind of Ajax function that I would write:\n\nvar searchNews = function(searchterm) {\n\tvar elem = document.createElement('script');\n\telem.src = 'http://ajax.googleapis.com/ajax/services/search/news?v=1.0&q='+searchterm+'&callback=displayNews';\n\tdocument.getElementsByTagName('head')[0].appendChild(elem);\n};\n\nI\u2019ve provided a callback function called displayNews that takes the JSON result of that Ajax request and adds it an element on the page with the ID newsresults:\n\nvar displayNews = function(news) {\n\tvar html = '',\n\titems = news.responseData.results,\n\ttotal = items.length;\n\tif (total>0) {\n\t\tfor (var i=0; i';\n\t\t\thtml+= '';\n\t\t\thtml+= '

      '+item.titleNoFormatting+'

      ';\n\t\t\thtml+= '
      ';\n\t\t\thtml+= '

      ';\n\t\t\thtml+= item.content;\n\t\t\thtml+= '

      ';\n\t\t\thtml+= '';\n\t\t}\n\t\tdocument.getElementById('newsresults').innerHTML = html;\n\t}\n};\n\nNow, I can call that function at the bottom of my document:\n\n\n\nIf I only want to run that search when there\u2019s room for a sidebar, I can wrap it in an if statement:\n\n\n\nIf the browser is wider than 640 pixels, that will fire off a search for news stories about cats and put the results into the newsresults element in my markup:\n\n
      \n \n
      \n\nThis works pretty well but I\u2019m making an assumption that people with small-screen devices wouldn\u2019t be interested in seeing that nice-to-have content. You know what they say about assumptions: they make an ass out of you and umptions. I should really try to give everyone at least the option to get to that extra content:\n\n\n\nSee the result\n\nVisitors with small-screen devices will see that link to the search results; visitors with larger screens will get the search results directly.\n\nI\u2019ve been concentrating on HTML and JavaScript, but this technique has consequences for content strategy and information architecture. Instead of thinking about possible page content in a binary way as either \u2018on the page\u2019 or \u2018not on the page\u2019, conditional loading introduces a third \u2018it\u2019s complicated\u2019 option.\n\nThis was just a simple example but I hope it illustrates that conditional loading could become an important part of the content-first responsive design approach.", "year": "2011", "author": "Jeremy Keith", "author_slug": "jeremykeith", "published": "2011-12-02T00:00:00+00:00", "url": "https://24ways.org/2011/conditional-loading-for-responsive-designs/", "topic": "ux"} {"rowid": 320, "title": "DOM Scripting Your Way to Better Blockquotes", "contents": "Block quotes are great. I don\u2019t mean they\u2019re great for indenting content \u2013 that would be an abuse of the browser\u2019s default styling. I mean they\u2019re great for semantically marking up a chunk of text that is being quoted verbatim. They\u2019re especially useful in blog posts. \n\n
      \n

      Progressive Enhancement, as a label for a strategy for Web design, \n was coined by Steven Champeon in a series of articles and presentations \n for Webmonkey and the SxSW Interactive conference.

      \n
      \n\nNotice that you can\u2019t just put the quoted text directly between the
      tags. In order for your markup to be valid, block quotes may only contain block-level elements such as paragraphs.\n\nThere is an optional cite attribute that you can place in the opening
      tag. This should contain a URL containing the original text you are quoting:\n\n
      \n

      Progressive Enhancement, as a label for a strategy for Web design, \n was coined by Steven Champeon in a series of articles and presentations \n for Webmonkey and the SxSW Interactive conference.

      \n
      \n\nGreat! Except\u2026 the default behavior in most browsers is to completely ignore the cite attribute. Even though it contains important and useful information, the URL in the cite attribute is hidden.\n\nYou could simply duplicate the information with a hyperlink at the end of the quoted text:\n\n
      \n

      Progressive Enhancement, as a label for a strategy for Web design, \n was coined by Steven Champeon in a series of articles and presentations \n for Webmonkey and the SxSW Interactive conference.

      \n

      \n source\n

      \n
      \n\nBut somehow it feels wrong to have to write out the same URL twice every time you want to quote something. It could also get very tedious if you have a lot of quotes.\n\nWell, \u201ctedious\u201d is no problem to a programming language, so why not use a sprinkling of DOM Scripting? Here\u2019s a plan for generating an attribution link for every block quote with a cite attribute:\n\n\n\tWrite a function called prepareBlockquotes.\n\tBegin by making sure the browser understands the methods you will be using.\n\tGet all the blockquote elements in the document.\n\tStart looping through each one.\n\tGet the value of the cite attribute.\n\tIf the value is empty, continue on to the next iteration of the loop.\n\tCreate a paragraph.\n\tCreate a link.\n\tGive the paragraph a class of \u201cattribution\u201d.\n\tGive the link an href attribute with the value from the cite attribute.\n\tPlace the text \u201csource\u201d inside the link.\n\tPlace the link inside the paragraph.\n\tPlace the paragraph inside the block quote.\n\tClose the for loop.\n\tClose the function.\n\n\nHere\u2019s how that translates to JavaScript:\n\nfunction prepareBlockquotes() {\n if (!document.getElementsByTagName || !document.createElement || !document.appendChild) return;\n var quotes = document.getElementsByTagName(\"blockquote\");\n for (var i=0; i tags.\n\nYou can style the attribution link using CSS. It might look good aligned to the right with a smaller font size.\n\nIf you\u2019re looking for something to do to keep you busy this Christmas, I\u2019m sure that this function could be greatly improved. Here are a few ideas to get you started:\n\n\n\tShould the text inside the generated link be the URL itself?\n\tIf the block quote has a title attribute, how would you take its value and use it as the text inside the generated link?\n\tShould the attribution paragraph be placed outside the block quote? If so, how would you that (remember, there is an insertBefore method but no insertAfter)?\n\tCan you think of other instances of useful information that\u2019s locked away inside attributes? Access keys? Abbreviations?", "year": "2005", "author": "Jeremy Keith", "author_slug": "jeremykeith", "published": "2005-12-05T00:00:00+00:00", "url": "https://24ways.org/2005/dom-scripting-your-way-to-better-blockquotes/", "topic": "code"} {"rowid": 242, "title": "Creating My First Chrome Extension", "contents": "Writing a Chrome Extension isn\u2019t as scary at it seems!\nNot too long ago, I used a Chrome extension called 20 Cubed. I\u2019m far-sighted, and being a software engineer makes it difficult to maintain distance vision. So I used 20 Cubed to remind myself to look away from my screen and rest my eyes. I loved its simple interface and design. I loved it so much, I often forgot to turn it off in the middle of presentations, where it would take over my entire screen. Oops.\nUnfortunately, the developer stopped updating the extension and removed it from Chrome\u2019s extension library. I was so sad. None of the other eye rest extensions out there matched my design aesthetic, so I decided to create my own! Want to do the same?\nFortunately, Google has some respectable documentation on how to create an extension. And remember, Chrome extensions are just HTML, CSS, and JavaScript. You can add libraries and frameworks, or you can just code the \u201cold-fashioned\u201d way. Sky\u2019s the limit!\nSetup\nBut first, some things you\u2019ll need to know about before getting started:\n\nCallbacks\nTimeouts\nChrome Dev Tools\n\nDeveloping with Chrome extension methods requires a lot of callbacks. If you\u2019ve never experienced the joy of callback hell, creating a Chrome extension will introduce you to this concept. However, things can get confusing pretty quickly. I\u2019d highly recommend brushing up on that subject before getting started.\nHyperbole and a Half\nTimeouts and Intervals are another thing you might want to brush up on. While creating this extension, I didn\u2019t consider the fact that I\u2019d be juggling three timers. And I probably would\u2019ve saved time organizing those and reading up on the Chrome extension Alarms documentation beforehand. But more on that in a bit.\nOn the note of organization, abstraction is important! You might have any combination of the following:\n\nThe Chrome extension options page\nThe popup from the Chrome Menu\nThe windows or tabs you create\nThe background scripts\n\nAnd that can get unwieldy. You might also edit the existing tabs or windows in the browser, which you\u2019ll probably want as a separate script too. Note that this tutorial only covers creating your own customized window rather than editing existing windows or tabs.\nAlright, now that you know all that up front, let\u2019s get going!\nDocumentation\nTL;DR READ THE DOCS.\nA few things to get started:\n\nRead Google\u2019s primer on browser extensions\nHave a look at their Getting started tutorial\nCheck out their overview on Chrome Extensions\n\nThis overview discusses the Chrome extension files, architecture, APIs, and communication between pages. Funnily enough, I only discovered the Overview page after creating my extension.\nThe manifest.json file gives the browser information about the extension, including general information, where to find your extension files and icons, and API permissions required. Here\u2019s what my manifest.json looked like, for example:\nhttps://github.com/jennz0r/eye-rest/blob/master/manifest.json\nBecause I\u2019m a visual learner, I found the images that describe the extension\u2019s architecture most helpful.\n\nTo clarify this diagram, the background.js file is the extension\u2019s event handler. It\u2019s constantly listening for browser events, which you\u2019ll feed to it using the Chrome Extension API. Google says that an effective background script is only loaded when it is needed and unloaded when it goes idle.\nThe Popup is the little window that appears when you click on an extension\u2019s icon in the Chrome Menu. It consists of markup and scripts, and you can tell the browser where to find it in the manifest.json under page_action: { \"default_popup\": FILE_NAME_HERE }.\nThe Options page is exactly as it says. This displays customizable options only visible to the user when they either right-click on the Chrome menu and choose \u201cOptions\u201d under an extension. This also consists of markup and scripts, and you can tell the browser where to find it in the manifest.json under options_page: FILE_NAME_HERE.\nContent scripts are any scripts that will interact with any web windows or tabs that the user has open. These scripts will also interact with any tabs or windows opened by your extension.\nDebugging\nA quick note: don\u2019t forget the debugging tutorial!\nJust like any other Chrome window, every piece of an extension has an inspector and dev tools. If (read: when) you run into errors (as I did), you\u2019re likely to have several inspector windows open \u2013 one for the background script, one for the popup, one for the options, and one for the window or tab the extension is interacting with.\nFor example, I kept seeing the error \u201cThis request exceeds the MAX_WRITE_OPERATIONS_PER_HOUR quota.\u201d Well, it turns out there are limitations on how often you can sync stored information.\nAnother error I kept seeing was \u201cAlarm delay is less than minimum of 1 minutes. In released .crx, alarm \u201cALARM_NAME_HERE\u201d will fire in approximately 1 minutes\u201d. Well, it turns out there are minimum interval times for alarms.\nChrome Extension creation definitely benefits from debugging skills. Especially with callbacks and listeners, good old fashioned console.log can really help!\nMe adding a ton of `console.log`s while trying to debug my alarms.\nEye Rest Functionality\nOk, so what is the extension I created? Again, it\u2019s a way to rest your eyes every twenty minutes for twenty seconds. So, the basic functionality should look like the following:\n\nIf the extension is running AND\nIf the user has not clicked Pause in the Popup HTML AND\nIf the counter in the Popup HTML is down to 00:00 THEN\n\nOpen a new window with Timer HTML AND\nStart a 20 sec countdown in Timer HTML AND\nReset the Popup HTML counter to 20:00\n\nIf the Timer HTML is down to 0 sec THEN\n\nClose that window. Rinse. Repeat.\n\n\nSounds simple enough, but wow, these timers became convoluted! Of all the Chrome extensions I decided to create, I decided to make one that\u2019s heavily dependent on time, intervals, and having those in sync with each other. In other words, I made this unnecessarily complicated and didn\u2019t realize until I started coding.\nFor visual reference of my confusion, check out the GitHub repository for Eye Rest. (And yes, it\u2019s a pun.)\nAPI\nNow let\u2019s discuss the APIs that I used to build this extension.\nAlarms\nWhat even are alarms? I didn\u2019t know either.\nAlarms are basically Chrome\u2019s setTimeout and setInterval. They exist because, as Google says\u2026\n\nDOM-based timers, such as window.setTimeout() or window.setInterval(), are not honored in non-persistent background scripts if they trigger when the event page is dormant.\n\nFor more information, check out this background migration doc.\nOne interesting note about alarms in Chrome extensions is that they are persistent. Garbage collection with Chrome extension alarms seems unreliable at best. I didn\u2019t have much luck using the clearAll method to remove alarms I created on previous extension loads or installs. A workaround (read: hack) is to specify a unique alarm name every time your extension is loaded and clearing any other alarms without that unique name.\nBackground Scripts\nFor Eye Rest, I have two background scripts. One is my actual initializer and event listener, and the other is a helpers file.\nI wanted to share a couple of functions between my Background and Popup scripts. Specifically, the clearAndCreateAlarm function. I wanted my background script to clear any existing alarms, create a new alarm, and add remaining time until the next alarm to local storage immediately upon extension load. To make the function available to the Background script, I added helpers.js as the first item under background > scripts in my manifest.json.\nI also wanted my Popup script to do the same things when the user has unpaused the extension\u2019s functionality. To make the function available to the Popup script, I just include the helpers script in the Popup HTML file.\nOther APIs\nWindows\nI use the Windows API to create the Timer window when the time of my alarm is up. The window creation is initiated by my Background script.\nOne day, while coding late into the evening, I found it very confusing that the window.create method included url as an option. I assumed it was meant to be an external web address. A friend pondered that there must be an option to specify the window\u2019s HTML. Until then, it hadn\u2019t dawned on me that the url could be relative. Duh. I was tired!\nI pass the timer.html as the url option, as well as type, size, position, and other visual options.\nStorage\nMaybe you want to pass information back and forth between the Background script and your Popup script? You can do that using Chrome or local storage. One benefit of using local storage over Chrome\u2019s storage is avoiding quotas and write operation maximums.\nI wanted to pass the time at which the latest alarm was set, the time to the next alarm, and whether or not the timer is paused between the Background and Popup scripts. Because the countdown should change every second, it\u2019s quite complicated and requires lots of writes. That\u2019s why I went with the user\u2019s local storage. You can see me getting and setting those variables in my Background, Helper, and Popup scripts. Just search for date, nextAlarmTime, and isPaused.\nDeclarative Content\nThe Declarative Content API allows you to show your extension\u2019s page action based on several type of matches, without needing to take a host permission or inject a content script. So you\u2019ll need this to get your extension to work in the browser!\nYou can see me set this in my Background script. Because I want my extension\u2019s popup to appear on every page one is browsing, I leave the page matchers empty.\nThere are many more APIs for Chrome apps and extensions, so make sure to surf around and see what features are available!\nThe Extension\nHere\u2019s what my original Popup looked like before I added styles.\nAnd here\u2019s what it looks like with new styles. I guess I\u2019m going for a Nickelodeon feel.\nAnd here\u2019s the Timer window and Popup together! \nPublishing\nPublishing is a cinch. You just zip up your files, create a new or use an existing Google Developer account, upload the files, add some details, and pay a one time $5 fee. That\u2019s all! Then your extension will be available on the Chrome extension store! Neato :D\nMy extension is now available for you to install.\nConclusion\nI thought creating a time based Chrome Extension would be quick and easy. I was wrong. It was more complicated than I thought! But it\u2019s definitely achievable with some time, persistence, and good ole Google searches.\nEventually, I\u2019d like to add more interactive elements to Eye Rest. For example, hitting the YouTube API to grab a silly or cute video as a reward for looking away during the 20 sec countdown and not closing the timer window. This harkens back to one of my first web projects, Toothtimer, from 2012. Or maybe a way to change the background colors of the Timer and Popup!\nEither way, with Eye Rest\u2019s framework built out, I\u2019m feeling fearless about future feature adds! Building this Chrome extension took some broken nails, achy shoulders, and tired eyes, but now Eye Rest can tell me to give my eyes a break every 20 minutes.", "year": "2018", "author": "Jennifer Wong", "author_slug": "jenniferwong", "published": "2018-12-05T00:00:00+00:00", "url": "https://24ways.org/2018/my-first-chrome-extension/", "topic": "code"} {"rowid": 22, "title": "The Responsive Hover Paradigm", "contents": "CSS transitions and animations provide web designers with a whole slew of tools to spruce up our designs. Move over ActionScript tweens! The techniques we can now implement with CSS are reminiscent of Flash-based adventures from the pages of web history.\n\nPairing CSS enhancements with our :hover pseudo-class allows us to add interesting events to our websites. We have a ton of power at our fingertips. However, with this power, we each have to ask ourselves: just because I can do something, should I?\n\nWhy bother? \n\nWe hear a lot of mantras in the web community. Some proclaim the importance of content; some encourage methods like mobile first to support content; and others warn of the overhead and speed impact of decorative flourishes and visual images. I agree, one hundred percent. At the same time, I believe that content can reign king and still provide a beautiful design with compelling interactions and acceptable performance impacts. Maybe, just maybe, we can even have a little bit of fun when crafting these systems!\n\nYes, a site with pure HTML content and no CSS will load very fast on your mobile phone, but it leaves a lot to be desired. If you went to your local library and every book looked the same, how would you know which one to borrow? Imagine if every book was printed on the same paper stock with the same cover page in the same type size set at a legible point value\u2026 how would you know if you were going to purchase a cookbook about wild game or a young adult story about teens fighting to the death?\n\nFor certain audiences, seeing a site with hip, lively hovers sure beats a stale website concept. I\u2019ve worked on many higher education sites, and setting the interactive options is often a very important factor in engaging potential students, alumni, and donors. The same can go for e-commerce sites: enticing your audience with surprise and delight factors can be the difference between a successful and a lost sale. \n\nKnowing your content and audience can help you decide if an intriguing experience is appropriate for your site; if it is, then hover responses can be a real asset. \n\nWhy hover?\n\nWe have all these capabilities with CSS properties to create the aforementioned fun interactions, and it would be quite easy to fall back into some old patterns and animation abuse. The world of Flash intros and skip links could be recreated with CSS keyframes. However, I don\u2019t think any of us want to go the route of forcing users into unwanted exchanges and road blocking content. \n\nWhat\u2019s great about utilizing hover to pair with CSS powered actions is that it\u2019s user initiated. It\u2019s a well-established expectation that when a user mouses over an object, something changes. If we can identify that something as a link, then we will expect something to change as we move our mouse over it. By waiting to trigger a CSS-based response until a user chooses to engage with a target makes for a more polished experience (as opposed to barraging our screens with animations all willy-nilly). This makes it the perfect opportunity to add some unique spunk. \n\nWhat about mobile, touch, and responsive?\n\nSo, you\u2019re on board with this so far, but what about mobile and touch devices? Sure, some devices like the Samsung Galaxy S4 have some hovering capabilities, but certainly most do not. Beyond mobile devices, we also have to worry about desktops with touch capabilities. It\u2019s super difficult to detect if a user is currently using touch or hover. One option we have is to design strictly for touch only and send hover enhancements to the graveyard. However, being that I\u2019m all \u201cfuck yeah hovers!,\u201d I like to explore all options. So, let\u2019s examine four different types of hover patterns and see how they can translate to our touch devices.\n\n1. The essential text hover\n\nChanging text color on hover is something we\u2019ve done for a while and it has helped aid in identifying links. To maintain the best accessibility we can achieve, it helps to have a different visual indicator on the default :link state, such as an underline. By making sure all text links have an underline, we won\u2019t have to rely on visual changes during hover to make sure touch device users know that it is a link. For hover-enabled devices, we can add a basic color transition. Doing so creates a nice fade, which makes the change on hover less jarring. Kinda like smooth jazz. The code* to achieve this is quite simple: \n\na {\n\tcolor: #6dd4b1;\n\ttransition: color 0.25s linear; \n}\n\na:hover, a:focus {\n\tcolor: #357099;\n}\n\n\n\tBrowser prefixes are omitted\n\n\nYou can see in the final result that, for both touch and hover, everyone wins: \n\nSee the Pen Most Basic Link Transition by Jenn Lukas (@Jenn) on CodePen\n\n \n\n2. Visual background wizardry and animated hovers\n\nWe can take this a step further by again making changes to our aesthetic on hover, but not making any content changes. Altering image hovers for fun and personality can separate your site from others; that personality is important and can enhance our content. \n\nLet\u2019s look at a few sites that do this really well. Scroll down to the judges section of CSS Off and check out the illustrations of the judges. On hover, the illustration fades into a photo of the judge. This provides a realistic alternative to the drawing. Users without the hover can click into the detail page, where they can see the full color picture and learn more about the judges; the information is still available through a different pathway. \n\nGoing back to the higher education field, let\u2019s visit Delaware Valley College. The school had recently gone through a rebranding that included loop icons as a symbol to connect ideas. These icons are brought into the website on hover of the slideshow arrows (WebKit browsers). The hover reveals a loop animation, tying in overall themes and adding some extra pizzazz that makes me think, \u201cThis is a hip place that feels current.\u201d For visitors who can\u2019t access the hover effect, the default arrow state clearly represents a clickable link, and there is swipe functionality on mobile devices to boot. \n\nDIY.org\u2019s Frontend Dev page has a bunch of enjoyable hover actions happening, featuring scaling transforms and looping animations. Nothing new is revealed on hover, so touch devices won\u2019t miss anything, but it intrigues the user who is visiting a site about front-end dev doing cool front-end things. It backs up its claim of front-end knowledge by adding this enhancement. \n\nThe old Cowork Chicago (now redirecting) had a great example, captured here:\n\n Coop: Chicago Coworking from Jenn Lukas on Vimeo.\n\nThe code for the Join areas is quite simple: \n\n.join-buttons .daily, .join-buttons .monthly { \n height: 260px; z-index: 0; margin-top: 30px;\n\ttransition: height .2s linear,margin .2s linear;\n}\n\n.join-buttons .daily:hover, .join-buttons .monthly:hover { \n\theight: 280px; margin-top: 20px; \n}\n\nli.button:hover { \n z-index: 20; \n}\n\nThe slight rotation on the photos, and the change of color and size of the rate options on hover, add to the fun factor. The site attempts to advertise the co-working space by letting bits of their charisma show through with these transitions. They don\u2019t hit the user over the head with animations, but provide a nice addition to make sure visitors know it\u2019s a welcoming place to work. Some text is added on the hover, but the text isn\u2019t essential to determine where the link goes.\n\n3. Image block hovers\n\nThere have been more designs popping up with large image blocks acting as extensive hit area links to subsequent pages. On hover of these links, text is revealed, letting the user know where the link destination goes. \n\nSee the Pen Transitioning Max Height by Jenn Lukas (@Jenn) on CodePen\n\nThis type of link is tough for users on touch as the image might not provide enough context to reveal its target. If you weren\u2019t aware of what my illustrated avatar from 2007 looked like (or even if you did), then how would you know that this is a link to my Twitter page? Instead, if we provide enough context \u2014 such as the @jennlukas handle \u2014 you could assume the destination. Users who receive the hover can also see the Twitter bio. It won\u2019t break the experience for users that can\u2019t hover, but it will provide a nice interaction and some more information for those that can. \n\nSee the Pen Transitioning Max Height by Jenn Lukas (@Jenn) on CodePen\n\nThe Esquire site follows this same pattern, in which the title of the story is shown and the subheading is revealed on hover. Dining at Altitude took the opposite approach, where all text is shown by default and, on hover, you can see more of the image that the text sits atop. This is a nice technique to follow. For touch users, following the link will allow them to see more of the image detail that was revealed on hover. \n\n4. Drop-down navigation menu hovers\n\nMain navigation options that rely on hover have come up as a problem for touch. One way to address this is to be sure your top level items are all functional links to somewhere, and not blank anchors to trigger a submenu drop-down. This ensures that, even without the hover-triggered menu, users can still navigate to those top-level pages. From there, they should be able to access the tertiary pages shown in the drop-down. Following this arrangement, drop-down menus act as a quick shortcut and aren\u2019t necessary to the navigational structure. If the top navigation items are your most visited pages, this execution won\u2019t hinder your visitors. \n\nIf the information within the menu is vital, such as a lone account menu, another option is to show drop-down menus on click instead of hover. This pattern will allow both mouse and touch users to access the drop-downs. \n\nWhy can\u2019t we just detect hover?\n\nThis is a really tricky thing to do. Internet Explorer 10 on Windows 8 uses the aria-haspopup attribute to simulate hover on touch devices, but usually our audience stretches beyond that group. There\u2019s been discussion around using Modernizr, but false positives have come with that. A W3C draft for Media Queries Level 4 includes a hover feature, but it\u2019s not supported yet. Since some devices can hover and touch, should you rely on hover effects for those? Arguments have come up that users can be browsing your site with a mouse and then decide to switch to touch, or vice versa. That might be a large concern for you, or it might be an edge case that isn\u2019t vital to your site\u2019s success. \n\nFor one site, I used mousemove and touchstart JavaScript events in order to detect if a visitor starts to browse the site with a mouse. The design initiates for touch users, showing all text on load, but as soon as a mouse movement occurs, the text becomes hidden and is then revealed on hover. \n\nSee the Pen Detect Touch devices with mousemove and touchstart by Jenn Lukas (@Jenn) on CodePen\n\nOne downside to this approach is that the text is viewable until a mouse enters the document, but if the elements are further down the page it might not be noticed. A second downside is if a user on a touch- and hover-enabled device starts browsing with the mouse and then switches back to touch, the hover-centric styles will remain until a new page load. These were acceptable scenarios in the project I worked on, but might not be for every project. \n\nCan we give our visitors a choice?\n\nI\u2019ve been thinking about how we can combat the concern of not knowing if our customers are using touch or a mouse, not to mention keyboard or Wacom tablets or Minority Report screens. We can cover keyboards with our friend :focus, but that still doesn\u2019t solve our other dilemmas. \n\nRemember when we couldn\u2019t rely on browsers to zoom text and we had to use those small A, medium A, big A [AAA] buttons? On selection of one of those options, a different style sheet would load with small, medium, or large text sizes to satisfy our user\u2019s request. We could even set cookies to remember their font choices. What if we offered a similar solution, a hover/touch switcher, for our new predicament? \n\nSee the Pen cwuJf by Jenn Lukas (@Jenn) on CodePen\n\nWe could add this switcher to our design. Maybe add it to the header on smaller screens and the footer on larger screens to play the odds. Then be sure to deliver the appropriate touch- or hover-optimized adventure for our guests.\n\nHow about adding View options in the areas where we\u2019re hiding content until hover? Looking at Delta Cycle, there\u2019s logic in place to switch layouts on some mobile devices. On desktops we can see the layout shows the product and price by default, and the name of the item and an Add to cart button on hover. If you want to keep this hover, but also worry that touch users can\u2019t access it \u2014 or even if you are concerned that people might want to view it with more details up front \u2014 we could add another view switcher. \n\nSee the Pen List/Grid Views for Hover or Touch by Jenn Lukas (@Jenn) on CodePen\n\nSimilar to the list versus grid view we often see in operating systems, a choice here could cover all of our bases. \n\nConclusion\n\nThere is no one-size-fits-all solution when it comes to hover patterns. Design for your content. If you are providing important information about driving directions or healthcare, you might want to err on the side of designing for touch only. If you are behind an educational site and trying to entice more traffic and sign-ups, or a more immersive e-commerce site selling pies, then hover activity can help support your content and engage your visitors without being a detriment. While content can be our top priority, let\u2019s not forget that our designs and interactions, hovers included, can have a great positive impact on how visitors experience our site. Hover wisely, friends.", "year": "2013", "author": "Jenn Lukas", "author_slug": "jennlukas", "published": "2013-12-12T00:00:00+00:00", "url": "https://24ways.org/2013/the-responsive-hover-paradigm/", "topic": null} {"rowid": 305, "title": "CSS Writing Modes", "contents": "Since you may not have a lot of time, I\u2019m going to start at the end, with the dessert.\nYou can use a little-known, yet important and powerful CSS property to make text run vertically. Like this.\n\nOr instead of running text vertically, you can layout a set of icons or interface buttons in this way. Or, of course, with anything on your page. \nThe CSS I\u2019ve applied makes the browser rethink the orientation of the world, and flow the layout of this element at a 90\u00b0 angle to \u201cnormal\u201d. Check out the live demo, highlight the headline, and see how the cursor is now sideways.\nSee the Pen Writing Mode Demo \u2014 Headline by Jen Simmons (@jensimmons) on CodePen.\n\nThe code for accomplishing this is pretty simple. \nh1 { \n writing-mode: vertical-rl;\n}\nThat\u2019s all it takes to switch the writing mode from the web\u2019s default horizontal top-to-bottom mode to a vertical right-to-left mode. If you apply such code to the html element, the entire page is switched, affecting the scroll direction, too. \nIn my example above, I\u2019m telling the browser that only the h1 will be in this vertical-rl mode, while the rest of my page stays in the default of horizontal-tb.\nSo now the dessert course is over. Let me serve up this whole meal, and explain the the CSS Writing Mode Specification.\nWhy learn about writing modes?\nThere are three reasons I\u2019m teaching writing modes to everyone\u2014including western audiences\u2014and explaining the whole system, instead of quickly showing you a simple trick.\n\n\nWe live in a big, diverse world, and learning about other languages is fascinating. Many of you lay out pages in languages like Chinese, Japanese and Korean. Or you might be inspired to in the future.\n\n\nUsing writing-mode to turn bits sideways is cool. This CSS can be used in all kinds of creative ways, even if you are working only in English.\n\nMost importantly, I\u2019ve found understanding Writing Modes incredibly helpful when understanding Flexbox and CSS Grid. Before I learned Writing Mode, I felt like there was still a big hole in my knowledge, something I just didn\u2019t get about why Grid and Flexbox work the way they do. Once I wrapped my head around Writing Modes, Grid and Flexbox got a lot easier. Suddenly the Alignment properties, align-* and justify-*, made sense.\n\nWhether you know about it or not, the writing mode is the first building block of every layout we create. You can do what we\u2019ve been doing for 25 years \u2013 and leave your page set to the default left-to-right direction, horizontal top-to-bottom writing mode. Or you can enter a world of new possibilities where content flows in other directions.\nCSS properties\nI\u2019m going to focus on the CSS writing-mode property in this article. It has five possible options:\n writing-mode: horizontal-tb;\n writing-mode: vertical-rl;\n writing-mode: vertical-lr;\n writing-mode: sideways-rl;\n writing-mode: sideways-lr;\nThe CSS Writing Modes Specification is designed to support a wide range of written languages in all our human and linguistic complexity. Which\u2014spoiler alert\u2014is pretty insanely complex. The global evolution of written languages has been anything but simple. \nSo I\u2019ve got to start with explaining some basic concepts of web page layout and writing systems. Then I can show you what these CSS properties do. \nInline Direction, Block Direction, and Character Direction\nIn the world of the web, there\u2019s a concept of \u2018block\u2019 and \u2018inline\u2019 layout. If you\u2019ve ever written display: block or display: inline, you\u2019ve leaned on these concepts. \nIn the default writing mode, blocks stack vertically starting at the top of the page and working their way down. Think of how a bunch of block-levels elements stack\u2014like a bunch of a paragraphs\u2014that\u2019s the block direction. \n\nInline is how each line of text flows. The default on the web is from left to right, in horizontal lines. Imagine this text that you are reading right now, being typed out one character at a time on a typewriter. That\u2019s the inline direction. \n\nThe character direction is which way the characters point. If you type a capital \u201cA\u201d for instance, on which side is the top of the letter? Different languages can point in different directions. Most languages have their characters pointing towards the top of the page, but not all.\n\nPut all three together, and you start to see how they work as a system. \nThe default settings for the web work like this.\nNow that we know what block, inline, and character directions mean, let\u2019s see how they are used in different writing systems from around the world.\nThe four writing systems of CSS Writing Modes\nThe CSS Writing Modes Specification handles all the use cases for four major writing systems; Latin, Arabic, Han and Mongolian. \nLatin-based systems\nOne writing system dominates the world more than any other, reportedly covering about 70% of the world\u2019s population. \n\nThe text is horizontal, running from left to right, or LTR. The block direction runs from top to bottom. \nIt\u2019s called the Latin-based system because it includes all languages that use the Latin alphabet, including English, Spanish, German, French, and many others. But there are many non-Latin-alphabet languages that also use this system, including Greek, Cyrillic (Russian, Ukrainian, Bulgarian, Serbian, etc.), and Brahmic scripts (Devanagari, Thai, Tibetan), and many more.\nYou don\u2019t need to do anything in your CSS to trigger this mode. This is the default. \nBest practices, however, dictate that you declare in your opening element which language and which direction (LTR or RTL) you are using. This website, for instance, uses to let the browser know this content is published in Great Britian\u2019s version of English, in a left to right direction. \nArabic-based systems\nArabic, Hebrew and a few other languages run the inline direction from right to left. This is commonly known as RTL. \nNote that the inline direction still runs horizontally. The block direction runs from top to bottom. And the characters are upright.\n\nIt\u2019s not just the flow of text that runs from right to left, but everything about the layout of the website. The upper right-hand corner is the starting position. Important things are on the right. The eyes travel from right to left. So, typically RTL websites use layouts that are just like LTR websites, only flipped.\nOn websites that support both LTR and RTL, like the United Nations\u2019 site at un.org, the two layouts are mirror images of each other.\nFor many web developers, our experiences with internationalization have focused solely on supporting Arabic and Hebrew script. \nCSS layout hacks for internationalization & RTL\nTo prepare an LTR project to support RTL, developers have had to create all sorts of hacks. For example, the Drupal community started a convention of marking every margin-left and -right, every padding-left and -right, every float: left and float: right with the comment /* LTR */. Then later developers could search for each instance of that exact comment, and create stylesheets to override each left with right, and vice versa. It\u2019s a tedious and error prone way to work. CSS itself needed a better way to let web developers write their layout code once, and easily switch language directions with a single command.\nOur new CSS layout system does exactly that. Flexbox, Grid and Alignment use start and end instead of left and right. This lets us define everything in relationship to the writing system, and switch directions easily. By writing justify-content: flex-start, justify-items: end, and eventually margin-inline-start: 1rem we have code that doesn\u2019t need to be changed. \nThis is a much better way to work. I know it can be confusing to think through start and end as replacements for left and right. But it\u2019s better for any multiligual project, and it\u2019s better for the web as a whole.\nSadly, I\u2019ve seen CSS preprocessor tools that claim to \u201cfix\u201d the new CSS layout system by getting rid of start and end and bringing back left and right. They want you to use their tool, write justify-content: left, and feel self-righteous. It seems some folks think the new way of working is broken and should be discarded. It was created, however, to fulfill real needs. And to reflect a global internet. As Bruce Lawson says, WWW stands for the World Wide Web, not the Wealthy Western Web. Please don\u2019t try to convince the industry that there\u2019s something wrong with no longer being biased towards western culture. Instead, spread the word about why this new system is here. \nSpend a bit of time drilling the concept of inline and block into your head, and getting used to start and end. It will be second nature soon enough. \nI\u2019ve also seen CSS preprocessors that let us use this new way of thinking today, even as all the parts aren\u2019t fully supported by browsers yet. Some tools let you write text-align: start instead of text-align: left, and let the preprocessor handle things for you. That is terrific, in my opinion. A great use of the power of a preprocessor to help us switch over now. \nBut let\u2019s get back to RTL. \nHow to declare your direction\nYou don\u2019t want to use CSS to tell the browser to switch from an LTR language to RTL. You want to do this in your HTML. That way the browser has the information it needs to display the document even if the CSS doesn\u2019t load.\nThis is accomplished mainly on the html element. You should also declare your main language. As I mentioned above, the 24 ways website is using to declare the LTR direction and the use of British English. The UN Arabic website uses to declare the site as an Arabic site, using a RTL layout. \nThings get more complicated when you\u2019ve got a page with a mix of languages. But I\u2019m not going to get into all of that, since this article is focused on CSS and layouts, not explaining everything about internationalization. \nLet me just leave direction here by noting that much of the heavy work of laying out the characters which make up each word is handled by Unicode. If you are interested in learning more about LTR, RTL and bidirectional text, watch this video: Introduction to Bidirectional Text, a presentation by Elika Etemad. \nMeanwhile, let\u2019s get back to CSS.\nThe writing mode CSS for Latin-based and Arabic-based systems\nFor both of these systems\u2014Latin-based and Arabic-based, whether LTR or RTL\u2014the same CSS property applies for specifying the writing mode: writing-mode: horizontal-tb. That\u2019s because in both systems, the inline text flow is horizontal, while the block direction is top-to-bottom. This is expressed as horizontal-tb.\nhorizontal-tb is the default writing mode for the web, so you don\u2019t need to specify it unless you are overriding something else higher up in the cascade. You can just imagine that every site you\u2019ve ever built came with:\nhtml {\n writing-mode: horizontal-tb;\n}\nNow let\u2019s turn our attention to the vertical writing systems. \nHan-based systems\nThis is where things start to get interesting. \nHan-based writing systems include CJK languages, Chinese, Japanese, Korean and others. There are two options for laying out a page, and sometimes both are used at the same time.\nMuch of CJK text is laid out like Latin-based languages, with a horizontal top-to-bottom block direction, and a left-to-right inline direction. This is the more modern way to doing things, started in the 20th century in many places, and further pushed into domination by the computer and later the web. \nThe CSS to do this bit of the layouts is the same as above:\nsection {\n writing-mode: horizontal-tb;\n}\nOr, you know, do nothing, and get that result as a default. \nAlternatively Han-based languages can be laid out in a vertical writing mode, where the inline direction runs vertically, and the block direction goes from right to left. \nSee both options in this diagram:\n\nNote that the horizontal text flows from left to right, while the vertical text flows from right to left. Wild, eh? \nThis Japanese issue of Vogue magazine is using a mix of writing modes. The cover opens on the left spine, opposite of what an English magazine does. \n\nThis page mixes English and Japanese, and typesets the Japanese text in both horizontal and vertical modes. Under the title \u201cRichard Stark\u201d in red, you can see a passage that\u2019s horizontal-tb and LTR, while the longer passage of text at the bottom of the page is typeset vertical-rl. The red enlarged cap marks the beginning of that passage. The long headline above the vertical text is typeset LTR, horizontal-tb.\n\nThe details of how to set the default of the whole page will depend on your use case. But each element, each headline, each section, each article can be marked to flow the opposite of the default however you\u2019d like.\nFor example, perhaps you leave the default as horizontal-tb, and specify your vertical elements like this:\ndiv.articletext {\n writing-mode: vertical-rl;\n}\nOr alternatively you could change the default for the page to a vertical orientation, and then set specific elements to horizontal-tb, like this:\nhtml { \n writing-mode: vertical-rl;\n}\nh2, .photocaptions, section {\n writing-mode: horizontal-tb;\n}\nIf your page has a sideways scroll, then the writing mode will determine whether the page loads with upper left corner as the starting point, and scroll to the right (horizontal-tb as we are used to), or if the page loads with the upper right corner as the starting point, scrolling to the left to display overflow. Here\u2019s an example of that change in scrolling direction, in a CSS Writing Mode demo by Chen Hui Jing. Check out her demo \u2014 you can switch from horizontal to vertical writing modes with a checkbox and see the difference. \n\nMongolian-based systems\nNow, hopefully so far all of this kind of makes sense. It might be a bit more complicated than expected, but it\u2019s not so hard. Well, enter the Mongolian-based systems.\nMongolian is also a vertical script language. Text runs vertically down the page. Just like Han-based systems. There are two major differences. First, the block direction runs the other way. In Mongolian, block-level elements stack from left to right. \nHere\u2019s a drawing of how Wikipedia would look in Mongolian if it were laid out correctly.\nPerhaps the Mongolian version of Wikipedia will be redone with this layout.\nNow you might think, that doesn\u2019t look so weird. Tilt your head to the left, and it\u2019s very familiar. The block direction starts on the left side of the screen and goes to the right. The inline direction starts on the top of the page and moves to the bottom (similar to RTL text, just turned 90\u00b0 counter-clockwise). But here comes the other huge difference. The character direction is \u201cupside down\u201d. The top of the Mongolian characters are not pointing to the left, towards the start edge of the block direction. They point to the right. Like this:\n\nNow you might be tempted to ignore all this. Perhaps you don\u2019t expect to be typesetting Mongolian content anytime soon. But here\u2019s why this is important for everyone \u2014 the way Mongolian works defines the results writing-mode: vertical-lr. And it means we cannot use vertical-lr for typesetting content in other languages in the way we might otherwise expect. \nIf we took what we know about vertical-rl and guessed how vertical-lr works, we might imagine this:\n\nBut that\u2019s wrong. Here\u2019s how they actually compare:\n\nSee the unexpected situation? In both writing-mode: vertical-rl and writing-mode: vertical-lr latin text is rotated clockwise. Neither writing mode let\u2019s us rotate text counter-clockwise. \nIf you are typesetting Mongolian content, apply this CSS in the same way you would apply writing-mode to Han-based writing systems. To the whole page on the html element, or to specific pages of the page like this:\nsection {\n writing-mode: vertical-lr;\n}\nNow, if you are using writing-mode for a graphic design effect on a language that is otherwise typesets horizontally, I don\u2019t think writing-mode: vertical-lr is useful. If the text wraps onto two lines, it stacks in a very unexpected way. So I\u2019ve sort of obliterated it from my toolkit. I find myself using writing-mode: vertical-rl a lot. And never using -lr. Hm.\nWriting modes for graphic design\nSo how do we use writing-mode to turn English headlines sideways? We could rely on transform: rotate()\nHere are two examples, one for each direction. (By the way, each of these demos use CSS Grid for their overall layout, so be sure to test them in a browser that supports CSS Grid, like Firefox Nightly.)\n\nIn this demo 4A, the text is rotated clockwise using this code: \nh1 {\n writing-mode: vertical-rl;\n}\n\nIn this demo 4B, the text is rotated counter-clockwise using this code: \nh1 {\n writing-mode: vertical-rl;\n transform: rotate(180deg);\n text-align: right;\n}\nI use vertical-rl to rotate the text so that it takes up the proper amount of space in the overall flow of the layout. Then I rotate it 180\u00b0 to spin it around to the other direction. And then I use text-align: right to get it to rise up to the top of it\u2019s container. This feels like a hack, but it\u2019s a hack that works.\nNow what I would like to do instead is use another CSS value that was designed for this use case \u2014 one of the two other options for writing mode.\nIf I could, I would lay out example 4A with:\nh1 {\n writing-mode: sideways-rl;\n}\nAnd layout example 4B with: \nh1 {\n writing-mode: sideways-lr;\n}\nThe problem is that these two values are only supported in Firefox. None of the other browsers recognize sideways-*. Which means we can\u2019t really use it yet. \nIn general, the writing-mode property is very well supported across browsers. So I\u2019ll use writing-mode: vertical-rl for now, with the transform: rotate(180deg); hack to fake the other direction. \nThere\u2019s much more to what we can do with the CSS designed to support multiple languages, but I\u2019m going to stop with this intermediate introduction. \nIf you do want a bit more of a taste, look at this example that adds text-orientation: upright; to the mix \u2014 turning the individual letters of the latin font to be upright instead of sideways.\n\nIt\u2019s this demo 4C, with this CSS applied: \nh1 {\n writing-mode: vertical-rl;\n text-orientation: upright;\n text-transform: uppercase;\n letter-spacing: -25px;\n}\nYou can check out all my Writing Modes demos at labs.jensimmons.com/#writing-modes. \n\nI\u2019ll leave you with this last demo. One that applies a vertical writing mode to the sub headlines of a long article. I like how small details like this can really bring a fresh feeling to the content. \nSee the Pen Writing Mode Demo \u2014 Article Subheadlines by Jen Simmons (@jensimmons) on CodePen.", "year": "2016", "author": "Jen Simmons", "author_slug": "jensimmons", "published": "2016-12-23T00:00:00+00:00", "url": "https://24ways.org/2016/css-writing-modes/", "topic": "code"} {"rowid": 48, "title": "A Holiday Wish", "contents": "A friend and I were talking the other day about why clients spend more on toilet cleaning than design, and how the industry has changed since the mid-1990s, when we got our starts. Early in his career, my friend wrote a fine CSS book, but for years he has called himself a UX designer. And our conversation got me thinking about how I reacted to that title back when I first started hearing it.\n\n\u201cJust what this business needs,\u201d I said to myself, \u201canother phony expert.\u201d\n\nOkay, so I was wrong about UX, but my touchiness was not altogether unfounded. In the beginning, our industry was divided between freelance jack-of-all-trade punks, who designed and built and coded and hosted and Photoshopped and even wrote the copy when the client couldn\u2019t come up with any, and snot-slick dot-com mega-agencies that blew up like Alice and handed out titles like impoverished nobles in the years between the world wars. \n\nI was the former kind of designer, a guy who, having failed or just coasted along at a cluster of other careers, had suddenly, out of nowhere, blossomed into a web designer\u2014an immensely curious designer slash coder slash writer with a near-insatiable lust to shave just one more byte from every image. We had modems back then, and I dreamed in sixteen colors. My source code was as pretty as my layouts (arguably prettier) and I hoovered up facts and opinions from newsgroups and bulletin boards as fast as any loudmouth geek could throw them. It was a beautiful life.\n\nBut soon, too soon, the professional digital agencies arose, buying loft buildings downtown, jacking in at T1 speeds, charging a hundred times what I did, and communicating with their clients in person, in large artfully bedecked rooms, wearing hand-tailored Barney\u2019s suits and bringing back the big city bullshit I thought I\u2019d left behind when I quit advertising to become a web designer. \n\nJust like the big bad ad agencies of my early career, the new digital agencies stocked every meeting with a totem pole worth of ranks and titles. If the client brought five upper middle managers to the meeting, the agency did likewise. If fifteen stakeholders got to ask for a bigger logo, fifteen agency personnel showed up to take notes on the percentage of enlargement required.\n\nBut my biggest gripe was with the titles.\n\nThe bigger and more expensive the agency, the lousier it ran with newly invented titles. Nobody was a designer any more. Oh, no. Designer, apparently, wasn\u2019t good enough. Designer was not what you called someone you threw that much money at.\n\nInstead of designers, there were user interaction leads and consulting middleware integrators and bilabial experience park rangers and you name it. At an AIGA Miami event where I was asked to speak in the 1990s, I once watched the executive creative director of the biggest dot-com agency of the day make a presentation where he spent half his time bragging that the agency had recently shaved down the number of titles for people who basically did design stuff from forty-six to just twenty-three\u2014he presented this as though it were an Einsteinian coup\u2014and the other half of his time showing a film about the agency\u2019s newly opened branch in Oslo. The Oslo footage was shot in December. I kept wondering which designer in the audience who lived in the constant breezy balminess of Miami they hoped to entice to move to dark, wintry Norway. But I digress.\n\nShortly after I viewed this presentation, the dot-com world imploded, brought about largely by the euphoric excess of the agencies and their clients. But people still needed websites, and my practice flourished\u2014to the point where, in 1999, I made the terrifying transition from guy in his underwear working freelance out of his apartment to head of a fledgling design studio. (Note: you never stop working on that change.)\n\nI had heard about experience design in the 1990s, but assumed it was a gig for people who only knew one font. \n\nBut sometime around 2004 or 2005, among my freelance and small-studio colleagues, like a hobbit in the Shire, I began hearing whispers in the trees of a new evil stirring. The fires of Mordor were burning. Web designers were turning in their HTML editing tools and calling themselves UXers.\n\nI wasn\u2019t sure if they pronounced it \u201cuck-sir,\u201d or \u201cyou-ex-er,\u201d but I trusted their claims to authenticity about as far as I trusted the actors in a Doctor Pepper commercial when they claimed to be Peppers. I\u2019m an UXer, you\u2019re an UXer, wouldn\u2019t you like to be an UXer too? No thanks, said I. I still make things. With my hands.\n\nSuch was my thinking. I may have earned an MFA at the end of some long-past period of soul confusion, but I have working-class roots and am profoundly suspicious of, well, everything, but especially of anything that smacks of pretense. I got exporting GIFs. I didn\u2019t get how white papers and bullet points helped anybody do anything.\n\nI was wrong. And gradually I came to know I was wrong. And before other members of my tribe embraced UX, and research, and content strategy, and the other airier consultant services, I was on board. It helped that my wife of the time was a librarian from Michigan, so I\u2019d already bought into the cult of information architecture. And if I wasn\u2019t exactly the seer who first understood how borderline academic practices related to UX could become as important to our medium and industry as our craft skills, at least I was down a lot faster than Judd Apatow got with feminism. But I digress.\n\nI love the web and all the people in it. Today I understand design as a strategic practice above all. The promise of the web, to make all knowledge accessible to all people, won\u2019t be won by HTML5, WCAG 2, and responsive web design alone. \n\nWe are all designers. You may call yourself a front-end developer, but if you spend hours shaving half-seconds off an interaction, that\u2019s user experience and you, my friend, are a designer. If the client asks, \u201cCan you migrate all my old content to the new CMS?\u201d and you answer, \u201cOf course we can, but should we?\u201d, you are a designer. Even our users are designers. Think about it. \n\nOnce again, as in the dim dumb dot-com past, we seem to be divided by our titles. But, O, my friends, our varied titles are only differing facets of the same bright gem. Sisters, brothers, we are all designers. Love on! Love on!\n\nAnd may all your web pages, cards, clusters, clumps, asides, articles, and relational databases be bright.", "year": "2014", "author": "Jeffrey Zeldman", "author_slug": "jeffreyzeldman", "published": "2014-12-18T00:00:00+00:00", "url": "https://24ways.org/2014/a-holiday-wish/", "topic": "ux"} {"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": 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": 97, "title": "Making Modular Layout Systems", "contents": "For all of the advantages the web has with distribution of content, I\u2019ve always lamented the handiness of the WYSIWYG design tools from the print publishing world. When I set out to redesign my personal website, I wanted to have some of the same abilities that those tools have, laying out pages how I saw fit, and that meant a flexible system for dealing with imagery. \n\nBuilding on some of the CSS that Eric Meyer employed a few years back on the A List Apart design, I created a set of classes to use together to achieve the variety I was after. Employing multiple classes isn\u2019t a new technique, but most examples aren\u2019t coming at this from strictly editorial and visual perspectives; I wanted to have options to vary my layouts depending on content.\n\nIf you want to skip ahead, you can view the example first.\n\nLaying the Foundation\n\nWe need to be able to map out our page so that we have predictable canvas, and then create a system of image sizes that work with it. For the sake of this article, let\u2019s use a simple uniform 7-column grid, consisting of seven 100px-wide columns and 10px of space between each column, though you can use any measurements you want as long as they remain constant.\n\n\nAll of our images will have a width that references the grid column widths (in our example, 100px, 210px, 320px, 430px, 540px, 650px, or 760px), but the height can be as large as needed.\n\n\nOnce we know our images will all have one of those widths, we can setup our CSS to deal with the variations in layout. In the most basic form, we\u2019re going to be dealing with three classes: one each that represent an identifier, a size, and a placement for our elements.\n\n\nThis is really a process of abstracting the important qualities of what you would do with a given image in a layout into separate classes, allowing you to quickly customize their appearance by combining the appropriate classes. Rather than trying to serve up a one-size-fits-all approach to styling, we give each class only one or two attributes and rely on the combination of classes to get us there.\n\n\nIdentifier\n\nThis specifies what kind of element we have: usually either an image (pic) or some piece of text (caption).\n\n\nSize\n\nSince we know how our grid is constructed and the potential widths of our images, we can knock out a space equal to the width of any number of columns. In our example, that value can be one, two, three, four, five, six, or seven.\n\nPlacement\n\nThis tells the element where to go. In our example we can use a class of left or right, which sets the appropriate floating rule.\n\n\nAdditions\n\nI created a few additions that be tacked on after the \u201cplacement\u201d in the class stack: solo, for a bit more space beneath images without captions, frame for images that need a border, and inset for an element that appears inside of a block of text. Outset images are my default, but you could easily switch the default concept to use inset images and create a class of outset to pull them out of the content columns.\n\n\nThe CSS\n\n/* I D E N T I F I E R */\n.pic p, .caption {\n font-size: 11px;\n line-height: 16px;\n font-family: Verdana, Arial, sans-serif;\n color: #666;\n margin: 4px 0 10px;\n}\n/* P L A C E M E N T */\n.left {float: left; margin-right: 20px;}\n.right {float: right; margin-left: 20px;}\n.right.inset {margin: 0 120px 0 20px;} /* img floated right within text */\n.left.inset {margin-left: 230px;} /* img floated left within text */\n/* S I Z E */\n.one {width: 100px;}\n.two {width: 210px;}\n.three {width: 320px;}\n.four {width: 430px;}\n.five {width: 540px;}\n.six {width: 650px;}\n.seven {width: 760px;}\n.eight {width: 870px;}\n/* A D D I T I O N S */\n.frame {border: 1px solid #999;}\n.solo img {margin-bottom: 20px;}\n\nIn Use\n\nYou can already see how powerful this approach can be. If you want an image and a caption on the left to stretch over half of the page, you would use:\n\n
      \n\t\n\t

      Caption goes here.

      \n
      \n\nOr, for that same image with a border and no caption:\n\n\n\nYou just tack on the classes that contain the qualities you need. And because we\u2019ve kept each class so simple, we can apply these same stylings to other elements too:\n\n

      Caption goes here.

      \n\nCaveats\n\nObviously there are some potential semantic hang-ups with these methods. While classes like pic and caption stem the tide a bit, others like left and right are tougher to justify. This is something that you have to decide for yourself; I\u2019m fine with the occasional four or left class because I think there\u2019s a good tradeoff. Just as a fully semantic solution to this problem would likely be imperfect, this solution is imperfect from the other side of the semantic fence. Additionally, IE6 doesn\u2019t understand the chain of classes within a CSS selector (like .right.inset). If you need to support IE6, you may have to write a few more CSS rules to accommodate any discrepancies.\n\nOpportunities\n\nThis is clearly a simple example, but starting with a modular foundation like this leaves the door open for opportunity. We\u2019ve created a highly flexible and human-readable system for layout manipulation. Obviously, this is something that would need to be tailored to the spacing and sizes of your site, but the systematic approach is very powerful, especially for editorial websites whose articles might have lots of images of varying sizes. It may not get us fully to the flexibility of WYSIWYG print layouts, but methods like this point us in a direction of designs that can adapt to the needs of the content.\n\n\nView the example: without grid and with grid.", "year": "2008", "author": "Jason Santa Maria", "author_slug": "jasonsantamaria", "published": "2008-12-15T00:00:00+00:00", "url": "https://24ways.org/2008/making-modular-layout-systems/", "topic": "process"} {"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": 127, "title": "Showing Good Form", "contents": "Earlier this year, I forget exactly when (it\u2019s been a good year), I was building a client site that needed widgets which look like this (designed, incidentally, by my erstwhile writing partner, Cameron Adams):\n\n\n\nBuilding this was a challenge not just in CSS, but in choosing the proper markup \u2013 how should such a widget be constructed?\n\nMmm \u2026 markup\n\nIt seemed to me there were two key issues to deal with:\n\n\n\tThe function of the interface is to input information, so semantically this is a form, therefore we have to find a way of building it using form elements: fieldset, legend, label and input\n\tWe can\u2019t use a table for layout, even though that would clearly be the easiest solution!\n\n\nAbusing tables for layout is never good \u2013 physical layout is not what table semantics mean. But even if this data can be described as a table, we shouldn\u2019t mix forms markup with non-forms markup, because of the behavioral impact this can have on a screen reader:\n\nTo take a prominent example, the screen reader JAWS has a mode specifically for interacting with forms (cunningly known as \u201cforms mode\u201d). When running in this mode its output only includes relevant elements \u2013 legends, labels and form controls themselves. Any other kind of markup \u2013 like text in a previous table cell, a paragraph or list in between \u2013 is simply ignored. The user in this situation would have to switch continually in and out of forms mode to hear all the content. (For more about this issue and some test examples, there\u2019s a thread at accessify forum which wanders in that direction.)\n\nOne further issue for screen reader users is implied by the design: the input fields are associated together in rows and columns, and a sighted user can visually scan across and down to make those associations; but a blind user can\u2019t do that. For such a user the row and column header data will need to be there at every axis; in other words, the layout should be more like this:\n\n\n\nAnd constructed with appropriate semantic markup to convey those relationships. By this point the selection of elements seems pretty clear: each row is a fieldset, the row header is a legend, and each column header is a label, associated with an input.\n\nHere\u2019s what that form looks like with no CSS:\n\n\n\nAnd here\u2019s some markup for the first row (with most of the attributes removed just to keep this example succinct):\n\n
      \n\t\n\t\tMatch points\n\t\n\t\n\t\n\t\n\t\n
      \n\nThe span inside each legend is because legend elements are highly resistant to styling! Indeed they\u2019re one of the most stubborn elements in the browsers\u2019 vocabulary. Oh man \u2026 how I wrestled with the buggers \u2026 until this obvious alternative occurred to me! So the legend element itself is just a container, while all the styling is on the inner span.\n\nOh yeah, there was some CSS too\n\nI\u2019m not gonna dwell too much on the CSS it took to make this work \u2013 this is a short article, and it\u2019s all there in the demo [demo page, style sheet]\n\nBut I do want to touch on the most interesting bit \u2013 where we get from a layout with headers on every row, to one where only the top row has headers \u2013 or at least, so it appears to graphical browsers. For screen readers, as we noted, we need those headers on every row, so we should employ some cunning CSS to partly negate their visual presence, without removing them from the output.\n\nThe core styling for each label span is like this:\n\nlabel span\n{\n\tdisplay:block;\n\tpadding:5px;\n\tline-height:1em;\n\tbackground:#423221;\n\tcolor:#fff;\n\tfont-weight:bold;\n}\n\nBut in the rows below the header they have these additional rules:\n\nfieldset.body label span\n{\n\tpadding:0 5px;\n\tline-height:0;\n\tposition:relative;\n\ttop:-10000em;\n}\n\nThe rendered width of the element is preserved, ensuring that the surrounding label is still the same width as the one in the header row above, and hence a unified column width is preserved all the way down. But the element effectively has no height, and so it\u2019s effectively invisible. The styling is done this way, rather than just setting the height to zero and using overflow:hidden, because to do that would expose an unrelated quirk with another popular screen reader! (It would hide the output from Window Eyes, as shown in this test example at access matters.)\n\nThe finished widget\n\nIt\u2019s an intricate beast allright! But after all that we do indeed get the widget we want:\n\n\n\tDemo page\n\tStyle sheet\n\n\nIt\u2019s not perfect, most notably because the legends have to have a fixed width; this can be in em to allow for text scaling, but it still doesn\u2019t allow the content to break into multiple lines. It also doesn\u2019t look quite right in Safari; and some CSS hacking was needed to make it look right in IE6 and IE7.\n\nStill it worked well enough for the purpose, and satisfied the client completely. And most of all it re-assured me in my faith \u2013 that there\u2019s never any need to abuse tables for layout. (Unless of course you think this content is a table anyway, but that\u2019s another story!)", "year": "2006", "author": "James Edwards", "author_slug": "jamesedwards", "published": "2006-12-11T00:00:00+00:00", "url": "https://24ways.org/2006/showing-good-form/", "topic": "ux"} {"rowid": 269, "title": "Adaptive Images for Responsive Designs\u2026 Again", "contents": "When I was asked to write an article for 24 ways I jumped at the chance, as I\u2019d been wanting to write about some fun hacks for responsive images and related parsing behaviours. My heart sank a little when Matt Wilcox beat me to the subject, but it floated back up when I realized I disagreed with his method and still had something to write about.\n\nSo, Matt Wilcox, if that is your real name (and I\u2019m pretty sure it is), I disagree. I see your dirty server-based hack and raise you an even dirtier client-side hack. Evil laugh, etc., etc.\n\nYou guys can stomach yet another article about responsive design, right? Right?\n\nHalf the room gets up to leave\n\nWhoa, whoa\u2026 OK, I\u2019ll cut to the chase\u2026\n\nTL;DR\n\nIn a previous episode, we were introduced to Debbie and her responsive cat poetry page. Well, now she\u2019s added some reviews of cat videos and some images of cats. Check out her new page and have a play around with the browser window. At smaller widths, the images change and the design responds. The benefits of this method are:\n\n\n\tit\u2019s entirely client-side\n\timages are still shown to users without JavaScript\n\tyour media queries stay in your CSS file\n\tno repetition of image URLs\n\tno extra downloads per image\n\tit\u2019s fast enough to work on resize\n\tit\u2019s pure filth\n\n\nWhat\u2019s wrong with the server-side solution?\n\nResponsive design is a client-side issue; involving the server creates a boatload of problems.\n\n\n\tIt sets a cookie at the top of the page which is read in subsequent requests. However, the cookie is not guaranteed to be set in time for requests on the same page, so the server may see an old value or no value at all.\n\tServing images via server scripts is much slower than plain old static hosting.\n\tThe URL can only cache with vary: cookie, so the cache breaks when the cookie changes, even if the change is unrelated. Also, far-future caching is out for devices that can change width.\n\tIt depends on detecting screen width, which is rather messy on mobile devices.\n\tResponding to things other than screen width (such as DPI) means packing more information into the cookie, and a more complicated script at the top of each page.\n\n\nSo, why isn\u2019t this straightforward on the client?\n\nClient-side solutions to the problem involve JavaScript testing user agent properties (such as screen width), looping through some images and setting their URLs accordingly. However, by the time JavaScript has sprung into action, the original image source has already started downloading. If you change the source of an image via JavaScript, you\u2019re setting off yet another request.\n\nImages are downloaded as soon as their DOM node is created. They don\u2019t need to be visible, they don\u2019t need to be in the document.\n\nnew Image().src = url\n\nThe above will start an HTTP request for url. This is a handy trick for quick requests and preloading, but also shows the browser\u2019s eagerness to download images.\n\nHere\u2019s an example of that in action. Check out the network tab in Web Inspector (other non-WebKit development aids are available) to see the image requests.\n\nBecause of this, some client-side solutions look like this:\n\n\n\nwhere t.gif is a 1\u00d71px tiny transparent GIF.\n\nThis results in no images if JavaScript isn\u2019t available. Dealing with the absence of JavaScript is still important, even on mobile. I was recently asked to make a website work on an old Blackberry 9000. I was able to get most of the way there by preventing that OS parsing any JavaScript, and that was only possible because the site didn\u2019t depend on it.\n\nWe need to delay loading images for JavaScript users, but ensure they load for users without JavaScript. How can we conditionally parse markup depending on JavaScript support?\n\nOh yeah!