24ways

Custom SQL query returning 101 rows (hide)

rowidtitlecontentsyearauthorauthor_slugpublishedurltopic
290 Creating a Weekly Research Cadence Working on a product team, it’s easy to get hyper-focused on building features and lose sight of your users and their daily challenges. User research can be time-consuming to set up, so it often becomes ad-hoc and irregular, only performed in response to a particular question or concern. But without frequent touch points and opportunities for discovery, your product will stagnate and become less and less relevant. Setting up an efficient cadence of weekly research conversations will re-focus your team on user problems and provide a steady stream of insights for product development. As my team transitioned into a Lean process earlier this year, we needed a way to get more feedback from users in a short amount of time. Our users are internet marketers—always busy and often difficult to reach. Scheduling research took days of emailing back and forth to find mutually agreeable times, and juggling one-off conversations made it difficult to connect with more than one or two people per week. The slow pace of research was allowing additional risk to creep into our product development. I wanted to find a way for our team to test ideas and validate assumptions sooner and more often—but without increasing the administrative burden of scheduling. The solution: creating a regular cadence of research and testing that required a minimum of effort to coordinate. Setting up a weekly user research cadence accelerated our learning and built momentum behind strategic experiments. By dedicating time every week to talk to a few users, we made ongoing research a painless part of every weekly sprint. But increasing the frequency of our research had other benefits as well. With only five working days between sessions, a weekly cadence forced us to keep our work small and iterative. Committing to testing something every week meant showing work earlier and more often than we might have preferred—pushing us out of your comfort zone into a process of more rapid experimentation. Best of all, frequent conversations with users helped us become more customer-focused. After just a few weeks in a consistent research cadence, I noticed user feedback weaving itself through our planning and strategy sessions. Comments like “Remember what Jenna said last week, about not being able to customize her lists?” would pop up as frequent reference points to guide our decisions. As discussions become less about subjective opinions and more about responding to user needs, we saw immediate improvement in the quality of our solutions. Establishing an efficient recruitment process The key to creating a regular cadence of ongoing user research is an efficient recruitment and scheduling process—along with a commitment to prioritize the time needed for research conversations. This is an invaluable tool for product teams (whether or not they follow a Lean process), but could easily be adapted for content strategy teams, agency teams, a UX team of one, or any other project that would benefit from short, frequent conversations with users. The process I use requires a few hours of setup time at the beginning, but pays off in better learning and better releases over the long run. Almost any team could use this as a starting point and adapt it to their own needs. Pick a dedicated time each week for research In order to make research a priority, we started by choosing a time each week when everyone on the product team was available. Between stand-ups, grooming sessions, and roadmap reviews, it wasn’t easy to do! Nevertheless, it’s important to include as many people as possible in conversations with your users. Getting a second-hand summary of research results doesn’t have the same impact as hearing someone describe their frustrations and concerns first-hand. The more people in the room to hear those concerns, the more likely they are to become priorities for your team. I blocked off 2 hours for research conversations every Thursday afternoon. We make this time sacred, and never schedule other meetings or work across those hours. Divide your time into several research slots After my weekly cadence was set, I divided the time into four 20-minute time slots. Twenty minutes is long enough for us to ask several open-ended questions or get feedback on a prototype, without being a burden on our users’ busy schedules. Depending on your work, you may need schedule longer sessions—but beware the urge to create blocks that last an hour or more. A weekly research cadence is designed to facilitate rapid, ongoing feedback and testing; it should force you to talk to users often and to keep your work small and iterative. Projects that require longer, more in-depth testing will probably need a dedicated research project of their own. I used the scheduling software Calendly to create interview appointments on a calendar that I can share with users, and customized the confirmation and reminder emails with information about how to access our video conferencing software. (Most of our research is done remotely, but this could be set up with details for in-person meetings as well.) Automating these emails and reminders took a little bit of time to set up, but was worth it for how much faster it made the process overall. Invite users to sign up for a time that’s convenient for them With a calendar set up and follow-up emails automated, it becomes incredibly easy to schedule research conversations. Each week, I send a short email out to a small group of users inviting them to participate, explaining that this is a chance to provide feedback that will improve our product or occasionally promoting the opportunity to get a sneak peek at new features we’re working on. The email includes a link to the Calendly appointments, allowing users who are interested to opt in to a time that fits their schedule. Setting up appointments the first go around involved a bit of educated guessing. How many invitations would it take to fill all four of my weekly slots? How far in advance did I need to recruit users? But after a few weeks of trial and error, I found that sending 12-16 invitations usually allows me to fill all four interview slots. Our users often have meetings pop up at short notice, so we get the best results when I send the recruiting email on Tuesday, two days before my research block. It may take a bit of experimentation to fine tune your process, but it’s worth the effort to get it right. (The worst thing that’s happened since I began recruiting this way was receiving emails from users complaining that there were no open slots available!) I can now fill most of an afternoon with back-to-back user research sessions just by sending just one or two emails each week, increasing our research pace while leaving plenty time to focus on discovery and design. Getting the most out of your research sessions As you get comfortable with the rhythm of talking to users each week, you’ll find more and more ways to get value out of your conversations. At first, you may prefer to just show work in progress—such as mockups or a simple prototype—and ask open-ended questions to measure user reaction. When you begin new projects, you may want to use this time to research behavior on existing features—either watching participants as they use part of your product or asking them to give an account of a recent experience in your app. You may even want to run more abstracted Lean experiments, if that’s the best way to validate the assumptions your team is working from. Whatever you do, plan some time a day or two later to come back together and review what you’ve learned each week. Synthesizing research outcomes as a group will help keep your team in alignment and allow each person to highlight what they took away from each conversation. Over time, you may find that the pace of weekly user research becomes more exhausting than energizing, especially if the responsibility for scheduling and planning falls on just one person. Don’t allow yourself to get burned out; a healthy research cadence should also include time to rest and reflect if the pace becomes too rapid to sustain. Take breaks as needed, then pick up the pace again as soon as you’re ready. 2016 Wren Lanier wrenlanier 2016-12-02T00:00:00+00:00 https://24ways.org/2016/creating-a-weekly-research-cadence/ ux
111 Geometric Background Patterns When the design is finished and you’re about to start the coding process, you have to prepare your graphics. If you’re working with a pattern background you need to export only the repeating fragment. It can be a bit tricky to isolate a fragment to achieve a seamless pattern background. For geometric patterns there is a method I always follow and that I want to share with you. Take for example a perfect 45° diagonal line pattern. How do you define this pattern fragment so it will be rendered seamlessly? Here is the method I usually follow to avoid a mismatch. First, zoom in so you see enough detail and you can distinguish the pixels. Select the Rectangular Marquee Selection tool and start your selection at the intersection of 2 different colors of a diagonal line. Hold down the Shift key while dragging so you drag a perfect square. Release the mouse when you reach the exact same intesection (as your starting) point at the top right. Copy this fragment (using Copy Merged: Cmd/Ctrl + Shift + C) and paste the fragment in a new layer. Give this layer the name ‘pattern’. Now hold down the Command Key (Control Key on Windows) and click on the ‘pattern’ layer in the Layers Palette to select the fragment. Now go to Edit > Define Pattern, enter a name for your pattern and click OK. Test your pattern in a new document. Create a new document of 600 px by 400px, hit Cmd/Ctrl + A and go to Edit > Fill… and choose your pattern. If the result is OK, you have created a perfect pattern fragment. Below you see this pattern enlarged. The guides show the boundaries of the pattern fragment and the red pixels are the reference points. The red pixels at the top right, bottom right and bottom left should match the red pixel at the top left. This technique should work for every geometric pattern. Some patterns are easier than others, but this, and the Photoshop pattern fill test, has always been my guideline. Other geometric pattern examples Example 1 Not all geometric pattern fragments are squares. Some patterns look easy at first sight, because they look very repetitive, but they can be a bit tricky. Zoomed in pattern fragment with point of reference shown: Example 2 Some patterns have a clear repeating point that can guide you, such as the blue small circle of this pattern as you can see from this zoomed in screenshot: Zoomed in pattern fragment with point of reference shown: Example 3 The different diagonal colors makes a bit more tricky to extract the correct pattern fragment. The orange dot, which is the starting point of the selection is captured a few times inside the fragment selection: 2008 Veerle Pieters veerlepieters 2008-12-02T00:00:00+00:00 https://24ways.org/2008/geometric-background-patterns/ design
131 Random Lines Made With Mesh I know that Adobe Illustrator can be a bit daunting for people who aren’t really advanced users of the program, but you would be amazed by how easy you can create cool effects or backgrounds. In this short tutorial I show you how to create a cool looking background only in 5 steps. Step 1 – Create Lines Create lines using random widths and harmonious suitable colors. If you get stuck on finding the right colors, check out Adobe’s Kuler and start experimenting. Step 2 – Convert Strokes to Fills Select all lines and convert them to fills. Go to the Object menu, select Path > Outline Stroke. Select the Rectangle tool and draw 1 big rectangle on top the lines. Give the rectangle a suitable color. With the rectangle still selected, go to the Object menu, select Arrange > Send to Back. Step 3 – Convert to Mesh Select all objects by pressing the command key (for Mac users), control key (for Windows users) + the “a” key. Go to the Object menu and select the Envelope Distort > Make with Mesh option. Enter 2 rows and 2 columns. Check the preview box to see what happens and click the OK button. Step 4 – Play Around with The Mesh Points Play around with the points of the mesh using the Direct Selection tool (the white arrow in the Toolbox). Click on the top right point of the mesh. Once you’re starting to drag hold down the shift key and move the point upwards. Now start dragging the bezier handles on the mesh to achieve the effect as shown in the above picture. Of course you can try out all kind of different effects here. The Final Result This is an example of how the final result can look. You can try out all kinds of different shapes dragging the handles of the mesh points. This is just one of the many results you can get. So next time you haven’t got inspiration for a background of a header, a banner or whatever, just experiment with a few basic shapes such as lines and try out the ‘Envelope Distort’ options in Illustrator or the ‘Make with Mesh’ option and experiment, you’ll be amazed by the unexpected creative results. 2006 Veerle Pieters veerlepieters 2006-12-08T00:00:00+00:00 https://24ways.org/2006/random-lines-made-with-mesh/ design
232 Optimize Your Web Design Workflow I’m not sure about you, but I still favour using Photoshop to create my designs for the web. I agree that this application, even with its never-ending feature set, is not the perfect environment to design websites in. The ideal application doesn’t exist yet, however, so until it does it’s maybe not such a bad idea to investigate ways to optimize our workflow. Why use Photoshop? It will probably not come as a surprise if I say that Photoshop and Illustrator are the applications that I know best and feel most comfortable and creative in. Some people prefer Fireworks for web design. Even though I understand people’s motivations, I still prefer Photoshop personally. On the occasions that I gave Fireworks a try, I ended up just using the application to export my images as slices, or to prepare a dummy for the client. For some reason, I’ve never been able to find my way in that app. There were always certain things missing that could only be done in either Photoshop or Illustrator, which bothered me. Why not start in the browser? These days, with CSS3 styling emerging, there are people who find it more efficient to design in the browser. I agree that at a certain point, once the basic design is all set and defined, you can jump right into the code and go from there. But the actual creative part, at least for me, needs to be done in an application such as Photoshop. As a designer I need to be able to create and experiment with shapes on the fly, draw things, move them around, change colours, gradients, effects, and so on. I can’t see me doing this with code. I’m sure if I switch to markup too quickly, I might end up with a rather boxy and less interesting design. Once I start playing with markup, I leave my typical ‘design zone’. My brain starts thinking differently – more rational and practical, if you know what I mean; I start to structure and analyse how to mark up my design in the most efficient semantic way. When I design, I tend to let that go for a bit. I think more freely and not so much about the limitations, as it might hinder my creativity. Now that you know my motivations to stick with Photoshop for the time being, let’s see how we can optimize this beast. Optimize your Photoshop workspace In Photoshop CS5 you have a few default workspace options to choose from which can be found at the top right in the Application Bar (Window > Application Bar). You can set up your panels and palettes the way you want, starting from the ‘Design’ workspace option, and save this workspace for future web work. Here is how I have set up things for when I work on a website design: I have the layers palette open, and I keep the other palettes collapsed. Sometimes, when space permits, I open them all. For designers who work both on print and web, I think it’s worthwhile to save a workspace for both, or for when you’re doing photo retouching. Set up a grid When you work a lot with Shape Layers like I do, it’s really helpful to enable the Grid (View > Show > Grid) in combination with Snap to Grid (View > Snap To > Grid). This way, your vector-based work will be pixel-sharp, as it will always snap to the grid, and so you don’t end up with blurry borders. To set up your preferred grid, go to Preferences > Guides, Grids and Slices. A good setting is to use ‘Gridline Every 10 pixels’ and ‘Subdivision 10’. You can switch it on and off at any time using the shortcut Cmd/Ctrl + ’. It might also help to turn on Smart Guides (View > Show > Smart Guides). Another important tip for making sure your Shape Layer boxes and other shapes are perfectly aligned to the pixel grid when you draw them is to enable Snap to Pixels. This option can be enabled in the Application bar in the Geometry options dropdown menu when you select one of the shape tools from the toolbox. Use Shape Layers To keep your design as flexible as possible, it’s a good thing to use Shape Layers wherever you can as they are scalable. I use them when I design for the iPhone. All my icons, buttons, backgrounds, illustrative graphics – they are all either Smart Objects placed from Illustrator, or Shape Layers. This way, the design is scalable for the retina display. Use Smart Objects Among the things I like a lot in Photoshop are Smart Objects. Smart Objects preserve an image’s source content with all its original characteristics, enabling you to perform non-destructive editing to the layer. For me, this is the ideal way of making my design flexible. For example, a lot of elements are created in Illustrator and are purely vector-based. Placing these elements in Photoshop as Smart Objects (via copy and paste, or dragging from Illustrator into Photoshop) will keep them vector-based and scalable at all times without loss of quality. Another way you could use Smart Objects is whenever you have repeating elements; for example, if you have a stream or list of repeating items. You could, for instance, create one, two or three different items (for the sake of randomness), make each one a Smart Object, and repeat them to create the list. Then, when you have to update, you need only change the Smart Object, and the update will be automatically applied in all its linked instances. Turning photos into Smart Objects before you resize them is also worth considering – you never know when you’ll need that same photo just a bit bigger. It keeps things more flexible, as you leave room to resize the image at a later stage. I use this in combination with the Smart Filters a lot, as it gives me such great flexibility. I usually use Smart Objects as well for the main sections of a web page, which are repeated across different pages of a site. So, for elements such as the header, footer and sidebar, it can be handy for bigger projects that are constantly evolving, where you have to create a lot of different pages in Photoshop. You could save a template page that has the main sections set up as Smart Objects, always in their latest version. Each time you need to create new page, you can start from that template file. If you need to update an existing page because the footer (or sidebar, or header) has been updated, you can drag the updated Smart Object into this page. Although, do I wish Photoshop made it possible to have Smart Objects live as separate files, which are then linked to my different pages. Then, whenever I update the Smart Object, the pages are automatically updated next time I open the file. This is how linked files work in InDesign and Illustrator when you place a external image. Use Layer Comps In some situations, using Layer Comps can come in handy. I try to use them when the design consists of different states; for example, if there are hidden and show states of certain content, such as when content is shown after clicking a certain button. It can be useful to create a Layer Comp for each state. So, when you switch between the two Layer Comps, you’re switching between the two states. It’s OK to move or hide content in each of these states, as well as apply different layer styles. I find this particularly useful when I need to save separate JPEG versions of each state to show to the client, instead of going over all the eye icons in the layers palette to turn the layers’ visibility on or off. Create a set of custom colour swatches I tend to use a distinct colour Swatches palette for each project I work on, by saving a separate Swatches palette in project’s folder (as an .ase file). You can do this through the palette’s dropdown menu, choosing Save Swatches for Exchange. Selecting this option gives you the flexibility to load this palette in other Adobe applications like Illustrator, InDesign or Fireworks. This way, you have the colours of any particular project at hand. I name each colour, using the hexadecimal values. Loading, saving or changing the view of the Swatches palette can be done via the palette’s dropdown menu. My preferred view is ‘Small List’ so I can see the hexadecimal values or other info I have added in the description. I do wish Photoshop had the option of loading several different Styles palettes, so I could have two or more of them open at the same time, but each as a separate palette. This would be handy whenever I switch to another project, as I’m usually working on more than one project in a day. At the moment, you can only add a set of colours to the palette that is already open, which is frustrating and inefficient if you need to update the palette of a project separately. Create a set of custom Styles Just like saving a Swatches palette, I also always save the styles I apply in the Styles palette as a separate Styles file in the project’s folder when I work on a website design or design for iPhone/iPad. During the design process, I can save it each time styles are added. Again, though, it would be great if we could have different Styles palettes open at the same time. Use a scratch file What I also find particularly timesaving, when working on a large project, is using some kind of scratch file. By that, I mean a file that has elements in place that you reuse a lot in the general design. Think of buttons, icons and so on, that you need in every page or screen design. This is great for both web design work and iPad/iPhone work. Use the slice tool This might not be something you think of at first, because you probably associate this way of working with ‘old-school’ table-based techniques. Still, you can apply your slice any way you want, keeping your way of working in mind. Just think about it for a second. If you use the slice tool, and you give each slice its proper filename, you don’t have to worry about it when you need to do updates on the slice or image. Photoshop will remember what the image of that slice is called and which ‘Save for Web’ export settings you’ve used for it. You can also export multiple slices all at once, or export only the ones you need using ‘Save selected slices’. I hope this list of optimization tips was useful, and that they will help you improve and enjoy your time in Photoshop. That is, until the ultimate web design application makes its appearance. Somebody is building this as we speak, right? 2010 Veerle Pieters veerlepieters 2010-12-10T00:00:00+00:00 https://24ways.org/2010/optimize-your-web-design-workflow/ process
61 Animation in Responsive Design Animation and responsive design can sometimes feel like they’re at odds with each other. Animation often needs space to do its thing, but RWD tells us that the amount of space we’ll have available is going to change a lot. Balancing that can lead to some tricky animation situations. Embracing the squishiness of responsive design doesn’t have to mean giving up on your creative animation ideas. There are three general techniques that can help you balance your web animation creativity with your responsive design needs. One or all of these approaches might help you sneak in something just a little extra into your next project. Focused art direction Smaller viewports mean a smaller stage for your motion to play out on, and this tends to amplify any motion in your animation. Suddenly 100 pixels is really far and multiple moving parts can start looking like they’re battling for space. An effect that looked great on big viewports can become muddled and confusing when it’s reframed in a smaller space. Making animated movements smaller will do the trick for simple motion like a basic move across the screen. But for more complex animation on smaller viewports, you’ll need to simplify and reduce the number of moving parts. The key to this is determining what the vital parts of the animation are, to zone in on the parts that are most important to its message. Then remove the less necessary bits to distill the motion’s message down to the essentials. For example, Rally Interactive’s navigation folds down into place with two triangle shapes unfolding each corner on larger viewports. If this exact motion was just scaled down for narrower spaces the two corners would overlap as they unfolded. It would look unnatural and wouldn’t make much sense. Open video The main purpose of this animation is to show an unfolding action. To simplify the animation, Rally unfolds only one side for narrower viewports, with a slightly different animation. The action is still easily interpreted as unfolding and it’s done in a way that is a better fit for the available space. The message the motion was meant to convey has been preserved while the amount of motion was simplified. Open video Si Digital does something similar. The main concept of the design is to portray the studio as a creative lab. On large viewports, this is accomplished primarily through an animated illustration that runs the full length of the site and triggers its animations based on your scroll position. The illustration is there to support the laboratory concept visually, but it doesn’t contain critical content. Open video At first, it looks like Si Digital just turned off the animation of the illustration for smaller viewports. But they’ve actually been a little cleverer than that. They’ve also reduced the complexity of the illustration itself. Both the amount of motion (reduced down to no motion) and the illustration were simplified to create a result that is much easier to glean the concept from. Open video The most interesting thing about these two examples is that they’re solved more with thoughtful art direction than complex code. Keeping the main concept of the animations at the forefront allowed each to adapt creative design solutions to viewports of varying size without losing the integrity of their design. Responsive choreography Static content gets moved around all the time in responsive design. A three-column layout might line up from left to right on wide viewports, then stack top to bottom on narrower viewports. The same approach can be used to arrange animated content for narrower views, but the animation’s choreography also needs to be adjusted for the new layout. Even with static content, just scaling it down or zooming out to fit it into the available space is rarely an ideal solution. Rearranging your animations’ choreography to change which animation starts when, or even which animations play at all, keeps your animated content readable on smaller viewports. In a recent project I had three small animations that played one after the other, left to right, on wider viewports but needed to be stacked on narrower viewports to be large enough to see. On wide viewports, all three animations could play one right after the other in sequence because all three were in the viewable area at the same time. But once these were stacked for the narrower viewport layouts, that sequence had to change. Open video What was essentially one animation on wider viewports became three separate animations when stacked on narrower viewports. The layout change meant the choreography had to change as well. Each animation starts independently when it comes into view in the stacked layout instead of playing automatically in sequence. (I’ve put the animated parts in this demo if you want to peek under the hood.) Open video I choose to use the GreenSock library, with the choreography defined in two different timelines for this particular project. But the same goals could be accomplished with other JavaScript options or even CSS keyframe animations and media queries. Even more complex responsive choreography can be pulled off with SVG. Media queries can be used to change CSS animations applied to SVG elements at specific breakpoints for starters. For even more responsive power, SVG’s viewBox property, and the positioning of the objects within it, can be adjusted at JavaScript-defined breakpoints. This lets you set rules to crop the viewable area and arrange your animating elements to fit any space. Sarah Drasner has some great examples of how to use this technique with style in this responsive infographic and this responsive interactive illustration. On the other hand, if smart scalability is what you’re after, it’s also possible to make all of an SVG’s shapes and motion scale with the SVG canvas itself. Sarah covers both these clever responsive SVG techniques in detail. Creative and complex animation can easily become responsive thanks to the power of SVG! Open video Bake performance into your design decisions It’s hard to get very far into a responsive design discussion before performance comes up. Performance goes hand in hand with responsive design and your animation decisions can have a big impact on the overall performance of your site. The translate3D “hack”, backface-visibility:hidden, and the will-change property are the heavy hitters of animation performance. But decisions made earlier in your animation design process can have a big impact on rendering performance and your performance budget too. Pick a technology that matches your needs One of the biggest advantages of the current web animation landscape is the range of tools we have available to us. We can use CSS animations and transitions to add just a dash of interface animation to our work, go all out with webGL to create a 3D experience, or anywhere in between. All within our browsers! Having this huge range of options is amazing and wonderful but it also means you need to be cognizant of what you’re using to get the job done. Loading in the full weight of a robust JavaScript animation library is going to be overkill if you’re only animating a few small elements here and there. That extra overhead will have an impact on performance. Performance budgets will not be pleased. Always match the complexity of the technology you choose to the complexity of your animation needs to avoid unnecessary performance strain. For small amounts of animation, stick to CSS solutions since it’s the most lightweight option. As your animations grow in complexity, or start to require more robust logic, move to a JavaScript solution that can accomplish what you need. Animate the most performant properties Whether you’re animating in CSS or JavaScript, you’re affecting specific properties of the animated element. Browsers can animate some properties more efficiently than others based on how many steps need to happen behind the scenes to visually update those properties. Browsers are particularly efficient at animating opacity, scale, rotation, and position (when the latter three are done with transforms). This article from Paul Irish and Paul Lewis gives the full scoop on why. Conveniently, those are also the most common properties used in motion design. There aren’t many animated effects that can’t be pulled off with this list. Stick to these properties to set your animations up for the best performance results from the start. If you find yourself needing to animate a property outside of this list, check CSS Triggers… to find out how much of an additional impact it might have. Offset animation start times Offsets (the concept of having a series of similar movements execute one slightly after the other, creating a wave-like pattern) are a long-held motion graphics trick for creating more interesting and organic looking motion. Employing this trick of the trade can also be smart for performance. Animating a large number of objects all at the same time can put a strain on the browser’s rendering abilities even in the best cases. Adding short delays to offset these animations in time, so they don’t all start at once, can improve rendering performance. Go explore the responsive animation possibilities for yourself! With smart art direction, responsive choreography, and an eye on performance you can create just about any creative web animation you can think up while still being responsive. Keep these in mind for your next project and you’ll pull off your animations with style at any viewport size! 2015 Val Head valhead 2015-12-09T00:00:00+00:00 https://24ways.org/2015/animation-in-responsive-design/ design
76 Giving CSS Animations and Transitions Their Place CSS animations and transitions may not sit squarely in the realm of the behaviour layer, but they’re stepping up into this area that used to be pure JavaScript territory. Heck, CSS might even perform better than its JavaScript equivalents in some cases. That’s pretty serious! With CSS’s new tricks blurring the lines between presentation and behaviour, it can start to feel bloated and messy in our CSS files. It’s an uncomfortable feeling. Here are a pair of methods I’ve found to be pretty helpful in keeping the potential bloat and wire-crossing under control when CSS has its hands in both presentation and behaviour. Same eggs, more baskets Structuring your CSS to have separate files for layout, typography, grids, and so on is a fairly common approach these days. But which one do you put your transitions and animations in? The initial answer, as always, is “it depends”. Small effects here and there will likely sit just fine with your other styles. When you move into more involved effects that require multiple animations and some logic support from JavaScript, it’s probably time to choose none of the above, and create a separate CSS file just for them. Putting all your animations in one file is a huge help for code organization. Even if you opt for a name less literal than animations.css, you’ll know exactly where to go for anything CSS animation related. That saves time and effort when it comes to editing and maintenance. Keeping track of which animations are still currently used is easier when they’re all grouped together as well. And as an added bonus, you won’t have to look at all those horribly unattractive and repetitive prefixed @-keyframe rules unless you actually need to. An animations.css file might look something like the snippet below. It defines each animation’s keyframes and defines a class for each variation of that animation you’ll be using. Depending on the situation, you may also want to include transitions here in a similar way. (I’ve found defining transitions as their own class, or mixin, to be a huge help in past projects for me.) // defining the animation @keyframes catFall { from { background-position: center 0;} to {background-position: center 1000px;} } @-webkit-keyframes catFall { from { background-position: center 0;} to {background-position: center 1000px;} } @-moz-keyframes catFall { from { background-position: center 0;} to {background-position: center 1000px;} } @-ms-keyframes catFall { from { background-position: center 0;} to {background-position: center 1000px;} } … // class that assigns the animation .catsBackground { height: 100%; background: transparent url(../endlessKittens.png) 0 0 repeat-y; animation: catFall 1s linear infinite; -webkit-animation: catFall 1s linear infinite; -moz-animation: catFall 1s linear infinite; -ms-animation: catFall 1s linear infinite; } If we don’t need it, why load it? Having all those CSS animations and transitions in one file gives us the added flexibility to load them only when we want to. Loading a whole lot of things that will never be used might seem like a bit of a waste. While CSS has us impressed with its motion chops, it falls flat when it comes to the logic and fine-grained control. JavaScript, on the other hand, is pretty good at both those things. Chances are the content of your animations.css file isn’t acting alone. You’ll likely be adding and removing classes via JavaScript to manage your CSS animations at the very least. If your CSS animations are so entwined with JavaScript, why not let them hang out with the rest of the behaviour layer and only come out to play when JavaScript is supported? Dynamically linking your animations.css file like this means it will be completely ignored if JavaScript is off or not supported. No JavaScript? No additional behaviour, not even the parts handled by CSS. <script> document.write('<link rel="stylesheet" type="text/css" href="animations.css">'); </script> This technique comes up in progressive enhancement techniques as well, but it can help here to keep your presentation and behaviour nicely separated when more than one language is involved. The aim in both cases is to avoid loading files we won’t be using. If you happen to be doing something a bit fancier – like 3-D transforms or critical animations that require more nuanced fallbacks – you might need something like modernizr to step in to determine support more specifically. But the general idea is the same. Summing it all up Using a couple of simple techniques like these, we get to pick where to best draw the line between behaviour and presentation based on the situation at hand, not just on what language we’re using. The power of when to separate and how to reassemble the individual pieces can be even greater if you use preprocessors as part of your process. We’ve got a lot of options! The important part is to make forward-thinking choices to save your future self, and even your current self, unnecessary headaches. 2012 Val Head valhead 2012-12-08T00:00:00+00:00 https://24ways.org/2012/giving-css-animations-and-transitions-their-place/ code
210 Stop Leaving Animation to the Last Minute Our design process relies heavily on static mockups as deliverables and this makes it harder than it needs to be to incorporate UI animation in our designs. Talking through animation ideas and dancing out the details of those ideas can be fun; but it’s not always enough to really evaluate or invest in animated design solutions. By including deliverables that encourage discussing animation throughout your design process, you can set yourself (and your team) up for creating meaningful UI animations that feel just as much a part of the design as your colour palette and typeface. You can get out of that “running out of time to add in the animation” trap by deliberately including animation in the early phases of your design process. This will give you both the space to treat animation as a design tool, and the room to iterate on UI animation ideas to come up with higher quality solutions. Two deliverables that can be especially useful for this are motion comps and animated interactive prototypes. Motion comps - an animation deliverable Motion comps (also called animatics or motion mock-ups) are usually video representation of UI animations. They are used to explore the details of how a particular animation might play out. And they’re most often made with timeline-based tools like Adobe After Effects, Adobe Animate, or Tumult Hype. The most useful things about motion comps is how they allow designers and developers to share the work of creating animations. (Instead of pushing all the responsibility of animation on one group or the other.) For example, imagine you’re working on a design that has a content panel that can either be open or closed. You might create a mockup like the one below including the two different views: the closed state and the open state. If you’re working with only static deliverables, these two artboards might be exactly what you handoff to developers along with the instruction to animate between the two. On the surface that seems pretty straight forward, but even with this relatively simple transition there’s a lot that those two artboards don’t address. There are seven things that change between the closed state and the open state. That’s seven things the developer building this out has to figure out how to move in and out of view, when, and in what order. And all of that is even before starting to write the code to make it work. By providing only static comps, all the logic of the animation falls on the developer. This might go ok if she has the bandwidth and animation knowledge, but that’s making an awful lot of assumptions. Instead, if you included a motion mock up like this with your static mock ups, you could share the work of figuring out the logic of the animation between design and development. Designers could work out the logic of the animation in the motion comp, exploring which items move at which times and in which order to create the opening and closing transitions. The motion comp can also be used to iterate on different possible animation approaches before any production code has to be committed too. Sharing the work and giving yourself time to explore animation ideas before you’re backed up again the deadline will lead to happier teammates and better design solutions. When to use motion comps I’m not a fan of making more deliverables just for the sake of having more things to make, so I find it helps to narrow down what question I’m trying answer before choosing which sort of deliverable to make to investigate. Motion comps can be most helpful for answering questions like: Exactly how should this animation look? Which items should move? Where? And when? Do the animation qualities reflect our brand or our voice and tone? One of the added bonuses of creating motion comps to answer these questions is that you’ll have a concrete thing to bring to design critiques or reviews to get others’ input on them as well. Using motion comps as handoff Motion comps are often used to handoff animation ideas from design to development. They can be super useful for this, but they’re even more useful when you include the details of the motion specs with them. (It’s difficult, if not impossible, to glean these details from playing back a video.) More specifically, you’ll want to include: Durations and the properties animated for each animation Easing curve values or spring values used Delay values and repeat counts In many cases you’ll have to collect these details up manually. But this isn’t necessarily something that that will take a lot of time. If you take note of them as you’re creating the motion comp, chances are most of these details will already be top of mind. (Also, if you use After Effects for your motion comps, the Inspector Spacetime plugin might be helpful for this task.) Animated prototypes - an interactive deliverable Making prototypes isn’t a new idea for web work by any stretch, but creating prototypes that include animation – or even creating prototypes specifically to investigate potential animation solutions – can go a long way towards having higher quality animations in your final product. Interactive prototypes are web or app-based, or displayed in a particular tool’s preview window to create a useable version of interactions that might end up in the end product. They’re often made with prototyping apps like Principle, Framer, or coded up in HTML, CSS and JS directly like the example below. See the Pen Prototype example by Val Head (@valhead) on CodePen. The biggest different between motion comps and animated prototypes is the interactivity. Prototypes can reposed to taps, drags or gestures, while motion comps can only play back in a linear fashion. Generally speaking, this makes prototypes a bit more of an effort to create, but they can also help you solve different problems. The interactive nature of prototypes can also make them useful for user testing to further evaluate potential solutions. When to use prototypes When it comes to testing out animation ideas, animated prototypes can be especially helpful in answering questions like these: How will this interaction feel to use? (Interactive animations often have different timing needs than animations that are passively viewed.) What will the animation be like with real data or real content? Does this animation fit the context of the task at hand? Prototypes can be used to investigate the same questions that motion comps do if you’re comfortable working in code or your prototyping tool of choice has capabilities to address high fidelity animation details. There are so many different prototyping tools out there at the moment, you’re sure to be able to find one that fits your needs. As a quick side note: If you’re worried that your coding skills might not be up to par to prototype in code, know that prototype code doesn’t have to be production quality code. Animated prototypes’ main concern is working out the animation details. Once you’ve arrived at a combination of animations that works, the animation specifics can be extracted or the prototype can be refactored for production. Motion comp or prototype? Both motion comps and prototypes can be extremely useful in the design process and you can use whichever one (or ones) that best fits your team’s style. The key thing that both offer is a way to make animation ideas visible and sharable. When you and your teammate are both looking at the same deliverable, you can be confident you’re talking about the same thing and discuss its pros and cons more easily than just describing the idea verbally. Motion comps tend to be more useful earlier in the design process when you want to focus on the motion without worrying about the underlying structure or code yet. Motion comps also be great when you want to try something completely new. Some folks prefer motion comps because the tools for making them feel more familiar to them which means they can work faster. Prototypes are most useful for animations that rely heavily on interaction. (Getting the timing right for interactions can be tough without the interaction part sometimes.) Prototypes can also be helpful to investigate and optimize performance if that’s a specific concern. Give them a try Whichever deliverables you choose to highlight your animation decisions, including them in your design reviews, critiques, or other design discussions will help you make better UI animation choices. More discussion around UI animation ideas during the design phase means greater buy-in, more room for iteration, and higher quality UI animations in your designs. Why not give them a try for your next project? 2017 Val Head valhead 2017-12-08T00:00:00+00:00 https://24ways.org/2017/stop-leaving-animation-to-the-last-minute/ design
205 Why Design Systems Fail Design systems are so hot right now, and for good reason. They promote a modular approach to building a product, and ensure organizational unity and stability via reusable code snippets and utility styles. They make prototyping a breeze, and provide a common language for both designers and developers. A design system is a culmination of several individual components, which can include any or all of the following (and more): Style guide or visual pattern library Design tooling (e.g. Sketch Library) Component library (where the components live in code) Code usage guidelines and documentation Design usage documentation Voice and tone guideline Animation language guideline Design systems are standalone (internal or external) products, and have proven to be very effective means of design-driven development. However, in order for a design system to succeed, everyone needs to get on board. I’d like to go over a few considerations to ensure design system success and what could hinder that success. Organizational Support Put simply, any product, including internal products, needs support. Something as cross-functional as a design system, which spans every vertical project team, needs support from the top and bottom levels of your organization. What I mean by that is that there needs to be top-level support from project managers up through VP’s to see the value of a design system, to provide resources for its implementation, and advocate for its use company-wide. This is especially important in companies where such systems are being put in place on top of existing, crufty codebases, because it may mean there needs to be some time and effort put in the calendar for refactoring work. Support from the bottom-up means that designers and engineers of all levels also need to support this system and feel responsibility for it. A design system is an organization’s product, and everyone should feel confident contributing to it. If your design system supports external clients as well (such as contractors), they too can become valuable teammates. A design system needs support and love to be nurtured and to grow. It also needs investment. Investment To have a successful design system, you need to make a continuous effort to invest resources into it. I like to compare this to working out. You can work out intensely for 3 months and see some gains, but once you stop working out, those will slowly fade away. If you continue to work out, even if its less often than the initial investment, you’ll see yourself maintaining your fitness level at a much higher rate than if you stopped completely. If you invest once in a design system (say, 3 months of overhauling it) but neglect to keep it up, you’ll face the same situation. You’ll see immediate impact, but that impact will fade as it gets out of sync with new designs and you’ll end up with strange, floating bits of code that nobody is using. Your engineers will stop using it as the patterns become outdated, and then you’ll find yourself in for another round of large investment (while dreading going through the process since its fallen so far out of shape). With design systems, small incremental investments over time lead to big gains overall. With this point, I also want to note that because of how they scale, design systems can really make a large impact across the platform, making it extremely important to really invest in things like accessibility and solid architecture from the start. You don’t want to scale a brittle system that’s not easy to use. Take care of your design systems, and keep working on them to ensure their effectiveness. One way to ensure this is to have a dedicated team working on this design system, managing tickets and styling updates that trickle out to the rest of your company. Responsibility With some kind of team to act as an owner of a design system, whether it be the design team, engineering team, or a new team made of both designers and engineers (the best option), your company is more likely to keep a relevant, up-to-date system that doesn’t break. This team is responsible for a few things: Helping others get set up on the system (support) Designing and building components (development) Advocating for overall UI consistency and adherence (evangelism) Creating a rollout plan and update system (product management) As you can see, these are a lot of roles, so it helps to have multiple people on this team, at least part of the time, if you can. One thing I’ve found to be effective in the past is to hold office hours for coworkers to book slots within to help them get set up and to answer any questions about using the system. Having an open Slack channel also helps for this sort of thing, as well as for bringing up bugs/issues/ideas and being an channel for announcements like new releases. Communication Once you have resources and a plan to invest in a design system, its really important that this person or team acts as a bridge between design and engineering. Continuous communication is really important here, and the way you communicate is even more important. Remember that nobody wants to be told what to do or prescribed a solution, especially developers, who are used to a lot of autonomy (usually they get to choose their own tools at work). Despite how much control the other engineers have on the process, they need to feel like they have input, and feel heard. This can be challenging, especially since ultimately, some party needs to be making a final decision on direction and execution. Because it’s a hard balance to strike, having open communication channels and being as transparent as possible as early as possible is a good start. Buy-in For all of the reasons we’ve just looked over, good communication is really important for getting buy-in from your users (the engineers and designers), as well as from product management. Building and maintaining a design system is surprisingly a lot of people-ops work. To get buy-in where you don’t have a previous concensus that this is the right direction to take, you need to make people want to use your design system. A really good way to get someone to want to use a product is to make it the path of least resistance, to show its value. Gather examples and usage wins, because showing is much more powerful than telling. If you can, have developers use your product in a low-stakes situation where it provides clear benefits. Hackathons are a great place to debut your design system. Having a hackathon internally at DigitalOcean was a perfect opportunity to: Evangelize for the design system See what people were using the component library for and what they were struggling with (excellent user testing there) Get user feedback afterward on how to improve it in future iterations Let people experience the benefits of using it themselves These kinds of moments, where people explore on their own are where you can really get people on your side and using the design system, because they can get their hands on it and draw their own conclusions (and if they don’t love it — listen to them on how to improve it so that they do). We don’t always get so lucky as to have this sort of instantaneous user feedback from our direct users. Architecture I briefly mentioned the scalable nature of design systems. This is exactly why it’s important to develop a solid architecture early on in the process. Build your design system with growth and scalability in mind. What happens if your company acquires a new product? What happens when it develops a new market segment? How can you make sure there’s room for customization and growth? A few things we’ve found helpful include: Namespacing Use namespacing to ensure that the system doesn’t collide with existing styles if applying it to an existing codebase. This means prefixing every element in the system to indicate that this class is a part of the design system. To ensure that you don’t break parts of the existing build (which may have styled base elements), you can namespace the entire system inside of a parent class. Sass makes this easy with its nested structure. This kind of namespacing wouldn’t be necessary per se on new projects, but it is definitely useful when integrating new and old styles. Semantic Versioning I’ve used Semantic Versioning on all of the design systems I’ve ever worked on. Semantic versioning uses a system of Major.Minor.Patch for any updates. You can then tag released on Github with versioned updates and ensure that someone’s app won’t break unintentionally when there is an update, if they are anchored to a specific version (which they should be). We also use this semantic versioning as a link with our design system assets at DigitalOcean (i.e. Sketch library) to keep them in sync, with the same version number corresponding to both Sketch and code. Our design system is served as a node module, but is also provided as a series of built assets using our CDN for quick prototyping and one-off projects. For these built assets, we run a deploy script that automatically creates folders for each release, as well as a latest folder if someone wanted the always-up-to-date version of the design system. So, semantic versioning for the system I’m currently building is what links our design system node module assets, sketch library assets, and statically built file assets. The reason we have so many ways of consuming our design system is to make adoption easier and to reduce friction. Friction A while ago, I posed the question of why design systems become outdated and unused, and a major conclusion I drew from the conversation was: “If it’s harder for people to use than their current system, people just won’t use it” You have to make your design system the path of least resistance, lowering cognitive overhead of development, not adding to it. This is vital. A design system is intended to make development much more efficient, enforce a consistent style across sites, and allow for the developer to not worry as much about small decisions like naming and HTML semantics. These are already sorted out for them, meaning they can focus on building product. But if your design system is complicated and over-engineered, they may find it frustrating to use and go back to what they know, even if its not the best solution. If you’re a Sass expert, and base your system on complex mixins and functions, you better hope your user (the developer) is also a Sass expert, or wants to learn. This is often not the case, however. You need to talk to your audience. With the DigitalOcean design system, we provide a few options: Option 1 Users can implement the component library into a development environment and use Sass, select just the components they want to include, and extend the system using a hook-based system. This is the most performant and extensible output. Only the components that are called upon are included, and they can be easily extended using mixins. But as noted earlier, not everyone wants to work this way (including Sass a dependency and potentially needing to set up a build system for it and learn a new syntax). There is also the user who just wants to throw a link onto their page and have it look nice, and thats where our versioned built assets come in. Option 2 With Option 2, users pull in links that are served via a CDN that contain JS, CSS, and our SVG icon library. The code is a bit bigger than the completely customized version, but often this isn’t the aim when people are using Option 2. Reducing friction for adoption should be a major goal of your design system rollout. Conclusion Having a design system is really beneficial to any product, especially as it grows. In order to have an effective system, it’s important to primarily always keep your user in mind and garner support from your entire company. Once you have support and acceptance, this system will flourish and grow. Make sure someone is responsible for it, and make sure its built with a solid foundation from the start which will be carefully maintained toward the future. Good luck, and happy holidays! 2017 Una Kravets unakravets 2017-12-14T00:00:00+00:00 https://24ways.org/2017/why-design-systems-fail/ process
175 Front-End Code Reusability with CSS and JavaScript Most web standards-based developers are more than familiar with creating their sites with semantic HTML with lots and lots of CSS. With each new page in a design, the CSS tends to grow and grow and more elements and styles are added. But CSS can be used to better effect. The idea of object-oriented CSS isn’t new. Nicole Sullivan has written a presentation on the subject and outlines two main concepts: separate structure and visual design; and separate container and content. Jeff Croft talks about Applying OOP Concepts to CSS: I can make a class of .box that defines some basic layout structure, and another class of .rounded that provides rounded corners, and classes of .wide and .narrow that define some widths, and then easily create boxes of varying widths and styles by assigning multiple classes to an element, without having to duplicate code in my CSS. This concept helps reduce CSS file size, allows for great flexibility, rapid building of similar content areas and means greater consistency throughout the entire design. You can also take this concept one step further and apply it to site behaviour with JavaScript. Build a versatile slideshow I will show you how to build multiple slideshows using jQuery, allowing varying levels of functionality which you may find on one site design. The code will be flexible enough to allow you to add previous/next links, image pagination and the ability to change the animation type. More importantly, it will allow you to apply any combination of these features. Image galleries are simply a list of images, so the obvious choice of marking the content up is to use a <ul>. Many designs, however, do not cater to non-JavaScript versions of the website, and thus don’t take in to account large multiple images. You could also simply hide all the other images in the list, apart from the first image. This method can waste bandwidth because the other images might be downloaded when they are never going to be seen. Taking this second concept — only showing one image — the only code you need to start your slideshow is an <img> tag. The other images can be loaded dynamically via either a per-page JavaScript array or via AJAX. The slideshow concept is built upon the very versatile Cycle jQuery Plugin and is structured in to another reusable jQuery plugin. Below is the HTML and JavaScript snippet needed to run every different type of slideshow I have mentioned above. <img src="path/to/image.jpg" alt="About the image" title="" height="250" width="400" class="slideshow"> <script type="text/javascript"> jQuery().ready(function($) { $('img.slideshow').slideShow({ images: ['1.jpg', '2.jpg', '3.jpg'] }); }); </script> Slideshow plugin If you’re not familiar with jQuery or how to write and author your own plugin there are plenty of articles to help you out. jQuery has a chainable interface and this is something your plugin must implement. This is easy to achieve, so your plugin simply returns the collection it is using: return this.each( function () {} }; Local Variables To keep the JavaScript clean and avoid any conflicts, you must set up any variables which are local to the plugin and should be used on each collection item. Defining all your variables at the top under one statement makes adding more and finding which variables are used easier. For other tips, conventions and improvements check out JSLint, the “JavaScript Code Quality Tool”. var $$, $div, $images, $arrows, $pager, id, selector, path, o, options, height, width, list = [], li = 0, parts = [], pi = 0, arrows = ['Previous', 'Next']; Cache jQuery Objects It is good practice to cache any calls made to jQuery. This reduces wasted DOM calls, can improve the speed of your JavaScript code and makes code more reusable. The following code snippet caches the current selected DOM element as a jQuery object using the variable name $$. Secondly, the plugin makes its settings available to the Metadata plugin‡ which is best practice within jQuery plugins. For each slideshow the plugin generates a <div> with a class of slideshow and a unique id. This is used to wrap the slideshow images, pagination and controls. The base path which is used for all the images in the slideshow is calculated based on the existing image which appears on the page. For example, if the path to the image on the page was /img/flowers/1.jpg the plugin would use the path /img/flowers/ to load the other images. $$ = $(this); o = $.metadata ? $.extend({}, settings, $$.metadata()) : settings; id = 'slideshow-' + (i++ + 1); $div = $('<div />').addClass('slideshow').attr('id', id); selector = '#' + id + ' '; path = $$.attr('src').replace(/[0-9]\.jpg/g, ''); options = {}; height = $$.height(); width = $$.width(); Note: the plugin uses conventions such as folder structure and numeric filenames. These conventions help with the reusable aspect of plugins and best practices. Build the Images The cycle plugin uses a list of images to create the slideshow. Because we chose to start with one image we must now build the list programmatically. This is a case of looping through the images which were added via the plugin options, building the appropriate HTML and appending the resulting <ul> to the DOM. $.each(o.images, function () { list[li++] = '<li>'; list[li++] = '<img src="' + path + this + '" height="' + height + '" width="' + width + '">'; list[li++] = '</li>'; }); $images = $('<ul />').addClass('cycle-images'); $images.append(list.join('')).appendTo($div); Although jQuery provides the append method it is much faster to create one really long string and append it to the DOM at the end. Update the Options Here are some of the options we’re making available by simply adding classes to the <img>. You can change the slideshow effect from the default fade to the sliding effect. By adding the class of stopped the slideshow will not auto-play and must be controlled via pagination or previous and next links. // different effect if ($$.is('.slide')) { options.fx = 'scrollHorz'; } // don't move by default if ($$.is('.stopped')) { options.timeout = 0; } If you are using the same set of images throughout a website you may wish to start on a different image on each page or section. This can be easily achieved by simply adding the appropriate starting class to the <img>. // based on the class name on the image if ($$.is('[class*=start-]')) { options.startingSlide = parseInt($$.attr('class').replace(/.*start-([0-9]+).*/g, "$1"), 10) - 1; } For example: <img src="/img/slideshow/3.jpg" alt="About the image" title="" height="250" width="400" class="slideshow start-3"> By default, and without JavaScript, the third image in this slideshow is shown. When the JavaScript is applied to the page the slideshow must know to start from the correct place, this is why the start class is required. You could capture the default image name and parse it to get the position, but only the default image needs to be numeric to work with this plugin (and could easily be changed in future). Therefore, this extra specifically defined option means the plugin is more tolerant. Previous/Next Links A common feature of slideshows is previous and next links enabling the user to manually progress the images. The Cycle plugin supports this functionality, but you must generate the markup yourself. Most people add these directly in the HTML but normally only support their behaviour when JavaScript is enabled. This goes against progressive enhancement. To keep with the best practice progress enhancement method the previous/next links should be generated with JavaScript. The follow snippet checks whether the slideshow requires the previous/next links, via the arrows class. It restricts the Cycle plugin to the specific slideshow using the selector we created at the top of the plugin. This means multiple slideshows can run on one page without conflicting each other. The code creates a <ul> using the arrows array we defined at the top of the plugin. It also adds a class to the slideshow container, meaning you can style different combinations of options in your CSS. // create the arrows if ($$.is('.arrows') && list.length > 1) { options.next = selector + '.next'; options.prev = selector + '.previous'; $arrows = $('<ul />').addClass('cycle-arrows'); $.each(arrows, function (i, val) { parts[pi++] = '<li class="' + val.toLowerCase() + '">'; parts[pi++] = '<a href="#' + val.toLowerCase() + '">'; parts[pi++] = '<span>' + val + '</span>'; parts[pi++] = '</a>'; parts[pi++] = '</li>'; }); $arrows.append(parts.join('')).appendTo($div); $div.addClass('has-cycle-arrows'); } The arrow array could be placed inside the plugin settings to allow for localisation. Pagination The Cycle plugin creates its own HTML for the pagination of the slideshow. All our plugin needs to do is create the list and selector to use. This snippet creates the pagination container and appends it to our specific slideshow container. It sets the Cycle plugin pager option, restricting it to the specific slideshow using the selector we created at the top of the plugin. Like the previous/next links, a class is added to the slideshow container allowing you to style the slideshow itself differently. // create the clickable pagination if ($$.is('.pagination') && list.length > 1) { options.pager = selector + '.cycle-pagination'; $pager = $('<ul />').addClass('cycle-pagination'); $pager.appendTo($div); $div.addClass('has-cycle-pagination'); } Note: the Cycle plugin creates a <ul> with anchors listed directly inside without the surrounding <li>. Unfortunately this is invalid markup but the code still works. Demos Well, that describes all the ins-and-outs of the plugin, but demos make it easier to understand! Viewing the source on the demo page shows some of the combinations you can create with a simple <img>, a few classes and some thought-out JavaScript. View the demos → Decide on defaults The slideshow plugin uses the exact same settings as the Cycle plugin, but some are explicitly set within the slideshow plugin when using the classes you have set. When deciding on what functionality is going to be controlled via this class method, be careful to choose your defaults wisely. If all slideshows should auto-play, don’t make this an option — make the option to stop the auto-play. Similarly, if every slideshow should have previous/next functionality make this the default and expose the ability to remove them with a class such as “no-pagination”. In the examples presented on this article I have used a class on each <img>. You can easily change this to anything you want and simply apply the plugin based on the jQuery selector required. Grab your images If you are using AJAX to load in your images, you can speed up development by deciding on and keeping to a folder structure and naming convention. There are two methods: basing the image path based on the current URL; or based on the src of the image. The first allows a different slideshow on each page, but in many instances a site will have a couple of sets of images and therefore the second method is probably preferred. Metadata ‡ A method which allows you to directly modify settings in certain plugins, which also uses the classes from your HTML already exists. This is a jQuery plugin called Metadata. This method allows for finer control over the plugin settings themselves. Some people, however, may dislike the syntax and prefer using normal classes, like above which when sprinkled with a bit more JavaScript allows you to control what you need to control. The takeaway Hopefully you have understood not only what goes in to a basic jQuery plugin but also learnt a new and powerful idea which you can apply to other areas of your website. The idea can also be applied to other common interfaces such as lightboxes or mapping services such as Google Maps — for example creating markers based on a list of places, each with different pin icons based the anchor class. 2009 Trevor Morris trevormorris 2009-12-06T00:00:00+00:00 https://24ways.org/2009/front-end-code-reusability-with-css-and-javascript/ code
82 Being Prepared To Contribute “You’ll figure it out.” The advice my dad gives has always been the same, whether addressing my grade school homework or paying bills after college. If I was looking for a shortcut, my dad wasn’t going to be the one to provide it. When I was a kid it infuriated the hell out of me, but what I then perceived to be a lack of understanding turned out to be a keystone in my upbringing. As an adult, I realize the value in not receiving outright solutions, but being forced to figure things out. Even today, when presented with a roadblock while building for the web, I am temped to get by with the help of the latest grid system, framework, polyfill, or plugin. In and of themselves these resources are harmless, but before I can drop them in, those damn words still echo in the back of my mind: “You’ll figure it out.” I know that if I blindly implement these tools as drag and drop solutions I fail to understand the intricacies behind how and why they were built; repeatedly using them as shortcuts handicaps my skill set. When I solely rely on the tools of others, my work is at their mercy, leaving me less creative and resourceful, and, thus, less able to contribute to the advancement of our industry and community. One of my favorite things about this community is how generous and collaborative it can be. I’ve loved seeing FitVids used all over the web and regularly improved upon at Github. I bet we can all think of a time where implementing a shared resource has benefitted our own work and sanity. Because these resources are so valuable, it’s important that we continue to be a part of the conversation in order to further develop solutions and ideas. It’s easy to assume there’s someone smarter or more up-to-date in any one area, but with a degree of understanding and perspective, we can all participate. This open form of collaboration is in our web DNA. After all, its primary purpose was to promote the exchange and development of new ideas. Tim Berners-Lee proposed a global hypertext project, to be known as the World Wide Web. Based on the earlier “Enquire” work, it was designed to allow people to work together by combining their knowledge in a web of hypertext documents. I’m delighted to find that this spirit of collaborative ingenuity is alive and well on the web today. Take the story of Off Canvas as an example. I was at an ATX Dribbble meet up where I met Jason Weaver and chatted to him about his recent work on the responsive layout prototype, Off Canvas. Jason said he came across a post by Luke Wroblewski outlining the idea and saw this: If anyone is interested in building a complete example of this approach using responsive Web design techniques, let me know! From there Luke recounts: We went back and forth on email, with me laying out ideas and Jason doing all the hard work to see if they can be done and improving them bit by bit! Once we got to something we both liked, I wrote up an article explaining things and he hosted the examples. Luke took the time to clearly outline and diagram his ideas, and Jason responded with a solid proof of concept that has evolved into a tool we all have at our disposal. Victory! I have also benefitted from comrades who have taken an idea of mine into development. After blogging about some concerns in regards to maintaining hierarchy as media queries are used to shift layouts, Jordan Moore rebounded with some responsive demos where he used flexbox to (re)order content as viewport sizing changes. Similar stories can be found behind the development of things like FitVids, FitText, and Molten Leading. I love this pattern of collaboration because it involves a fairly specific process: Initial idea or prototype is outlined or built, then shared Discuss Someone develops or improves it, then shares it Discuss Someone else develops or improves it, then shares it. Infinity. This is what the web looks like when we build it together, and I’d argue that steps 2+ are absolutely crucial. A web where everyone develops their own ideas and tools independent of one another is like a room full of people talking and no one listening. The pattern itself mimics a literal web structure, and ideally we’d be able to follow a strand from one idea to the next and so on. Blessed are the curators Sometimes those lines aren’t easy to find or follow. Thankfully, there are people who painstakingly log each experiment and index much of what’s out there. Chris Coyier does this with CSS in general, and Brad Frost is doing this for responsive and multi-device design with his Pattern Library. Seriously, take a look at this page and imagine what it would take to find, track and organize the progression of each of these resources yourself. I’d argue that ongoing collections like these are more valuable than the sum of their parts when they are updated regularly as opposed to a top ten tips blog post format. Here’s my soapbox Here are a few things I appreciate about how things are shared and contributed online. And yes, I could do way better at all of them myself. Concise write-ups: honor others’ time by getting to the point. Not every idea or solution needs two thousand words to convey fully. I love long-form posts, but there’s a time and a place for them. Visual aids: if a quick illustration, screenshot, or graphic helps illustrate your point or problem, yes please. By the way, Luke Wroblewski rules the school on both of these. Demo it: host it yourself, or put it on CodePen or JS Bin for others to see. Put it on Github: share and improve with the rest of the community. Consider, however, that because someone puts something on Github doesn’t mean they’re forever bound to provide support or instruction. This isn’t a call for everyone to learn everything all the time, but if you’re curious or interested in something, skip the shortcut and get your hands dirty: sketch, prototype, question, debate, fork, and share. Figuring these things out on our own makes us valuable contributors to the web – the thing that ultimately we’re all trying to figure out together. 2012 Trent Walton trentwalton 2012-12-03T00:00:00+00:00 https://24ways.org/2012/being-prepared-to-contribute/ process
11 JavaScript: Taking Off the Training Wheels JavaScript is the third pillar of front-end web development. Of those pillars, it is both the most powerful and the most complex, so it’s understandable that when 24 ways asked, “What one thing do you wish you had more time to learn about?”, a number of you answered “JavaScript!” This article aims to help you feel happy writing JavaScript, and maybe even without libraries like jQuery. I can’t comprehensively explain JavaScript itself without writing a book, but I hope this serves as a springboard from which you can jump to other great resources. Why learn JavaScript? So what’s in it for you? Why take the next step and learn the fundamentals? Confidence with jQuery If nothing else, learning JavaScript will improve your jQuery code; you’ll be comfortable writing jQuery from scratch and feel happy bending others’ code to your own purposes. Writing efficient, fast and bug-free jQuery is also made much easier when you have a good appreciation of JavaScript, because you can look at what jQuery is really doing. Understanding how JavaScript works lets you write better jQuery because you know what it’s doing behind the scenes. When you need to leave the beaten track, you can do so with confidence. In fact, you could say that jQuery’s ultimate goal is not to exist: it was invented at a time when web APIs were very inconsistent and hard to work with. That’s slowly changing as new APIs are introduced, and hopefully there will come a time when jQuery isn’t needed. An example of one such change is the introduction of the very useful document.querySelectorAll. Like jQuery, it converts a CSS selector into a list of matching elements. Here’s a comparison of some jQuery code and the equivalent without. $('.counter').each(function (index) { $(this).text(index + 1); }); var counters = document.querySelectorAll('.counter'); [].slice.call(counters).forEach(function (elem, index) { elem.textContent = index + 1; }); Solving problems no one else has! When you have to go to the internet to solve a problem, you’re forever stuck reusing code other people wrote to solve a slightly different problem to your own. Learning JavaScript will allow you to solve problems in your own way, and begin to do things nobody else ever has. Node.js Node.js is a non-browser environment for running JavaScript, and it can do just about anything! But if that sounds daunting, don’t worry: the Node community is thriving, very friendly and willing to help. I think Node is incredibly exciting. It enables you, with one language, to build complete websites with complex and feature-filled front- and back-ends. Projects that let users log in or need a database are within your grasp, and Node has a great ecosystem of library authors to help you build incredible things. Exciting! Here’s an example web server written with Node. http is a module that allows you to create servers and, like jQuery’s $.ajax, make requests. It’s a small amount of code to do something complex and, while working with Node is different from writing front-end code, it’s certainly not out of your reach. var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World'); }).listen(1337); console.log('Server running at http://localhost:1337/'); Grunt and other website tools Node has brought in something of a renaissance in tools that run in the command line, like Yeoman and Grunt. Both of these rely heavily on Node, and I’ll talk a little bit about Grunt here. Grunt is a task runner, and many people use it for compiling Sass or compressing their site’s JavaScript and images. It’s pretty cool. You configure Grunt via the gruntfile.js, so JavaScript skills will come in handy, and since Grunt supports plug-ins built with JavaScript, knowing it unlocks the bucketloads of power Grunt has to offer. Ways to improve your skills So you know you want to learn JavaScript, but what are some good ways to learn and improve? I think the answer to that is different for different people, but here are some ideas. Rebuild a jQuery app Converting a jQuery project to non-jQuery code is a great way to explore how you modify elements on the page and make requests to the server for data. My advice is to focus on making it work in one modern browser initially, and then go cross-browser if you’re feeling adventurous. There are many resources for directly comparing jQuery and non-jQuery code, like Jeffrey Way’s jQuery to JavaScript article. Find a mentor If you think you’d work better on a one-to-one basis then finding yourself a mentor could be a brilliant way to learn. The JavaScript community is very friendly and many people will be more than happy to give you their time. I’d look out for someone who’s active and friendly on Twitter, and does the kind of work you’d like to do. Introduce yourself over Twitter or send them an email. I wouldn’t expect a full tutoring course (although that is another option!) but they’ll be very glad to answer a question and any follow-ups every now and then. Go to a workshop Many conferences and local meet-ups run workshops, hosted by experts in a particular field. See if there’s one in your area. Workshops are great because you can ask direct questions, and you’re in an environment where others are learning just like you are — no need to learn alone! Set yourself challenges This is one way I like to learn new things. I have a new thing that I’m not very good at, so I pick something that I think is just out of my reach and I try to build it. It’s learning by doing and, even if you fail, it can be enormously valuable. Where to start? If you’ve decided learning JavaScript is an important step for you, your next question may well be where to go from here. I’ve collected some links to resources I know of or use, with some discussion about why you might want to check a particular site out. I hope this serves as a springboard for you to go out and learn as much as you want. Beginner If you’re just getting started with JavaScript, I’d recommend heading to one of these places. They cover the basics and, in some cases, a little more advanced stuff. They’re all reputable sources (although, I’ve included something I wrote — you can decide about that one!) and will not lead you astray. jQuery’s JavaScript 101 is a great first resource for JavaScript that will give you everything you need to work with jQuery like a pro. Codecademy’s JavaScript Track is a small but useful JavaScript course. If you like learning interactively, this could be one for you. HTMLDog’s JavaScript Tutorials take you right through from the basics of code to a brief introduction to newer technology like Node and Angular. [Disclaimer: I wrote this stuff, so it comes with a hazard warning!] The tuts+ jQuery to JavaScript mentioned earlier is great for seeing how jQuery code looks when converted to pure JavaScript. Getting in-depth For more comprehensive documentation and help I’d recommend adding these places to your list of go-tos. MDN: the Mozilla Developer Network is the first place I go for many JavaScript questions. I mostly find myself there via a search, but it’s a great place to just go and browse. Axel Rauschmayer’s 2ality is a stunning collection of articles that will take you deep into JavaScript. It’s certainly worth looking at. Addy Osmani’s JavaScript Design Patterns is a comprehensive collection of patterns for writing high quality JavaScript, particularly as you (I hope) start to write bigger and more complex applications. And finally… I think the key to learning anything is curiosity and perseverance. If you have a question, go out and search for the answer, even if you have no idea where to start. Keep going and going and eventually you’ll get there. I bet you’ll learn a whole lot along the way. Good luck! Many thanks to the people who gave me their time when I was working on this article: Tom Oakley, Jack Franklin, Ben Howdle and Laura Kalbag. 2013 Tom Ashworth tomashworth 2013-12-05T00:00:00+00:00 https://24ways.org/2013/javascript-taking-off-the-training-wheels/ code
294 New Tricks for an Old Dog Much of my year has been spent helping new team members find their way around the expansive and complex codebase that is the TweetDeck front-end, trying to build a happy and productive group of people around a substantial codebase with many layers of legacy. I’ve loved doing this. Everything from writing new documentation, drawing diagrams, and holding technical architecture sessions teaches you something you didn’t know or exposes an area of uncertainty that you can go work on. In this article, I hope to share some experiences and techniques that will prove useful in your own situation and that you can impress your friends in some new and exciting ways! How do you do, fellow kids? To start with I’d like to introduce you to our JavaScript framework, Flight. Right now it’s used by twitter.com and TweetDeck although, as a company, Twitter is largely moving to React. Over time, as we used Flight for more complex interfaces, we found it wasn’t scaling with us. Composing components into trees was fiddly and often only applied for a specific parent-child pairing. It seems like an obvious feature with hindsight, but it didn’t come built-in to Flight, and it made reusing components a real challenge. There was no standard way to manage the state of a component; they all did it slightly differently, and the technique often varied by who was writing the code. This cost us in maintainability as you just couldn’t predict how a component would be built until you opened it. Making matters worse, Flight relied on events to move data around the application. Unfortunately, events aren’t good for giving structure to complex logic. They jump around in a way that’s hard to understand and debug, and force you to search your code for a specific string — the event name‚ to figure out what’s going on. To find fixes for these problems, we looked around at other frameworks. We like React for it’s simple, predictable state management and reactive re-render flow, and Elm for bringing strict functional programming to everyone. But when you have lots of existing code, rewriting or switching framework is a painful and expensive option. You have to understand how it will interact with your existing code, how you’ll test it alongside existing code, and how it will affect the size and performance of the application. This all takes time and effort! Instead of planning a rewrite, we looked for the ideas hidden within other frameworks that we could reapply in our own situation or bring to the tools we already were using. Boiled down, what we liked seemed quite simple: Component nesting & composition Easy, predictable state management Normal functions for data manipulation Making these ideas applicable to Flight took some time, but we’re in a much better place now. Through persistent trial-and-error, we have well documented, testable and standard techniques for creating complex component hierarchies, updating and reacting to state changes, and passing data around the app. While the specifics of our situation and Flight aren’t really important, this experience taught me something: Distill good tech into great ideas. You can apply great ideas anywhere. You don’t have to use cool kids’ latest framework, hottest build tool or fashionable language to benefit from them. If you can identify a nugget of gold at the heart of it all, why not use it to improve what you have already? Times, they are a changin’ Apart from stealing ideas from the new and shiny, how can we keep make the most of improved tooling and techniques? Times change and so should the way we write code. Going back in time a bit, TweetDeck used some slightly outmoded tools for building and bundling. Without a transpiler like Babel we were missing out new language features, and without a more advanced build tools like Webpack, every module’s source was encased in AMD boilerplate. In fact, we found ourselves with a mix of both AMD syntaxes: define(["lodash"], function (_) { // . . . }); define(function (require) { var _ = require("lodash"); // . . . }); This just wouldn’t do. And besides, what we really wanted was CommonJS, or even ES2015 module syntax: import _ from "lodash"; These days we’re using Babel, Webpack, ES2015 modules and many new language features that make development just… better. But how did we get there? To explain, I want to introduce you to codemods and jscodeshift. A codemod is a large-scale refactor of a whole codebase, often mechanical or repetitive. Think of renaming a module or changing an API like URL("...") to new URL("..."). jscodeshift is a toolkit for running automated codemods, where you express a code transformation using code. The automated codemod operates on each file’s syntax tree – a data-structure representation of the code — finding and modifying in place as it goes. Here’s an example that renames all instances of the variable foo to bar: module.exports = function (fileInfo, api) { return api .jscodeshift(fileInfo.source) .findVariableDeclarators('foo') .renameTo('bar') .toSource(); }; It’s a seriously powerful tool, and we’ve used it to write a series of codemods that: rename modules, unify our use of AMD to a single syntax, transition from one testing framework to another, and switch from AMD to CommonJS. These changes can be pretty huge and far-reaching. Here’s an example commit from when we switched to CommonJS: commit 8f75de8fd4c702115c7bf58febba1afa96ae52fc Date: Tue Jul 12 2016 Run AMD -> CommonJS codemod 418 files changed, 47550 insertions(+), 48468 deletions(-) Yep, that’s just under 50k lines changed, tested, merged and deployed without any trouble. AMD be gone! From this step-by-step approach, using codemods to incrementally tweak and improve, we extracted a little codemod recipe for making significant, multi-stage changes: Find all the existing patterns Choose the two most similar Unify with a codemod Repeat. For example: For module loading, we had 2 competing AMD patterns plus some use of CommonJS The two AMD syntaxes were the most similar We used a codemod to move to unify the AMD patterns Later we returned to AMD to convert it to CommonJS It’s worked for us, and if you’d like to know more about codemods then check out Evolving Complex Systems Incrementally by Facebook engineer, Christoph Pojer. Welcome aboard! As TweetDeck has gotten older and larger, the amount of things a new engineer has to learn about has exploded. The myriad of microservices that manage our data and their layers of authentication, security and business logic around them make for an overwhelming amount of information to hand to a newbie. Inspired by Amy’s amazing Guide to the Care and Feeding of Junior Devs, we realised it was important to take time to design our onboarding that each of our new hires go through to make the most of their first few weeks. Joining a new company, team, or both, is stressful and uncomfortable. Everything you can do to help a new hire will be valuable to them. So please, take time to design your onboarding! And as you build up an onboarding process, you’ll create things that are useful for more than just new hires; it’ll force you to write documentation, for example, in a way that’s understandable for people who are unfamiliar with your team, product and codebase. This can lead to more outside contributions: potential contributors feel more comfortable getting set up on your product without asking for help. This is something that’s taken for granted in open source, but somehow I think we forget about it in big companies. After all, better documentation is just a good thing. You will forget things from time to time, and you’d be surprised how often the “beginner” docs help! For TweetDeck, we put together system and architecture diagrams, and one-pager explanations of important concepts: What are our dependencies? Where are the potential points of failure? Where does authentication live? Storage? Caching? Who owns “X”? Of course, learning continues long after onboarding. The landscape is constantly shifting; old services are deprecated, new APIs appear and what once true can suddenly be very wrong. Keeping up with this is a serious challenge, and more than any one person can track. To address this, we’ve thought hard about our knowledge sharing practices across the whole team. For example, we completely changed the way we do code review. In my opinion, code review is the single most effective practice you can introduce to share knowledge around, and build the quality and consistency of your team’s work. But, if you’re not doing it, here’s my suggestion for getting started: Every pull request gets a +1 from someone else. That’s all — it’s very light-weight and easy. Just ask someone to have a quick look over your code before it goes into master. At Twitter, every commit gets a code review. We do a lot of reviewing, so small efficiency and effectiveness improvements make a big difference. Over time we learned some things: Don’t review for more than hour 1 Keep reviews smaller than ~400 lines 2 Code review your own code first 2 After an hour, and above roughly 400 lines, your ability to detect issues in a code review starts to decrease. So review little and often. The gaps around lunch, standup and before you head home are ideal. And remember, if someone’s put code up for a review, that review is blocking them doing other work. It’s your job to unblock them. On TweetDeck, we actually try to keep reviews under 250 lines. It doesn’t sound like much, but this constraint applies pressure to make smaller, incremental changes. This makes breakages easier to detect and roll back, and leads to a very natural feature development process that encourages learning and iteration. But the most important thing I’ve learned personally is that reviewing my own code is the best way to spot issues. I try to approach my own reviews the way I approach my team’s: with fresh, critical eyes, after a break, using a dedicated code review tool. It’s amazing what you can spot when you put a new in a new interface around code you’ve been staring at for hours! And yes, this list features science. The data backs up these conclusions, and if you’d like to learn more about scientific approaches to software engineering then I recommend you buy Making Software: What Really Works, and Why We Believe It. It’s ace. For more dedicated information sharing, we’ve introduced regular seminars for everyone who works on a specific area or technology. It works like this: a team-member shares or teaches something to everyone else, and next time it’s someone else’s turn. Giving everyone a chance to speak, and encouraging a wide range of topics, is starting to produce great results. If you’d like to run a seminar, one thing you could try to get started: run a point at the thing you least understand in our architecture session — thanks to James for this idea. And guess what… your onboarding architecture diagrams will help (and benefit from) this! More, please! There’s a few ideas here to get you started, but there are even more in a talk I gave this year called Frontend Archaeology, including a look at optimising for confidence with front-end operations. And finally, thanks to Amy for proof reading this and to Passy for feedback on the original talk. Dunsmore et al. 2000. Object-Oriented Inspection in the Face of Delocalisation. Beverly, MA: SmartBear Software. ↩ Cohen, Jason. 2006. Best Kept Secrets of Peer Code Review. Proceedings of the 22nd ICSE 2000: 467-476. ↩ ↩ 2016 Tom Ashworth tomashworth 2016-12-18T00:00:00+00:00 https://24ways.org/2016/new-tricks-for-an-old-dog/ code
119 Rocking Restrictions I love my job. I live my job. For every project I do, I try to make it look special. I’ll be honest: I have a fetish for comments like “I never saw anything like that!” or, “I wish I thought of that!”. I know, I have an ego-problem. (Eleven I’s already) But sometimes, you run out of inspiration. Happens to everybody, and everybody hates it. “I’m the worst designer in the world.” “Everything I designed before this was just pure luck!” No it wasn’t. Countless articles about finding inspiration have already been written. Great, but they’re not the magic potion you’d expect them to be when you need it. Here’s a list of small tips that can have immediate effect when applying them/using them. Main theme: Liberate yourself from the designers’ block by restricting yourself. Do’s Grids If you aren’t already using grids, you’re doing something wrong. Not only are they a great help for aligning your design, they also restrict you to certain widths and heights. (For more information about grids, I suggest you read Mark Boulton’s series on designing grid systems. Oh, he’s also publishing a book I think.) So what’s the link between grids and restrictions? Instead of having the option to style a piece of layout with a width of 1 to 960 pixels, you have to choose from values like 60 pixels, 140, 220, 300, … Start small Having a hard time finding a style for the layout, why don’t you start with one small object? No, not that small object, I meant a piece of a form, or a link, or try styling your headers (h1 – h6). Let’s take a submit button of a form: it’s small, but needs much attention. People will click it. People will hover it. Maybe sometimes it’s disabled? Also: a button needs to look like a button, so typically it requires more styling then a regular link. Once you’ve got the button, move on, following the button’s style. Color palettes There are lots of resources on the web for finding inspiration for color palettes. Some of the most famous are COLOURlovers, wear palettes and Adobe’s Kuler. Browse through them (or create your own from a picture), pick a color palette you like and which works with the subject you’re handling, and stick with it. 4-5 colors, maybe with some tonal variations, but that’s it. Fonts There aren’t many fonts available for the web (Richard Rutter has a great article on this subject), but you’d be surprised how long they go. A simple text-transform: uppercase; or font-style: italic; can change a dull looking font into something entirely fresh. Play around with the fonts you want to use and the variations you’ll be using, and make a list. Pick five combinations of fonts and their variations, and stick with them throughout the layout. Single-task Most of us use multiple monitors. They’re great to increase productivity, but make it harder to focus on a single task. Here’s what you do: try using only your smallest monitor. Maybe it’s the one from your laptop, maybe it’s an old 1024×768 you found in the attic. Having Photoshop (or Fireworks or…) taking over your entire workspace blocks out all the other distractions on your screen, and works quite liberating. Mute everything… …but not entirely. I noticed I was way more focused when I set NetNewsWire to refresh it’s feeds only once every two hours. After two hours, I need a break anyway. Turning off Twitterrific was a mistake, as it’s my window to the world, and it’s the place where the people I like to call colleagues live. You can’t exactly ask them to bring you a cup of coffee when they go to the vending machine, but they do keep you fresh, and it stops you from going human-shy. Instead I changed the settings to not play a notification sound when new Tweets arrive so it doesn’t disturb me when I’m zoning. Don’ts CSS galleries Don’t start browsing all kinds of CSS galleries. Either you’ll feel bad, or you just start using elements in a way you can’t call “inspired” anymore. Instead gather your own collection of inspiration. Example: I use LittleSnapper in which I dump everything I find inspiring. This goes from a smart layout idea, to a failed picture someone posted on Flickr. Everything is inspiring. Panicking Don’t panic. It’s the worst thing you could do. Instead, get away from the computer, and go to bed early. A good night of sleep combined with a hot/cold shower can give you a totally new perspective on a design. Got a deadline by tomorrow? Well, you should’ve started earlier. Got a good excuse to start on this design this late? Tell your client it was either that or a bad design. 120-hour work-week Don’t work all day long, including evenings and early mornings. Write off that first hour, you don’t really think you’ll get anything productive done before 9AM?! I don’t even think you should work on one and the same design all day long. If you’re stuck, try working in blocks of 1 or 2 hours on a certain design. Mixing projects isn’t for everyone, but it might just do the trick for you. Summary Use grids, not only for layout purposes. Pick a specific element to start with. Use a colour palette. Limit the amount of fonts and variations you’ll use. Search for the smallest monitor around, and restrict yourself to that one. Reduce the amount of noise. Don’t start looking on the internet for inspiration. Build your own little inspirarchive. Work in blocks. 2008 Tim Van Damme timvandamme 2008-12-14T00:00:00+00:00 https://24ways.org/2008/rocking-restrictions/ process
191 CSS Animations Friend: You should learn how to write CSS! Me: … Friend: CSS; Cascading Style Sheets. If you’re serious about web design, that’s the next thing you should learn. Me: What’s wrong with <font> tags? That was 8 years ago. Thanks to the hard work of Jeffrey, Andy, Andy, Cameron, Colly, Dan and many others, learning how to decently markup a website and write lightweight stylesheets was surprisingly easy. They made it so easy even a complete idiot (OH HAI) was able to quickly master it. And then… nothing. For a long time, it seemed like there wasn’t happening anything in the land of CSS, time stood still. Once you knew the basics, there wasn’t anything new to keep up with. It looked like a great band split, but people just kept re-releasing their music in various “Best Of!” or “Remastered!” albums. Fast forward a couple of years to late 2006. On the official WebKit blog Surfin’ Safari, there’s an article about something called CSS animations. Great new stuff to play with, but only supported by nightly builds (read: very, very beta) of WebKit. In the following months, they release other goodies, like CSS gradients, CSS reflections, CSS masks, and even more CSS animation sexiness. Whoa, looks like the band got back together, found their second youth, and went into overdrive! The problem was that if you wanted to listen to their new albums, you had to own some kind of new high-tech player no one on earth (besides some early adopters) owned. Back in the time machine. It is now late 2009, close to Christmas. Things have changed. Browsers supporting these new toys are widely available left and right. Even non-techies are using these advanced browsers to surf the web on a daily basis! Epic win? Almost, but at least this gives us enough reason to start learning how we could use all this new CSS voodoo. On Monday, Natalie Downe showed you a good tutorial on Going Nuts with CSS Transitions. Today, I’m taking it one step further… Howto: A basic spinner No matter how fast internet tubes or servers are, we’ll always need spinners to indicate something’s happening behind the scenes. Up until now, people would go to some site, pick one of the available templates, customize their foreground and background colors, and download a beautiful GIF image. There are some downsides to this though: It’s only _semi_-transparent: If you change your mind and pick a slightly different background color, you need to go back to the site, set all the parameters again, and replace your current image. There isn’t even a way to pick an image or gradient as background. Limited number of frames, probable to keep the file-size as small as possible (don’t forget this thing needs to be loaded before whatever process is finished in the background), and you don’t have that 24 frames per second smoothness. This is just too fucking easy. As a front-end code geek, there must be a “cooler” way to do this! What do we need to make a spinner with CSS animations? One image, and one element on our webpage we can hook on to. Yes, that’s it. I created a simple transparent PNG that looks it might be a spinner, and for the element on the page, I wrote this piece of genius HTML: <p id="spinner">Please wait while we do what we do best.</p> Looks semantic enough to me! Here’s the basic HTML I’m using to position the element in the center of the screen, and make the text inside it disappear: #spinner { position: absolute; top: 50%; left: 50%; margin: -100px 0 0 -100px; height: 200px; width: 200px; text-indent: 250px; white-space: nowrap; overflow: hidden; } Cool, but now we don’t see anything. Let’s pull rabbit number one out of the hat: -webkit-mask-image (accompanied by the previously mentioned transparent PNG image): #spinner { ... -webkit-mask-image: url(../img/spinner.png); } By now you should be feeling like a magician already. Oh, wait, we still have a blank screen, looks like we left something in the hat (tip: not rabbit droppings): #spinner { ... -webkit-mask-image: url(../img/spinner.png); background-color: #000; } Nice! What we’ve done right here is telling the element to clip onto the PNG. It’s a lot like clipping layers in Photoshop. So, spinners, they move, right? Into the hat again, and look what we pull out this time: CSS animations! #spinner { ... -webkit-mask-image: url(../img/spinner.png); background-color: #000; -webkit-animation-name: spinnerRotate; -webkit-animation-duration: 2s; -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: linear; } Some explanation: -webkit-animation-name: Name of the animation we’ll be defining later. -webkit-animation-duration: The timespan of the animation. -webkit-animation-iteration-count: Repeat once, a defined number of times or infinitely? -webkit-animation-timing-function: Linear is the one you’ll be using mostly. Other options are ease-in, ease-out, ease-in-out… Let’s define spinnerRotate: @-webkit-keyframes spinnerRotate { from { -webkit-transform:rotate(0deg); } to { -webkit-transform:rotate(360deg); } } En Anglais: Rotate #spinner starting at 0 degrees, ending at 360 degrees, over a timespan of 2 seconds, at a constant speed, and keep repeating this animation forever. That’s it! See it in action on the demo page. Note: these examples only work when you’re using a WebKit-based browser like Safari, Mobile Safari or Google Chrome. I’m confident though that Mozilla and Opera will try their very best catching up with all this new CSS goodness soon. When looking at this example, you see the possibilities are endless. Another advantage is you can change the look of it entirely by only changing a couple of lines of CSS, instead of re-creating and re-downloading the image from some website smelling like web 2.0 gone bad. I made another demo that shows how great it is to be able to change background and foreground colors (even on the fly!). So there you have it, a smoothly animated, fully transparent and completely customizable spinner. Cool? I think so. (Ladies?) But you can do a lot more with CSS animations than just create pretty spinners. Since I was fooling around with it anyway, I decided to test how far you can push this, space is the final limit, right? Conclusion CSS has never been more exciting than it is right now. I’m even prepared to say CSS is “cool” again, both for the more experienced front-end developers as for the new designers discovering CSS every day now. But… Remember when Javascript became popular? Remember when Flash became popular? Every time we’re been given new toys, some people aren’t ashamed to use it in a way you can barely call constructive. I’m thinking of Geocities websites, loaded with glowing blocks of text, moving images, bad color usage… In the wise words of Stan Lee: With great power there must also come great responsibility! A sprinkle of CSS animations is better than a bucket load. Apply with care. 2009 Tim Van Damme timvandamme 2009-12-15T00:00:00+00:00 https://24ways.org/2009/css-animations/ code
84 Responsive Responsive Design Now more than ever, we’re designing work meant to be viewed along a gradient of different experiences. Responsive web design offers us a way forward, finally allowing us to “design for the ebb and flow of things.” With those two sentences, Ethan closed the article that introduced the web to responsive design. Since then, responsive design has taken the web by storm. Seemingly every day, some company is touting their new responsive redesign. Large brands such as Microsoft, Time and Disney are getting in on the action, blowing away the once common criticism that responsive design was a technique only fit for small blogs. Certainly, this is a good thing. As Ethan and John Allsopp before him, were right to point out, the inherent flexibility of the web is a feature, not a bug. The web’s unique ability to be consumed and interacted with on any number of devices, with any number of input methods is something to be embraced. But there’s one part of the web’s inherent flexibility that seems to be increasingly overlooked: the ability for the web to be interacted with on any number of networks, with a gradient of bandwidth constraints and latency costs, on devices with varying degrees of hardware power. A few months back, Stephanie Rieger tweeted “Shoot me now…responsive design has seemingly become confused with an opportunity to reduce performance rather than improve it.” I would love to disagree, but unfortunately the evidence is damning. Consider the size and number of requests for four highly touted responsive sites that were launched this year: 74 requests, 1,511kb 114 requests, 1,200kb 99 requests, 1,298kb 105 requests, 5,942kb And those numbers were for the small screen versions of each site! These sites were praised for their visual design and responsive nature, and rightfully so. They’re very easy on the eyes and a lot of thought went into their appearance. But the numbers above tell an inconvenient truth: for all the time spent ensuring the visual design was airtight, seemingly very little (if any) attention was given to their performance. It would be one thing if these were the exceptions, but unfortunately they’re not. Guy Podjarny, who has done a lot of research around responsive performance, discovered that 86% of the responsive sites he tested were either the same size or larger on the small screen as they were on the desktop. The reality is that high performance should be a requirement on any web project, not an afterthought. Poor performance has been tied to a decrease in revenue, traffic, conversions, and overall user satisfaction. Case study after case study shows that improving performance, even marginally, will impact the bottom line. The situation is no different on mobile where 71% of people say they expect sites to load as quickly or faster on their phone when compared to the desktop. The bottom line: performance is a fundamental component of the user experience. So, given it’s extreme importance in the success of any web project, why is it that we’re seeing so many bloated responsive sites? First, I adamantly disagree with the belief that poor performance is inherent to responsive design. That’s not a rule – it’s a cop-out. It’s an example of blaming the technique when we should be blaming the implementation. This argument also falls flat because it ignores the fact that the trend of fat sites is increasing on the web in general. While some responsive sites are the worst offenders, it’s hardly an issue resigned to one technique. To fix the issue, we need to stop making excuses and start making improvements instead. Here, then, are some things we can do to start improving the state of responsive performance, and performance in general, right now. Create a culture of performance If you understand just how important performance is to the success of a project, the natural next step is to start creating a culture where high performance is a key consideration. One of the things you can do is set a baseline. Determine the maximum size and number of requests you are going to allow, and don’t let a page go live if either of those numbers is exceeded. The BBC does this with its responsive mobile site. A variation of that, which Steve Souders discussed in a recent podcast is to create a performance budget based on those numbers. Once you have that baseline set, if someone comes along and wants to add a something to the page, they have to make sure the page remains under budget. If it exceeds the budget, you have three options: Optimize an existing feature or asset on the page Remove an existing feature or asset from the page Don’t add the new feature or asset The idea here is that you make performance part of the process instead of something that may or may not get tacked on at the end. Embrace the pain This troubling trend of web bloat can be blamed in part on the lack of pain associated with poor performance. Most of us work on high-speed connections with low latency. When we fire up a 4Mb site, it doesn’t feel so bad. When I tested the previously mentioned 5,942kb site on a 3G network, it took over 93 seconds to load. A minute and a half just staring at a white screen. Had anyone working on that project experienced that, you can bet the site wouldn’t have launched in that state. Don’t just crunch numbers. Fire up your site on a slower network and see what it feels like to wait. If you don’t have access to a slow network, simulate one using a tool like Slowy, Throttle or the Network Conditioner found in Mac OS X 10.7. Watch for low-hanging fruit There are a bunch of general performance improvements that apply to any site (responsive or not) but often aren’t made. A great starting point is to refer to Yahoo!‘s list of rules. Some of this might sound complicated or intimidating, but it doesn’t have to be. You can grab an .htaccess file from HTML 5 Boilerplate or use Sergey Chernyshev’s drop-in .htaccess file. You can use tools like SpriteMe to simplify the creation of sprites, and ImageOptim to compress images. Just by implementing these simple optimizations you will achieve a noticeable improvement in terms of weight and page load time. Be careful with images The most common offender for poor responsive performance is downloading unnecessarily large images, or worse yet, multiple sizes of the same image. For background images, simply being careful with where and how you include the image can ensure you don’t get caught in the trap of multiple background images being downloaded without being used. Don’t count on display:none to help. While it may hide elements from displaying on screen, those images will still be requested and downloaded. Content images can be a little trickier. Whatever you do, don’t serve a large image that works on a large screen display to small screens. It’s wasteful, not only in terms of adding weight to the page, but also in wasting precious memory. Instead, use a tool like Adaptive Images or src.sencha.io to make sure only appropriately sized images are being downloaded. The new <picture> element that has been so often discussed is another excellent solution if you’re feeling particularly future-oriented. A picture polyfill exists so that you can start using the element now without any worries about support. Conditional loading Don’t load any more than you absolutely need to. If a script isn’t needed at certain sizes, use the matchMedia polyfill to ensure it only loads when needed. Use eCSSential to do the same for unnecessary CSS files. Last year on 24 ways, Jeremy Keith wrote an article about conditional loading of content in a responsive design based on the screen width. The technique was later refined by the Filament Group into what they dubbed the Ajax-Include Pattern. It’s a powerful and simple way to lighten the load on small screens as well as reduce clutter. Go vanilla? If you take a look at the HTTP Archive you’ll see that other than image size, JavaScript is the heaviest asset on a page weighing in at 215kb on average. It also boasts the fifth highest correlation to load time as well as the second highest correlation to render time. Much of the weight can be attributed to our industry’s increasing reliance on frameworks. This is especially a concern on mobile devices. PPK recently exclaimed that current JavaScript libraries are just “too heavy for mobile”. “Research from Stoyan Stefanov on parse times supports this. On some Android and iOS devices, it can take as long as 200-300ms just to parse jQuery. There’s nothing wrong about using a framework, but the problem is that they’ve become the default. Before dropping another framework or plugin into a page, we should stop to consider the value it adds and whether we could accomplish what we need to do using a combination of vanilla JavaScript and CSS instead. (This is a great example of a scenario where a performance budget could help.) Start thinking beyond visual aesthetics We love to tout the web’s universality when discussing the need for responsive design. But that universality is not limited simply to screen size. Networks and hardware capabilities must factor in as well. The web is an incredibly dynamic and interactive medium, and designing for it demands that we consider more than just visual aesthetics. Let’s not forget to give those other qualities the attention they deserve. 2012 Tim Kadlec timkadlec 2012-12-05T00:00:00+00:00 https://24ways.org/2012/responsive-responsive-design/ design
225 Good Ideas Grow on Paper Great designers have one thing in common: their design process is centred on ideas; ideas that are more often than not developed on paper. Though it’s often tempting to take the path of least resistance, turning to the computer in the headlong rush to complete a project (often in the face of formidable client pressure), resist the urge and – for a truly great idea – start first on paper. The path of least resistance is often characterised by cliché and overused techniques – one per cent noise, border-radius, text-shadow – the usual suspects – techniques that are ten-a-penny at the gallery sites. Whilst all are useful, and technique and craft are important, great design isn’t about technique alone – it’s about technique in the service of good ideas. But how do we generate those ideas? Inspiration can certainly come to you out of the blue. When working as a designer in a role which often consists of incubating good ideas, however, idly waiting for the time-honoured lightbulb to appear above your head just isn’t good enough. We need to establish an environment where we tip the odds of getting good ideas in our favour. So, when faced with the blank canvas, what do we do to unlock the proverbial tidal wave of creativity? Fear not. We’re about to share with you a couple of stalwart techniques that will stand you in good stead when you need that good idea, in the face of the pressure of yet another looming deadline. Get the process right Where do ideas come from? In many cases they come from anywhere but the screen. Hence, our first commandment is to close the lid of your computer and, for a change, work on paper. It might seem strange, it might also seem like a distraction, but – trust us – the time invested here will more than pay off. Idea generation should be a process of rapid iteration, sketching and thinking aloud, all processes best undertaken in more fast paced, analogue media. Our tool of choice is the Sharpie and Flip Chart Combo©, intentionally low resolution to encourage lo-fi idea generation. In short, your tools should be designed not to be precious, but to quickly process your thoughts. Ideas can be expressed with a thick line marker or by drawing with a stick in the sand; it’s the ideas that matter, not the medium. Input > Synthesise > Output Ideas don’t materialise in a vacuum. Without constant input, the outputs will inevitably remain the same. As such, it’s essential to maintain an inquisitive mind, ensuring a steady flow of new triggers and stimuli that enable your thinking to evolve. What every designer brings to the table is their prior experience and unique knowledge. It should come as no surprise to discover that a tried and tested method of increasing that knowledge is, believe it or not, to read – often and widely. The best and most nuanced ideas come after many years of priming the brain with an array of diverse material, a point made recently in Jessica Hische’s aptly named Why You Should Know Your Shit. One of the best ways of synthesising the knowledge you accumulate is to write. The act of writing facilitates your thinking and stores the pieces of the jigsaw you’ll one day return to. You don’t have to write a book or a well-articulated article; a scribbled note in the margin will suffice in facilitating the process of digestion. As with writing, we implore you to make sketching an essential part of your digestion process. More immediate than writing, sketching has the power to put yet unformed ideas down on paper, giving you an insight into the fantastic conceptions you’re more often than not still incubating. Our second commandment is a practical one: always carry a sketchbook and a pen. Although it seems that the very best ideas are scribbled on the back of a beer mat or a wine-stained napkin, always carrying your ‘thinking utensils’ should be as natural as not leaving the house without your phone, wallet, keys or pants. Further, the more you use your sketchbook, the less precious you’ll find yourself becoming. Sketching isn’t about being an excellent draughtsman, it’s about synthesising and processing your thoughts and ideas, as Jason Santa Maria summarises nicely in his article Pretty Sketchy: Sketchbooks are not about being a good artist, they’re about being a good thinker. Jason Santa Maria The sketchbook and pen should become your trusted tools in your task to constantly survey the world around you. As Paul Smith says, You Can Find Inspiration in Anything; close the lid, look beyond the computer; there’s a whole world of inspiration out there. Learn to love old dusty buildings So, how do you learn? How do you push beyond the predictable world pre-filtered by Mr Google? The answer lies in establishing a habit of exploring the wonderful worlds of museums and libraries, dusty old buildings that repay repeated visits. Once the primary repositories of thought and endless sources of inspiration, these institutions are now often passed over for the quick fix of a Google search or Wikipedia by you, the designer, chained to a desk and manacled to a MacBook. Whilst others might frown, we urge you to get away from your desk and take an eye-opening stroll through the knowledge-filled corridors of yore (and don’t forget to bring your sketchbook). Here you’ll find ideas aplenty, ideas that will set you apart from your peers, who remain ever-reliant on the same old digital sources. The idea generation toolbox Now that we’ve established the importance of getting the process and the context right, it’s time to meet the idea generation toolbox: a series of tools and techniques that can be applied singularly or in combination to solve the perennial problem of the blank canvas. The clean sheet of paper, numbing in its emptiness, can prove an insurmountable barrier to many a project, but the route beyond it involves just a few, well-considered steps. The route to a good idea lies in widening your pool of inspiration at the project outset. Let go and generate ideas quickly; it’s critical to diverge before you converge – but how do we do this and what exactly do we mean by this? The temptation is to pull something out of your well-worn box of tricks, something that you know from experience will do the job. We urge you, however, not to fall prey to this desire. You can do better; better still, a few of you putting your minds together can do a lot better. By avoiding the path of least resistance, you can create something extraordinary. Culturally, we value logical, linear thinking. Since the days of Plato and Aristotle, critical thinking, deduction and the pursuit of truth have been rewarded. To generate creative ideas, however, we need to start thinking sideways, making connections that don’t necessarily follow logically. Lateral thinking, a phrase coined by Edward de Bono in 1967, aptly describes this very process: With logic you start out with certain ingredients, just as in playing chess you start out with given pieces – lateral thinking is concerned not with playing with the existing pieces but with seeking to change those very pieces. Edward de Bono One of the easiest ways to start thinking laterally is to start with a mind map, a perfect tool for widening the scope of a project beyond the predictable and an ideal one for getting the context right for discovery. Making connections Mind maps can be used to generate, visualise and structure ideas. Arranged intuitively and classified around groupings, mind maps allow chance connections to be drawn across related groups of information, and are perfect for exposing alogical associations and unexpected relationships. Get a number of people together in a room, equipped with the Sharpie and Flip Chart Combo©. Give yourself a limited amount of time – half an hour should prove more than enough – and you’ll be surprised at the results a few well-chosen people can generate in a very short space of time. The key is to work fast, diverge and not inhibit thinking. We’ve been embracing Tony Buzan’s methods in our teaching for over a decade. His ideas on the power of radiant thinking and how this can be applied to mind maps, uncover the real power which lies in the human brain’s ability to spot connections across a mapped out body of diverse knowledge. Frank Chimero wrote about this recently in How to Have an Idea, which beautifully illustrates Mr Buzan’s theories, articulating the importance of the brain’s ability to make abstract connections, finding unexpected pairings when a concept is mapped out on paper. Once a topic is surveyed and a rich set of stimuli articulated, the next stage is to draw connections, pulling from opposite sides of the mind map. It’s at this point, when defining alogical connections, that the truly interesting and unexpected ideas are often uncovered. The curve ball If you’ve followed our instructions so far, all being well, you should have a number of ideas. Good news: we have one last technique to throw into the mix. We like to call it ‘the curve ball’, that last minute ‘something’ that forces you to rethink and encourages you to address a problem from a different direction. There are a number of ways of throwing in a curve ball – a short, sharp, unexpected impetus – but we have a firm favourite we think you’ll appreciate. Brian Eno and Peter Schmidt’s Oblique Strategies – subtitled ‘Over One Hundred Worthwhile Dilemmas’ – are the perfect creative tool for throwing in a spot of unpredictability. As Eno and Schmidt put it: The Oblique Strategies can be used as a pack (a set of possibilities being continuously reviewed in the mind) or by drawing a single card from the shuffled pack when a dilemma occurs in a working situation. In this case the card is trusted even if its appropriateness is quite unclear. They are not final, as new ideas will present themselves, and others will become self-evident. Brian Eno and Peter Schmidt Simply pick a card and apply the strategy to the problem at hand. The key here, as with de Bono’s techniques, is to embrace randomness and provocation to inspire lateral creative approaches. To assist this process, you might wish to consult one of the many virtual decks of Oblique Strategies online. Wrapping up To summarise, it’s tempting to see the route to the fastest satisfactory conclusion in a computer when, in reality, that’s the last place you should start. The tools we’ve introduced, far from time-consuming, are hyper-efficient, always at hand and, if you factor them into your workflow, the key to unlocking the ideas that set the great designers apart. We wish you well on your quest in search of the perfect idea, now armed with the knowledge that the quest begins on paper. 2010 The Standardistas thestandardistas 2010-12-13T00:00:00+00:00 https://24ways.org/2010/good-ideas-grow-on-paper/ process
196 Designing a Remote Project I came across an article recently, which I have to admit made my blood boil a little. Yes, I know it’s the season of goodwill and all that, and I’m going to risk sounding a little Scrooge-like, but I couldn’t help it. It was written by someone who’d tried out ‘telecommuting’ (big sigh) a.k.a. remote or distributed working. They’d tested it in their company and decided it didn’t work. Why did it enrage me so much? Well, this person sounded like they’d almost set it up to fail. To them, it was the latest buzzword, and they wanted to offer their employees a ‘perk’. But it was going to be risky, because, well, they just couldn’t trust their employees not to be lazy and sit around in their pyjamas at home, watching TV, occasionally flicking their mousepad to ‘appear online’. Sounds about right, doesn’t it? Well, no. This attitude towards remote working is baked in the past, where working from one office and people all sitting around together in a cosy circle singing kum-by-yah* was a necessity not an option. We all know the reasons remote working and flexibility can happen more easily now: fast internet, numerous communication channels, and so on. But why are companies like Yahoo! and IBM backtracking on this? Why is there still such a negative perception of this way of working when it has so much real potential for the future? *this might not have ever really happened in an office. So what is remote working? It can come in various formats. It’s actually not just the typical office worker, working from home on a specific day. The nature of digital projects has been changing over a number of years. In this era where organisations are squeezing budgets and trying to find the best value wherever they can, it seems that the days of whole projects being tackled by one team, in the same place, is fast becoming the past. What I’ve noticed more recently is a much more fragmented way of putting together a project – a mixture of in-house and agency, or multiple agencies or organisations, or working with an offshore team. In the past we might have done the full integrated project from beginning to end, now, it’s a piece of the pie. Which means that everyone is having to work with people who aren’t sat next to them even more than before. Whether that’s a freelancer you’re working with who’s not in the office, an offshore agency doing development or a partner company in another city tackling UX… the future is looking more and more like a distributed workplace. So why the negativity, man? As I’ve seen from this article, and from examples of large corporations changing their entire philosophy away from remote working, there’s a lot of negativity towards this way of working. Of course if you decide to let everyone work from home when they want, set them off and then expect them all to check in at the right time or be available 24/7 it’s going to be a bit of a mess. Equally if you just jump into work with a team on the other side of the world without any setup, should you expect anything less than a problematic project? Okay, okay so what about these people who are going to sit on Facebook all day if we let them work from home? It’s the age old response to the idea of working from home. I can’t see the person, so how do I know what they are doing? This comes up regularly as one of the biggest fears of letting people work remotely. There’s also the perceived lack of productivity and distractions at home. The limited collaboration and communication with distributed workers. The lack of availability. The lower response times. Hang on a second, can’t these all still be problems even if you’ve got your whole team sat in the same place? “They won’t focus on work.” How many people will go on Facebook or Twitter whilst sat in an office? “They won’t collaborate as much.” How many people sit in the office with headphones on to block out distractions? I think we have to move away from the idea that being sat next to people automatically makes them work harder. If the work is satisfying, challenging, and relevant to a person – surely we should trust them to do it, wherever they are sat? There’s actually a lot of benefits to remote working, and having distributed teams. Offering this as a way of working can attract and retain employees, due to the improved flexibility. There can actually be fewer distractions and disruptions at home, which leads to increased productivity. To paraphrase Jason Fried in his talk ‘Why work doesn’t happen at work’, at home there are voluntary distractions where you have to choose to distract yourself with something. At the office these distractions become involuntary. Impromptu meetings and people coming to talk to you all the time are actually a lot more disruptive. Often, people find it easier to focus away from the office environment. There’s also the big benefit for a lot of people of the time saved commuting. The employee can actually do a lot that’s beneficial to them in this time, rather than standing squeezed into people’s armpits on public transport. Hence increased job satisfaction. With a distributed team, say if you’re working with an off-shore team, there could be a wider range of talent to pick from and it also encourages diversity. There can be a wider range of cultural differences and opinions brought to a project, which encourages more diverse ways of thinking. Tackling the issues - or, how to set up a project with a remote team But that isn’t to say running projects with a distributed team or being a remote worker is easy, and can just happen, like that. It needs work – and good groundwork – to ensure you don’t set it up to fail. So how do you help create a smoother remote project? Start with trust First of all, the basis of the team needs to be trust. Yes I’m going to sound a little like a cheesy, self-help guru here (perhaps in an attempt to seem less Scrooge-like and inject some Christmas cheer) but you do need to trust the people working remotely as well as them trusting you. This extends to a distributed team. You can’t just tell the offshore team what to do, and micromanage them, scared they won’t do what you want, how you want it because you can’t see them. You need to give them ownership and let them manage the tasks. Remember, people are less likely to criticise their own work. Make them own the work and they are more likely to be engaged and productive. Set a structure Distributed teams and remote workers can fail when there is no structure – just as much as teams sitting together fail without it too. It’s not so much setting rules, as having a framework to work within. Eliminate blockers before they happen. Think about what could cause issues for the team, and think of ways to solve this. For example, what do you do if you won’t be able to get hold of someone for a few hours because of a time difference? Put together a contingency, e.g. is there someone else on your time zone you could go to with queries after assessing the priority? Would it be put aside until that person is back in? Define team roles and responsibilities clearly. Sit down at the beginning of the project and clearly set out expectations. Also ask the team, what are their expectations of you? There won’t be a one size fits all framework either. Think about your team, the people in it, the type of project you’re working with, the type of client and stakeholder. This should give you an idea of what sort of communications you’ll need on the project. Daily calls, video calls, Slack channels, the choice is yours. Decide on the tools To be honest, I could spend hours talking about the different tools you can use for communication. But you know them, right? And in the end it’s not the tool that’s important here - it’s the communication that’s being done on the tool. Tools need to match the type of communications needed for your team. One caveat here though, never rely solely on email! Emails are silos, and can become beasts to manage communications on. Transparency in communication Good communication is key. Make sure there are clear objectives for communication. Set up one time during the week where those people meet together, discuss all the work during that week that they’ve done. If decisions are made between team members who are together, make sure everyone knows what these are. But try to make collective decisions where you can, when it doesn’t impact on people’s time. Have a face-to-face kick off Yes, I know this might seem to counter my argument, but face-to-face comms are still really important. If it’s feasible, have an in-person meeting to kick off your project, and to kick off your team working together. An initial meeting, to break the ice, discuss ways of working, set the goals, can go a long way to making working with distributed teams successful. If this is really not viable, then hold a video call with the team. Try to make this a little more informal. I know, I know, not the dreaded cringey icebreakers… but something to make everyone relax and get to know each other is really important. Bring everybody together physically on a regular basis if you can, for example with quarterly meetings. You’ve got to really make sure people still feel part of a team, and it often takes a little more work with a remote team. Connect with new team members, one-on-one first, then you can have more of a ‘remote’ relationship. Get visual Visual communication is often a lot better tool to use than just a written sentence, and can help bring ideas to life. Encourage people to sketch things, take a photo and add this to your written communications. Or use a mockup tool to sketch ideas. But what about Agile projects? The whole premise of Agile projects is to have face-to-face contact I hear you cry. The Agile Manifesto itself states “The most efficient and effective method of conveying information to and within a development team is face-to-face conversation”. However, this doesn’t mean the death of remote working. In fact loads of successful companies still run Agile projects, whilst having a distributed team. With all the collaborative tools you can use for centralising code, tracking tasks, visualising products, it’s not difficult to still communicate in a way that works. Just think about how to replicate the principles of Agile remotely - working together daily, a supportive environment, trust, and simplicity. How can you translate these to your remote or distributed team? One last thought to leave you with before you run off to eat your mince pies (in your pyjamas, whilst working). A common mistake in working with a remote project team or working remotely yourself, is replacing distance with time. If you’re away from the office you think you need to always be ‘on’ – messaging, being online, replying to requests. If you have a distributed team, you might think a lot of meetings, calls, and messages will be good to foster communication. But don’t overload these meetings, calls, and communication. This can be disruptive in itself. Give people the gift of some uninterrupted time to actually do some work, and not feel like they have to check in every second. 2017 Suzanna Haworth suzannahaworth 2017-12-06T00:00:00+00:00 https://24ways.org/2017/designing-a-remote-project/ business
198 Is Your Website Accidentally Sexist? Women make up 51% of the world’s population. More importantly, women make 85% of all purchasing decisions about consumer goods, 75% of the decisions about buying new homes, and 81% of decisions about groceries. The chances are, you want your website to be as attractive to women as it is to men. But we are all steeped in a male-dominated culture that subtly influences the design and content decisions we make, and some of those decisions can result in a website that isn’t as welcoming to women as it could be. Typography tells a story Studies show that we make consistent judgements about whether a typeface is masculine or feminine: Masculine typography has a square or geometric form with hard corners and edges, and is emphatically either blunt or spiky. Serif fonts are also considered masculine, as is bold type and capitals. Feminine typography favours slim lines, curling or flowing shapes with a lot of ornamentation and embellishment, and slanted letters. Sans-serif, cursive and script fonts are seen as feminine, as are lower case letters. The effect can be so subtle that even choosing between bold and regular styles within a single font family can be enough to indicate masculinity or femininity. If you want to appeal to both men and women, search for fonts that are gender neutral, or at least not too masculine. When you’re choosing groups of fonts that need to work harmoniously together, consider which fonts you are prioritising in your design. Is the biggest word on the page in a masculine or feminine font? What about the smallest words? Is there an imbalance between the prominence of masculine and feminine fonts, and what does this imply? Typography is a language in and of itself, so be careful what you say with it. Colour me unsurprised Colour also has an obvious gender bias. We associate pinks and purples, especially in combination, with girls and women, and a soft pink has become especially strongly related to breast cancer awareness campaigns. On the other hand, pale blue is strongly associated with boys and men, despite the fact that pastels are usually thought of as more feminine. These associations are getting stronger and stronger as more and more marketers use them to define products as “for girls” and “for boys”, setting expectations from an incredibly young age — children as young as four understand gender stereotypes. It should be obvious that using these highly gender-associated colours sends an incredibly strong message to your visitors about who you think your target audience is. If you want to appeal to both men and women, then avoid pinks and pale blues. But men and women also have different colour preferences. Men tend to prefer intense primary colours and deeper colours (shades), and tolerate greys better, whilst women prefer pastels (tints). When choosing colours, consider not just the hue itself, but also tint, tone and shade. Slightly counterintuitively, everyone likes blue, but no one seems to particularly like brown or orange. A picture is worth a thousand words, or none Stock photos are the quickest and easiest way to add a little humanity to your website, directly illustrating the kind of people you believe are in your audience. But the wrong photo can put a woman off before she’s even read your text. A website about a retirement home will, for example, obviously include photos of older people, and a baby clothes retailer will obviously show photos of babies. But, in the latter case, should they also show only photographs of mothers with their children, or should they include fathers too? It’s true that women take on the majority of childcare responsibilities, but that’s a cultural holdover from a previous era, rather than some rule of law. We are seeing increasing number of stay at home dads as well as single dads, so showing only photographs of women both enforces the stereotype that only women can care, as well as marginalising male carers. Equally, featuring prominent photographs of women on sites about male-dominated topics such as science, technology or engineering help women feel welcomed and appreciated in those fields. Photos really do speak volumes, so make sure that you also represent other marginalised groups, especially ethnic groups. If people do not see themselves represented on your site, they are not going to engage with it as much as they might. Another form of picture that we often ignore is the icon. When you do use icons, make sure that they are gender neutral. For example, avoid using a icon of a man to denote engineers, or of a woman to denote nurses. Avoid overly masculine or feminine metaphors, such as a hammer to denote DIY or a flower to denote gardens. Not only are these gendered, they’re also trite and unappealing, so come up with more exciting and novel metaphors. Use gender-neutral language Last, but not least, be very careful in your use of gender in language. Pronouns are an obvious pitfall. A lot of web content is written in the second person, using the cleary gender neutral ‘you’, but if you have to write in the third person, which uses ‘she’, ‘he’, ‘it’, and ‘they’, then be very careful which pronouns you use. The singular ‘they’ is becoming more widely acceptable, and is a useful gender-neutral option. If you must use generic ‘he’ and ‘she’, (as opposed to talking about a specific person), then vary the order that they come in, so don’t always put the male pronoun first. When you are talking about people, make sure that you use the same level of formality for both men and women. The tendency is to refer to men by their surname and women by their first name so, for example, when people are talking about Ada Lovelace and Charles Babbage, they often talk about “Ada and Babbage”, rather than “Lovelace and Babbage” or “Ada and Charles”. As a rule, it’s best to use people’s surnames in formal and semi-formal writing, and their first names only in very informal writing. It’s also very important to make sure that you respect people’s honorifics, especially academic titles such as Dr or Professor, and that you use titles consistently. Studies show that women and people of colour are the most likely to have their honorifics dropped, which is not only disrespectful, it gives readers the idea that women and people of colour are less qualified than white men. If you mention job titles, avoid old-fashioned gendered titles such as ‘chairman’, and instead look for a neutral version, like ‘chair’ or ‘chairperson’. Where neutral terms have strong gender associations, such as nurse or engineer, take special care that the surrounding text, especially pronouns, is diverse and/or neutral. Do not assume engineers are male and nurses female. More subtle intimations of gender can be found in the descriptors people use. Military metaphors and phrases, out-sized claims, competitive words, and superlatives are masculine, such as ‘ground-breaking’, ‘best’, ‘genius’, ‘world-beating’, or ‘killer’. Excessive unnecessary factual detail is also very masculine. Women tend to relate to more cooperative, non-competitive, future-focused, and warmer language, paired with more general information. Women’s language includes word like ’global’, ‘responsive’, ‘support’, ‘include’, ‘engage’ and ‘imagine’. Focus more on the kind of relationship you can build with your customers, how you can help make their lives easier, and less on your company or product’s status. Smash the patriarchy, one assumption at a time We’re all brought up in a cultural stew that prioritises men’s needs, feelings and assumptions over women’s. This is the patriarchy, and it’s been around for thousands of years. But given women’s purchasing power, adhering to the patriarchy’s norms is unlikely to be good for your business. If you want to tap into the female market, pay attention to the details of your design and content, and make sure that you’re not inadvertently putting women off. A gender neutral website that designs away gender stereotypes will attract both men and women, expanding your market and helping your business flourish. 2017 Suw Charman-Anderson suwcharmananderson 2017-12-20T00:00:00+00:00 https://24ways.org/2017/is-your-website-accidentally-sexist/ content
202 Design Systems and CSS Grid Recently, my client has been looking at creating a few new marketing pages for their website. They currently have a design system in place but they’re looking to push this forward into 2018 with some small and possibly some larger changes. To start with we are creating a couple of new marketing pages. As well as making use of existing components within the design systems component library there are a couple of new components. Looking at the first couple of sketch files I felt this would be a great opportunity to use CSS Grid, to me the newer components need to be laid out on that page and grid would help with this perfectly. As well as this layout of the new components and the text within it, imagery would be used that breaks out of the grid and pushes itself into the spaces where the text is aligned. The existing grid system When the site was rebuilt in 2015 the team decided to make use of Sass and Susy, a “lightweight grid-layout engine using Sass”. It was built separating the grid system from the components that would be laid out on the page with a container, a row, an optional column, and a block. To make use of the grid system on a page for a component that would take the full width of the row you would have to write something like this: <div class="grid-container"> <div class="grid-row"> <div class="grid-column-4"> <div class="grid-block"> <!-- component code here --> </div> </div> </div> </div> Using a grid system similar to this can easily create quite the tag soup. It could fill the HTML full of divs that may become complex to understand and difficult to edit. Although there is this reliance on several <div>s to lay out the components on a page it does allow a tidy way to place the component code within that page. It abstracts the layout of the page to its own code, its own system, so the components can ‘fit’ where needed. The requirements of the new grid system Moving forward I set myself some goals for what I’d like to have achieved in this new grid system: It needs to behave like the existing grid systems We are not ripping up the existing grid system, it would be too much work, for now, to retrofit all of the existing components to work in a grid that has a different amount of columns, and spacing at various viewport widths. Allow full-width components Currently the grid system is a 14 column grid that becomes centred on the page when viewport is wide enough. We have, in the past, written some CSS that would allow for a full-width component, but his had always felt like a hack. We want the option to have a full-width element as part of the new grid system, not something that needs CSS to fight against. Less of a tag soup Ideally we want to end up writing less HTML to layout the page. Although the existing system can be quite clear as to what each element is doing, it can also become a little laborious in working out what each grid row or block is doing where. I would like to move the layout logic to CSS as much as is possible, potentially creating some utility classes or additional ‘layout classes’ for the components. Easier for people to use and author With many people using the existing design systems codebase we need to create a new grid system that is as easy or easier to use than the existing one. I think and hope this would be helped by removing as many <div>s as needed and would require new documentation and examples, and potentially some initial training. Separating layout from style There still needs to be a separation of layout from the styles for the component. To allow for the component itself to be placed wherever needed in the page we need to make sure that the CSS for the layout is a separate entity to the CSS for that styling. With these base requirements I took to CodePen and started working on some throwaway code to get started. Making the new grid(s) The Full-Width Grid To start with I created a grid that had three columns, one for the left, one for the middle, and one for the right. This would give the full-width option to components. Thankfully, one of Rachel Andrew’s many articles on Grid discussed this exact requirement of the new grid system to break out with Grid. I took some of the code in the examples and edited to make grid we needed. .container { display: grid; grid-template-columns: [full-start] minmax(.75em, 1fr) [main-start] minmax(0, 1008px) [main-end] minmax(.75em, 1fr) [full-end]; } We are declaring a grid, we have four grid column lines which we name and we define how the three columns they create react to the viewport width. We have a left and right column that have a minimum of 12px, and a central column with a maximum width of 1008px. Both left and right columns fill up any additional space if the viewport is wider that 1032px wide. We are also not declaring any gutters to this grid, the left and right columns would act as gutters at smaller viewports. At this point I noticed that older versions of Sass cannot parse the brackets in this code. To combat this I used Sass’ unquote method to wrap around the value of the grid-template-column. .container { display: grid; grid-template-columns: unquote(" [full-start] minmax(.75em, 1fr) [main-start] minmax(0, 1008px) [main-end] minmax(.75em, 1fr) [full-end] "); } The existing codebase makes use of Sass variables, mixins and functions so to remove that would be a problem, but luckily the version of Sass used is up-to-date (note: example CodePens will be using CSS). The initial full-width grid displays on a webpage as below: The 14 column grid I decided to work out the 14 column grid as a separate prototype before working out how it would fit within the full-width grid. This grid is very similar to the 12 column grids that have been used in web design. Here we need 14 columns with a gutter between each one. Along with the many other resources on Grid, Mozilla’s MDN site had a page on common layouts using CSS Grid. This gave me the perfect CSS I needed to create my grid and I edited it as required: .inner { display: grid; grid-template-columns: repeat(14, [col-start] 1fr); grid-gap: .75em; } We, again, are declaring a grid, and we are splitting up the available space by creating 14 columns with 1 fr-unit and giving each one a starting line named col-start. This grid would display on web page as below: Bringing the grids together Now that we have got the two grids we need to help fulfil our requirements we need to put them together so that they are actually we we need. The subgrid There is no subgrid in CSS, yet. To workaround this for the new grid system we could nest the 14 column grid inside the full-width grid. In the HTML we nest the 14 column inner grid inside the full-width container. <div class="container"> <div class="inner"> </div> </div> So that the inner knows where to be laid out within the container we tell it what column to start and end with, with this code it would be the start and end of the main column. .inner { display: grid; grid-column: main-start / main-end; grid-template-columns: repeat(14, [col-start] 1fr); grid-gap: .75em; } The CSS for the container remains unchanged. This works, but we have added another div to our HTML. One of our requirements is to try and remove the potential for tag soup. The faux subgrid subgrid I wanted to see if it would be possible to place the CSS for the 14 column grid within the CSS for the full-width grid. I replaced the CSS for the main grid and added the grid-column-gap to the .container. .container { display: grid; grid-gap: .75em; grid-template-columns: [full-start] minmax(.75em, 1fr) [main-start] repeat(14, [col-start] 1fr) [main-end] minmax(.75em, 1fr) [full-end]; } What this gave me was a 16 column grid. I was unable to find a way to tell the main grid, the grid betwixt main-start and main-end to be a maximum of 1008px as required. I trawled the internet to find if it was possible to create our main requirement, a 14 column grid which also allows for full-width components. I found that we could not reverse minmax to minmax(1fr, 72px) as 1fr is not allowed as a minimum if there is a maximum. I tried working out if we could make the min larger than its max but in minmax it would be ignored. I was struggling, I was hoping for a cleaner version of the grid system we currently use but getting to the point where needing that extra <div> would be a necessity. At 3 in the morning, when I was failing to get to sleep, my mind happened upon an question: “Could you use calc?” At some point I drifted back to sleep so the next day I set upon seeing if this was possible. I knew that the maximum width of the central grid needed to be 1008px. The left and right columns needed to be however many pixels were left in the viewport divided by 2. In CSS it looked like I would need to use calc twice. The first time to takeaway 1008px from 100% of the viewport width and the second to divide that result by 2. calc(calc(100% - 1008px) / 2) The CSS above was part of the value that I would need to include in the declaration for the grid. .container { display: grid; grid-gap: .75em; grid-template-columns: [full-start] minmax(calc(calc(100% - 1008px) / 2), 1fr) [main-start] repeat(14, [col-start] 1fr) [main-end] minmax(calc(calc(100% - 1008px) / 2), 1fr) [full-end]; } We have created the grid required. A full-width grid, with a central 14 column grid, using fewer <div> elements. See the Pen Design Systems and CSS Grid, 6 by Stuart Robson (@sturobson) on CodePen. Success! Progressive enhancement Now that we have created the grid system required we need to back-track a little. Not all browsers support Grid, over the last 9 months or so this has gotten a lot better. However there will still be browsers that visit that potentially won’t have support. The effort required to make the grid system fall back for these browsers depends on your product or sites browser support. To determine if we will be using Grid or not for a browser we will make use of feature queries. This would mean that any version of Internet Explorer will not get Grid, as well as some mobile browsers and older versions of other browsers. @supports (display: grid) { /* Styles for browsers that support Grid */ } If a browser does not pass the requirements for @supports we will fallback to using flexbox where possible, and if that is not supported we are happy for the page to be laid out in one column. A website doesn’t have to look the same in every browser after all. A responsive grid We started with the big picture, how the grid would be at a large viewport and the grid system we have created gets a little silly when the viewport gets smaller. At smaller viewports we have a single column layout where every item of content, every component stacks atop each other. We don’t start to define a grid before we the viewport gets to 700px wide. At this point we have an 8 column grid and if the viewport gets to 1100px or wider we have our 14 column grid. /* * to start with there is no 'grid' just a single column */ .container { padding: 0 .75em; } /* * when we get to 700px we create an 8 column grid with * a left and right area to breakout of the grid. */ @media (min-width: 700px) { .container { display: grid; grid-gap: .75em; grid-template-columns: [full-start] minmax(calc(calc(100% - 1008px) / 2), 1fr) [main-start] repeat(8, [col-start] 1fr) [main-end] minmax(calc(calc(100% - 1008px) / 2), 1fr) [full-end]; padding: 0; } } /* * when we get to 1100px we create an 14 column grid with * a left and right area to breakout of the grid. */ @media (min-width: 1100px) { .container { grid-template-columns: [full-start] minmax(calc(calc(100% - 1008px) / 2), 1fr) [main-start] repeat(14, [col-start] 1fr) [main-end] minmax(calc(calc(100% - 1008px) / 2), 1fr) [full-end]; } } Being explicit in creating this there is some repetition that we could avoid, we will define the number of columns for the inner grid by using a Sass variable or CSS custom properties (more commonly termed as CSS variables). Let’s use CSS custom properties. We need to declare the variable first by adding it to our stylesheet. :root { --inner-grid-columns: 8; } We then need to edit a few more lines. First make use of the variable for this line. repeat(8, [col-start] 1fr) /* replace with */ repeat(var(--inner-grid-columns), [col-start] 1fr) Then at the 1100px breakpoint we would only need to change the value of the —inner-grid-columns value. @media (min-width: 1100px) { .container { grid-template-columns: [full-start] minmax(calc(calc(100% - 1008px) / 2), 1fr) [main-start] repeat(14, [col-start] 1fr) [main-end] minmax(calc(calc(100% - 1008px) / 2), 1fr) [full-end]; } } /* replace with */ @media (min-width: 1100px) { .container { --inner-grid-columns: 14; } } See the Pen Design Systems and CSS Grid, 8 by Stuart Robson (@sturobson) on CodePen. The final grid system We have finally created our new grid for the design system. It stays true to the existing grid in place, adds the ability to break-out of the grid, removes a <div> that could have been needed for the nested 14 column grid. We can move on to the new component. Creating a new component Back to the new components we are needing to create. To me there are two components one of which is a slight variant of the first. This component contains a title, subtitle, a paragraph (potentially paragraphs) of content, a list, and a call to action. To start with we should write the HTML for the component, something like this: <article class="features"> <h3 class="features__title"></h3> <p class="features__subtitle"></p> <div class="features__content"> <p class="features__paragraph"></p> </div> <ul class="features__list"> <li></li> <li></li> </ul> <a href="" class="features__button"></a> </article> To place the component on the existing grid is fine, but as child elements are not affected by the container grid we need to define another grid for the features component. As the grid doesn’t get invoked until 700px it is possible to negate the need for a media query. .features { grid-column: col-start 1 / span 6; } @supports (display: grid) { @media (min-width: 1100px) { .features { grid-column-end: 9; } } } We can also avoid duplication of declarations by making use of the grid-column shorthand and longhand. We need to write a little more CSS for the variant component, the one that will sit on the right side of the page too. .features:nth-of-type(even) { grid-column-start: 4; grid-row: 2; } @supports (display: grid) { @media (min-width: 1100px) { .features:nth-of-type(even) { grid-column-start: 9; grid-column-end: 16; } } } We cannot place the items within features on the container grid as they are not direct children. To make this work we have to define a grid for the features component. We can do this by defining the grid at the first breakpoint of 700px making use of CSS custom properties again to define how many columns there will need to be. .features { grid-column: col-start 1 / span 6; --features-grid-columns: 5; } @supports (display: grid) { @media (min-width: 700px) { .features { display: grid; grid-gap: .75em; grid-template-columns: repeat(var(--features-grid-columns), [col-start] 1fr); } } } @supports (display: grid) { @media (min-width: 1100px) { .features { grid-column-end: 9; --features-grid-columns: 7; } } } See the Pen Design Systems and CSS Grid, 10 by Stuart Robson (@sturobson) on CodePen. Laying out the parts Looking at the spec and reading several articles I feel there are two ways that I could layout the text of this component on the grid. We could use the grid-column shorthand that incorporates grid-column-start and grid-column-end or we can make use of grid-template-areas. grid-template-areas allow for a nice visual way of representing how the parts of the component would be laid out. We can take the the mock of the features on the grid and represent them in text in our CSS. Within the .features rule we can add the relevant grid-template-areas value to represent the above. .features { display: grid; grid-template-columns: repeat(var(--features-grid-columns), [col-start] 1fr); grid-template-areas: ". title title title title title title" ". subtitle subtitle subtitle subtitle subtitle . " ". content content content content . . " ". list list list . . . " ". . . . link link link "; } In order to make the variant of the component we would have to create the grid-template-areas for that component too. We then need to tell each element of the component in what grid-area it should be placed within the grid. .features__title { grid-area: title; } .features__subtitle { grid-area: subtitle; } .features__content { grid-area: content; } .features__list { grid-area: list; } .features__link { grid-area: link; } See the Pen Design Systems and CSS Grid, 12 by Stuart Robson (@sturobson) on CodePen. The other way would be to use the grid-column shorthand and the grid-column-start and grid-column-end we have used previously. .features .features__title { grid-column: col-start 2 / span 6; } .features .features__subtitle { grid-column: col-start 2 / span 5; } .features .features__content { grid-column: col-start 2 / span 4; } .features .features__list { grid-column: col-start 2 / span 4; } .features .features__link { grid-column: col-start 5 / span 3; } For the variant of the component we can use the grid-column-start property as it will inherit the span defined in the grid-column shorthand. .features:nth-of-type(even) .features__title { grid-column-start: col-start 1; } .features:nth-of-type(even) .features__subtitle { grid-column-start: col-start 1; } .features:nth-of-type(even) .features__content { grid-column-start: col-start 3; } .features:nth-of-type(even) .features__list { grid-column-start: col-start 3; } .features:nth-of-type(even) .features__link { grid-column-start: col-start 1; } See the Pen Design Systems and CSS Grid, 14 by Stuart Robson (@sturobson) on CodePen. I think, for now, we will go with using grid-column properties rather than grid-template-areas. The repetition needed for creating the variant feels too much where we can change the grid-column-start instead, keeping the components elements layout properties tied a little closer to the elements rather than the grid. Some additional decisions The current component library has existing styles for titles, subtitles, lists, paragraphs of text and calls to action. These are name-spaced so that they shouldn’t clash with any other components. Looking forward there will be a chance that other products adopt the component library, but they may bring their own styles for titles, subtitles, etc. One way that we could write our code now for that near future possibility is to make sure our classes are working hard. Using class-attribute selectors we can target part of the class attributes that we know the elements in the component will have using *=. .features [class*="title"] { grid-column: col-start 2 / span 6; } .features [class*="subtitle"] { grid-column: col-start 2 / span 5; } .features [class*="content"] { grid-column: col-start 2 / span 4; } .features [class*="list"] { grid-column: col-start 2 / span 4; } .features [class*="link"] { grid-column: col-start 5 / span 3; } See the Pen Design Systems and CSS Grid, 15 by Stuart Robson (@sturobson) on CodePen. Although the component we have created have a title, subtitle, paragraphs, a list, and a call to action there may be a time where one ore more of these is not required or available. One thing I found out is that if the element doesn’t exist then grid will not create space for it. This may be obvious, but it can be really helpful in making a nice malleable component. We have only looked at columns, as existing components have their own spacing for the vertical rhythm of the page we don’t really want to have them take up equal space in the component and just take up the space as needed. We can do this by adding grid-auto-rows: min-content; to our .features. This is useful if you also need your component to take up a height that is more than the component itself. The grid of the future From prototyping this new grid and components in CSS Grid, I’ve found it a fantastic way to reimagine how we can create a layout or grid system for our sites. It gives us options to create the same layouts in differing ways that could suit a project and its needs. It allows us to carry on – if we choose to – using a <div>-based grid but swapping out floats for CSS Grid or to tie it to our components so they have specific places to go depending on what component is being used. Or we could have several ‘grid components’ in our design system that we could use to layout various components throughout a page. If you find yourself tasked with creating some new components for your design system try it. If you are starting from scratch I believe you really should start with CSS Grid for your layout. It really feels like the possibilities are endless in terms of layout for the web. Resources Here are just a few resources I have pawed over these last few weeks whilst getting acquainted with CSS Grid. A collection of CodePens from this article Grid by Example from Rachel Andrew A Complete Guide to CSS Grid on Codrops from Hui Jing Chen Rachel Andrew’s Blog Archive tagged: cssgrid CSS Grid Layout Examples MDN’s CSS Grid Layout A Complete Guide to Grid from CSS-Tricks CSS Grid Layout Module Level 1 Specification 2017 Stuart Robson stuartrobson 2017-12-12T00:00:00+00:00 https://24ways.org/2017/design-systems-and-css-grid/ code
157 Capturing Caps Lock One of the more annoying aspects of having to remember passwords (along with having to remember loads of them) is that if you’ve got Caps Lock turned on accidentally when you type one in, it won’t work, and you won’t know why. Most desktop computers alert you in some way if you’re trying to enter your password to log on and you’ve enabled Caps Lock; there’s no reason why the web can’t do the same. What we want is a warning – maybe the user wants Caps Lock on, because maybe their password is in capitals – rather than something that interrupts what they’re doing. Something subtle. But that doesn’t answer the question of how to do it. Sadly, there’s no way of actually detecting whether Caps Lock is on directly. However, there’s a simple work-around; if the user presses a key, and it’s a capital letter, and they don’t have the Shift key depressed, why then they must have Caps Lock on! Simple. DOM scripting allows your code to be notified when a key is pressed in an element; when the key is pressed, you get the ASCII code for that key. Capital letters, A to Z, have ASCII codes 65 to 90. So, the code would look something like: on a key press if the ASCII code for the key is between 65 and 90 *and* if shift is pressed warn the user that they have Caps Lock on, but let them carry on end if end keypress The actual JavaScript for this is more complicated, because both event handling and keypress information differ across browsers. Your event handling functions are passed an event object, except in Internet Explorer where you use the global event object; the event object has a which parameter containing the ASCII code for the key pressed, except in Internet Explorer where the event object has a keyCode parameter; some browsers store whether the shift key is pressed in a shiftKey parameter and some in a modifiers parameter. All this boils down to code that looks something like this: keypress: function(e) { var ev = e ? e : window.event; if (!ev) { return; } var targ = ev.target ? ev.target : ev.srcElement; // get key pressed var which = -1; if (ev.which) { which = ev.which; } else if (ev.keyCode) { which = ev.keyCode; } // get shift status var shift_status = false; if (ev.shiftKey) { shift_status = ev.shiftKey; } else if (ev.modifiers) { shift_status = !!(ev.modifiers & 4); } // At this point, you have the ASCII code in “which”, // and shift_status is true if the shift key is pressed } Then it’s just a check to see if the ASCII code is between 65 and 90 and the shift key is pressed. (You also need to do the same work if the ASCII code is between 97 (a) and 122 (z) and the shift key is not pressed, because shifted letters are lower-case if Caps Lock is on.) if (((which >= 65 && which <= 90) && !shift_status) || ((which >= 97 && which <= 122) && shift_status)) { // uppercase, no shift key /* SHOW THE WARNING HERE */ } else { /* HIDE THE WARNING HERE */ } The warning can be implemented in many different ways: highlight the password field that the user is typing into, show a tooltip, display text next to the field. For simplicity, this code shows the warning as a previously created image, with appropriate alt text. Showing the warning means creating a new <img> tag with DOM scripting, dropping it into the page, and positioning it so that it’s next to the appropriate field. The image looks like this: You know the position of the field the user is typing into (from its offsetTop and offsetLeft properties) and how wide it is (from its offsetWidth properties), so use createElement to make the new img element, and then absolutely position it with style properties so that it appears in the appropriate place (near to the text field). The image is a transparent PNG with an alpha channel, so that the drop shadow appears nicely over whatever else is on the page. Because Internet Explorer version 6 and below doesn’t handle transparent PNGs correctly, you need to use the AlphaImageLoader technique to make the image appear correctly. newimage = document.createElement('img'); newimage.src = "http://farm3.static.flickr.com/2145/2067574980_3ddd405905_o_d.png"; newimage.style.position = "absolute"; newimage.style.top = (targ.offsetTop - 73) + "px"; newimage.style.left = (targ.offsetLeft + targ.offsetWidth - 5) + "px"; newimage.style.zIndex = "999"; newimage.setAttribute("alt", "Warning: Caps Lock is on"); if (newimage.runtimeStyle) { // PNG transparency for IE newimage.runtimeStyle.filter += "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://farm3.static.flickr.com/2145/2067574980_3ddd405905_o_d.png',sizingMethod='scale')"; } document.body.appendChild(newimage); Note that the alt text on the image is also correctly set. Next, all these parts need to be pulled together. On page load, identify all the password fields on the page, and attach a keypress handler to each. (This only needs to be done for password fields because the user can see if Caps Lock is on in ordinary text fields.) var inps = document.getElementsByTagName("input"); for (var i=0, l=inps.length; i The “create an image” code from above should only be run if the image is not already showing, so instead of creating a newimage object, create the image and attach it to the password field so that it can be checked for later (and not shown if it’s already showing). For safety, all the code should be wrapped up in its own object, so that its functions don’t collide with anyone else’s functions. So, create a single object called capslock and make all the functions be named methods of the object: var capslock = { ... keypress: function(e) { } ... } Also, the “create an image” code is saved into its own named function, show_warning(), and the converse “remove the image” code into hide_warning(). This has the advantage that developers can include the JavaScript library that has been written here, but override what actually happens with their own code, using something like: <script src="jscapslock.js" type="text/javascript"></script> <script type="text/javascript"> capslock.show_warning(target) { // do something different here to warn the user } capslock.hide_warning(target) { // hide the warning that we created in show_warning() above } </script> And that’s all. Simply include the JavaScript library in your pages, override what happens on a warning if that’s more appropriate for what you’re doing, and that’s all you need. See the script in action. 2007 Stuart Langridge stuartlangridge 2007-12-04T00:00:00+00:00 https://24ways.org/2007/capturing-caps-lock/ code
203 Jobs-to-Be-Done in Your UX Toolbox Part 1: What is JTBD? The concept of a “job” in “Jobs-To-Be-Done” is neatly encapsulated by a oft-quoted line from Theodore Levitt: “People want a quarter-inch hole, not a quarter inch drill”. Even so, Don Norman pointed out that perhaps Levitt “stopped too soon” at what the real customer goal might be. In the “The Design of Everyday Things”, he wrote: “Levitt’s example of the drill implying that the goal is really a hole is only partially correct, however. When people go to a store to buy a drill, that is not their real goal. But why would anyone want a quarter-inch hole? Clearly that is an intermediate goal. Perhaps they wanted to hang shelves on the wall. Levitt stopped too soon. Once you realize that they don’t really want the drill, you realize that perhaps they don’t really want the hole, either: they want to install their bookshelves. Why not develop methods that don’t require holes? Or perhaps books that don’t require bookshelves.” In other words, a “job” in JTBD lingo is a way to express a user need or provide a customer-centric problem frame that’s independent of a solution. As Tony Ulwick says: “A job is stable, it doesn’t change over time.” An example of a job is “tiding you over from breakfast to lunch.” You could hire a donut, a flapjack or a banana for that mid-morning snack—whatever does the job. If you can arrive at a clearly identified primary job (and likely some secondary ones too), you can be more creative in how you come up with an effective solution while keeping the customer problem in focus. The team at Intercom wrote a book on their application of JTBD. In it, Des Traynor cleverly characterised how JTBD provides a different way to think about solutions that compete for the same job: “Economy travel and business travel are both capable candidates applying for [the job: Get me face-to-face with my colleague in San Francisco], though they’re looking for significantly different salaries. Video conferencing isn’t as capable, but is willing to work for a far smaller salary. I’ve a hiring choice to make.” So far so good: it’s relatively simple to understand what a job is, once you understand how it’s different from a “task”. Business consultant and Harvard professor Clay Christensen talks about the concept of “hiring” a product to do a “job”, and firing it when something better comes along. If you’re a company that focuses solutions on the customer job, you’re more likely to succeed. You’ll find these concepts often referred to as “Jobs-to-be-Done theory”. But the application of Jobs-to-Be-Done theory is a little more complicated; it comprises several related approaches. I particularly like Jim Kalbach’s description of how JTBD is a “lens through which to understand value creation”. But it is also more. In my view, it’s a family of frameworks and methods—and perhaps even a philosophy. Different facets in a family of frameworks JTBD has its roots in market research and business strategy, and so it comes to the research table from a slightly different place compared to traditional UX or design research—we have our roots in human-computer interaction and ergonomics. I’ve found it helpful to keep in mind is that the application of JTBD theory is an evolving beast, so it’s common to find contradictions across different resources. My own use of it has varied from project to project. In speaking to others who have adopted it in different measures, it seems that we have all applied it in somewhat multifarious ways. As we like to often say in interviews: there are no wrong answers. Outcome Driven Innovation Tony Ulwick’s version of the JTBD history began with Outcome Driven Innovation (ODI), and this approach is best outlined in his seminal article published in the Harvard Business Review in 2002. To understand his more current JTBD approach in his new book “Jobs to Be Done: Theory to Practice”, I actually found it beneficial to read his approach in the original 2002 article for a clearer reference point. In the earlier article, Ulwick presented a rigorous approach that combines interviews, surveys and an “opportunity” algorithm—a sequence of steps to determine the business opportunity. ODI centres around working with “desired outcome statements” that you unearth through interviews, followed by a means to quantify the gap between importance and satisfaction in a survey to different types of customers. Since 2008, Ulwick has written about using job maps to make sense of what the customer may be trying to achieve. In a recent article, he describes the aim of the activity is “to discover what the customer is trying to get done at different points in executing a job and what must happen at each juncture in order for the job to be carried out successfully.” A job map is not strictly a journey map, however tempting it is to see it that way. From a UX perspective, is one of many models we can use—and as our research team at Clearleft have found, how we use model can depend on the nature of the jobs we’ve uncovered in interviews and the characteristics of the problem we’re attempting to solve. Figure 1. Universal job map Ulwick’s current methodology is outlined in his new book, where he describes a complete end-to-end process: from customer and competitor research to framing market and product strategy. The Jobs-To-Be-Done Interview Back in 2013, I attended a workshop by Chris Spiek and Bob Moesta from the ReWired Group on JTBD at the behest of a then-MailChimp colleague, and I came away excited about their approach to product research. It felt different from anything I’d done before and for the first time in years, I felt that I was genuinely adding something new to my research toolbox. A key idea is that if you focus on the stories of those who switched to you, and those who switch away from you, you can uncover the core jobs through looking at these opposite ends of engagement. This framework centres around the JTBD interview method, which harnesses the power of a narrative framework to elicit the real reasons why someone “hired” something to do a job—be it something physical like a new coffee maker, or a digital service, such as a to-do list app. As you interview, you are trying to unearth the context around the key moments on the JTBD timeline (Figure 2). A common approach is to begin from the point the customer might have purchased something, back to the point where the thought of buying this thing first occurred to them. Figure 2. JTBD Timeline Figure 3. The Four Forces The Forces Diagram (Figure 3) is a post-interview analysis tool where you can map out what causes customers to switch to something new and what holds them back. The JTBD interview is effective at identifying core and secondary jobs, as well as some context around the user need. Because this method is designed to extract the story from the interviewee, it’s a powerful way to facilitate recall. Having done many such interviews, I’ve noticed one interesting side effect: participants often remember more details later on after the conversation has formally ended. It is worth scheduling a follow-up phone call or keep the channels open. Strengths aside, it’s good to keep in mind that the JTBD interview is still primarily an interview technique, so you are relying on the context from the interviewee’s self-reported perspective. For example, a stronger research methodology combines JTBD interviews with contextual research and quantitative methods. Job Stories Alan Klement is credited for coming up with the term “job story” to describe the framing of jobs for product design by the team at Intercom: “When … I want to … so I can ….” Figure 4. Anatomy of a Job Story Unlike a user story that traditionally frames a requirement around personas, job stories frame the user need based on the situation and context. Paul Adams, the VP of Product at Intercom, wrote: “We frame every design problem in a Job, focusing on the triggering event or situation, the motivation and goal, and the intended outcome. […] We can map this Job to the mission and prioritise it appropriately. It ensures that we are constantly thinking about all four layers of design. We can see what components in our system are part of this Job and the necessary relationships and interactions required to facilitate it. We can design from the top down, moving through outcome, system, interactions, before getting to visual design.” Systems of Progress Apart from advocating using job stories, Klement believes that a core tenet of applying JTBD revolves around our desire for “self-betterment”—and that focusing on everyone’s desire for self-betterment is core to a successful strategy. In his book, Klement takes JTBD further to being a tool for change through applying systems thinking. There, he introduces the systems of progress and how it can help focus product strategy approach to be more innovative. Coincidentally, I applied similar thinking on mapping systemic change when we were looking to improve users’ trust with a local government forum earlier this year. It’s not just about capturing and satisfying the immediate job-to-be-done, it’s about framing the job so that you can a clear vision forward on how you can help your users improve their lives in the ways they want to. This is really the point where JTBD becomes a philosophy of practice. Part 2: Mixing It Up There has been some misunderstanding about how adopting JTBD means ditching personas or some of our existing design tools or research techniques. This couldn’t have been more wrong. Figure 5: Jim Kalbach’s JTBD model Jim Kalbach has used Outcome-Driven Innovation for around 10 years. In a 2016 article, he presents a synthesised model of how to think about that has key elements from ODI, Christensen’s theories and the structure of the job story. More interestingly, Kalbach has also combined the use of mental models with JTBD. Claire Menke of UDemy has written a comprehensive article about using personas, JTBD and customer journey maps together in order to communicate more complete story from the users’ perspective. Claire highlights an especially interesting point in her article as she described her challenges: “After much trial and error, I arrived at a foundational research framework to suit every team’s needs — allowing everyone to share the same holistic understanding, but extract the type of information most applicable to their work.” In other words, the organisational context you are in likely can dictate what works best—after all the goal is to arrive at the best user experience for your audiences. Intercom can afford to go full-on on applying JTBD theory as a dominant approach because they are a start-up, but a large company or organisation with multiple business units may require a mix of tools, outputs and outcomes. JTBD is an immensely powerful approach on many fronts—you’ll find many different references that lists the ways you can apply JTBD. However, in the context of this discussion, it might also be useful to we examine where it lies in our models of how we think about our UX and product processes. JTBD in the UX ecosystem Figure 6. The Elements of User Experience (source) There are many ways we have tried to explain the UX discipline but I think Jesse James Garrett’s Elements of User Experience is a good place to begin. I sometimes also use little diagram to help me describe the different levels you might work at when you work through the complexity of designing and developing a product. A holistic UX strategy needs to address all the different levels for a comprehensive experience: your individual product UI, product features, product propositions and brand need to have a cohesive definition. Figure 7. Which level of product focus? We could, of course, also think about where it fits best within the double diamond. Again, bearing in mind that JTBD has its roots in business strategy and market research, it is excellent at clarifying user needs, defining high-level specifications and content requirements. It is excellent for validating brand perception and value proposition —all the way down to your feature set. In other words, it can be extremely powerful all the way through to halfway of the second diamond. You could quite readily combine the different JTBD approaches because they have differences as much as overlaps. However, JTBD generally starts getting a little difficult to apply once we get to the details of UI design. The clue lies in JTBD’s raison d’être: a job statement is solution independent. Hence, once we get to designing solutions, we potentially fall into a existential black hole. That said, Jim Kalbach has a quick case study on applying JTBD to content design tucked inside the main article on a synthesised JTBD model. Alan Klement has a great example of how you could use UI to resolve job stories. You’ll notice that the available language of “jobs” drops off at around that point. Job statements and outcome statements provide excellent “mini north-stars” as customer-oriented focal points, but purely satisfying these statements would not necessarily guarantee that you have created a seamless and painless user experience. Playing well with others You will find that JTBD plays well with Lean, and other strategy tools like the Value Proposition Canvas. With every new project, there is potential to harness the power of JTBD alongside our established toolbox. When we need to understand complex contexts where cultural or socioeconomic considerations have to be taken into account, we are better placed with combining JTBD with more anthropological approaches. And while we might be able to evaluate if our product, website or app satisfies the customer jobs through interviews or surveys, without good old-fashioned usability testing we are unlikely to be able to truly validate why the job isn’t being represented as it should. In this case, individual jobs solved on the UI can be set up as hypotheses to be proven right or wrong. The application of Jobs-to-be-Done is still evolving. I’ve found it to be very powerful and I struggle to remember what my UX professional life was like before I encountered it—it has completely changed my approach to research and design. The fact JTBD is still evolving as a practice means we need to be watchful of dogma—there’s no right way to get a UX job done after all, it nearly always depends. At the end of the day, isn’t it about having the right tool for the right job? 2017 Steph Troeth stephtroeth 2017-12-04T00:00:00+00:00 https://24ways.org/2017/jobs-to-be-done-in-your-ux-toolbox/ ux
88 Think First, Code Later This is a story that’s best told from the end, and it’s probably one you’re all familiar with. You, or someone just like you, have been building a website, probably as part of a skilled and capable team. You’re a front-end developer, focusing on JavaScript – it’s either your sole responsibility or shared around. It’s quite a big job, been going on for months, and at last it feels like you’re reaching the end of it. But, in a brief moment of downtime, you step back and take a look at the code as a whole. You notice that the folder called “jQuery plugins” suddenly looks rather full, and maybe there’s evidence of several methods of doing the same thing; there are loads of little niggly fixes in the bug tracker; and every place you use Ajax the structure of the data is slightly different. You sigh, and your shoulders droop slightly, and you think “Yeah, we’ll do that more cleanly next time.” The thing is, you probably already know how to rewrite the start of this story to make the ending work better. This situation is not really anyone’s fault – it’s just an accumulation of all the things you decided along the way, all the things you agreed you’d fix later that have disappeared into the black hole of technical debt, and accomodating all the “can we just…?” requests from around the team and the client. So, the solution to this is easy, right? More interminable planning meetings, more tightly controlled and documented specifications, less freedom to innovate, to try out new ideas and enjoy what you’re doing. Wait, that sounds even less fun than the old way. Minimum viable planning Actually, planning and specifications are exactly what you need, but the way you go about them can make a real difference, both to the quality of your code, and the quality of your life as a developer. It can be as simple as being a little more thoughtful before starting on any new piece of functionality. Involve your whole team if possible, or at least those working on what you’re doing. Canvass opinions and work out what the solution to the problem might look like first, rather than coding speculatively to find out. There are easy ways you can get into this habit of putting the thought and design up front, and it doesn’t have to mean spending more time on the project as a whole. It also doesn’t have to result in reams of functional specifications. Instead, let the code itself form the specification. As JavaScript applications become more complex, unit testing is becoming ever more important. So embrace it, whether you prefer QUnit, or Mocha, or any of the other JavaScript testing frameworks out there. The TDD (or test-driven development) pattern is all about writing the tests first and then writing functional code to pass those tests; or, if you prefer, code that meets the specification given by the tests. Sounds like a hassle at first, but once you get into the rhythm of it you should find that the time spent writing tests up front is no greater, and often significantly less, than the time you would have spent fixing bugs afterwards. If what you’re working on requires an API between client and server (usually Ajax but this can apply to any method of sending or receiving data) then spend a bit of time with the back-end developer to design the data contracts, before either of you cut any code. Work out what the API endpoints are going to be, and what the data structure you’ll get back from a certain endpoint looks like. A mock JSON object documented on a wiki is enough and it can be atomic. Don’t worry about planning the entire project at once, just plan enough to get on with your current tasks. Definition in this way doesn’t have to make your API immutable – change is still fine – but if you know roughly where you’re heading, then not only can your team’s efforts become more parallel, but you’re far more likely to have an easier time making it all work. And again, you have a specification – the shape of the data – to write your JavaScript against. Putting everything together, you end up with a logical flow of development, from the specification agreed with the client (your backlog), to the specification agreed with your team (the API contract design), to the specification agreed with your code (your unit tests). Hopefully, there will be ample clues in all of this to inform your front-end library choices, because by then you should have a better picture of what you’re going to need. What the framework? As a JavaScript developer predominantly, these are the choices I’m particularly interested in – how and why you use JavaScript libraries and frameworks, both what you expect from them and what you actually get. If we look back at how web development, and specifically JavaScript development has progressed – from the earliest days of using lines and lines of Dreamweaver code-barf to make an image rollover effect, to today’s large frameworks that handle working with the DOM, Ajax communication and visual effects all in one hit – the purpose of it is clear: to smooth over the inconsistent bumps between browsers and give a solid, reliable, predictable base on which to put our desired functionality. Understanding what we expect the language as a specification to do, and matching that to what we observe browsers actually doing, and then smoothing out the differences, is a big job. Since the language and the implementations are also changing as we go along, it also feels like a never-ending job. So make full use of this valuable effort. Use jQuery or YUI or anything else you’re comfortable with, but it still pays to think early on about what you need your library to do and what the best choice is to meet that need. I’ve come in to projects as a fixer and found, to take a recent example, that jQuery UI was being used just to provide a date picker and a modal effect. That’s a lot of code weight to provide two fairly simple pieces of functionality that could easily be covered by smaller plugins. Which isn’t to say that jQuery UI itself is a bad choice, but I could see that it had been included late on just to do those things, whereas a more considered approach would have been to put the library in early and use it more universally. There are other choices, too. If you automatically throw in jQuery (or whatever your favourite main library is) to a small site with limited functionality, you might only touch a tiny fraction of its scope. In my own development I started looking at what I actually needed from a JavaScript library. For a simple project like What the Framework?, all jQuery needed to do was listen for .ready() and then perform some light DOM selection before handing over to a client-side MVC framework. So perhaps there was another way to go about this while still avoiding the cross-browser headaches. Deleting jQuery But the jQuery pattern is compelling and familiar. And once you’re comfortable with something, it’s a bit of an effort to force yourself out of that comfort zone and learn. But looking back at my whole career, I realised that I’ve relearned pretty much everything I do, probably several times, since I started out. So it’s worth keeping in mind that learning and trying new things is how development has advanced to where it is now, and how it will keep advancing in the future. In the end this lead me to Ender, which is billed as an NPM-style package manager for the browser, letting you search for and manage small, loosely coupled modules and their dependencies, and compile them to one file with a common API. For What the Framework I ended up with a set of DOM tools, Underscore and Knockout, all minified into 25kb of JavaScript. This compares really well with 32kb minified for jQuery on its own, and Ender’s use of the dollar variable and the jQuery-like syntax in many modules makes switching over a low-friction experience. On more complex projects, where you’re really going to use all the features of something like jQuery, but want to minimise the loading of other dependencies when you don’t need them, I’ve recently started looking at Jam. This uses the RequireJS pattern to compile commonly used code into a library file and then manage dependencies and bring in others on a per-page basis depending on how you need it. Again, it all comes down to thinking about what you need and using it only when you need it. And the configurability of tools like Ender or Jam allow you to be responsive to changing requirements as your project grows. There is no right answer That’s not to say this way of working automatically makes things easier. It doesn’t. On a large, long-running project or one where future functionality is unknown, it’s still hard to predict and plan for everything – at least until crystal balls as a service come about. But by including strong engineering practices in your front-end, and trying to minimise technical debt, you’re at least giving yourself a decent safety net to guard against the “can we just…?” tendencies that are a fact of life. So, really, this is not an advocation of using a particular technology or framework, because I can’t tell you what works for you or your team. But what I can tell you is that working this way round has done wonders for my productivity and enthusiasm, both for code quality and for trying out new libraries. Give it a go, you might like it! 2012 Stephen Fulljames stephenfulljames 2012-12-07T00:00:00+00:00 https://24ways.org/2012/think-first-code-later/ process
201 Lint the Web Forward With Sonarwhal Years ago, when I was in a senior in college, much of my web development courses focused on two things: the basics like HTML and CSS (and boy, do I mean basic), and Adobe Flash. I spent many nights writing ActionScript 3.0 to build interactions for the websites that I would add to my portfolio. A few months after graduating, I built one website in Flash for a client, then never again. Flash was dying, and it became obsolete in my résumé and portfolio. That was my first lesson in the speed at which things change in technology, and what a daunting realization that was as a new graduate looking to enter the professional world. Now, seven years later, I work on the Microsoft Edge team where I help design and build a tool that would have lessened my early career anxieties: sonarwhal. Sonarwhal is a linting tool, built by and for the web community. The code is open source and lives under the JS Foundation. It helps web developers and designers like me keep up with the constant change in technology while simultaneously teaching how to code better websites. Introducing sonarwhal’s mascot Nellie Good web development is hard. It is more than HTML, CSS, and JavaScript: developers are expected to have a grasp of accessibility, performance, security, emerging standards, and more, all while refreshing this knowledge every few months as the web evolves. It’s a lot to keep track of.   Web development is hard Staying up-to-date on all this knowledge is one of the driving forces for developing this scanning tool. Whether you are just starting out, are a student, or you have over a decade of experience, the sonarwhal team wants to help you build better websites for all browsers. Currently sonarwhal checks for best practices in five categories: Accessibility, Interoperability, Performance, PWAs, and Security. Each check is called a “rule”. You can configure them and even create your own rules if you need to follow some specific guidelines for your project (e.g. validate analytics attributes, title format of pages, etc.). You can use sonarwhal in two ways: An online version, that provides a quick and easy way to scan any public website. A command line tool, if you want more control over the configuration, or want to integrate it into your development flow. The Online Scanner The online version offers a streamlined way to scan a website; just enter a URL and you will get a web page of scan results with a permalink that you can share and revisit at any time. The online version of sonarwal When my team works on a new rule, we spend the bulk of our time carefully researching each subject, finding sources, and documenting it rather than writing the rule’s code. Not only is it important that we get you the right results, but we also want you to understand why something is failing. Next to each failing rule you’ll find a link to its detailed documentation, explaining why you should care about it, what exactly we are testing, examples that pass and examples that don’t, and useful links to even more in-depth documentation if you are interested in the subject. We hope that between reading the documentation and continued use of sonarwhal, developers can stay on top of best practices. As devs continue to build sites and identify recurring issues that appear in their results, they will hopefully start to automatically include those missing elements or fix those pieces of code that are producing errors. This also isn’t a one-way communication: the documentation is not only available on the sonarwhal site, but also on GitHub for editing so you can help us make it even better! A results report The current configuration for the online scanner is very strict, so it might hurt your feelings (it did when I first tested it on my personal website). But you can configure sonarwhal to any level of strictness as well as customize the command line tool to your needs! Sonarwhal’s CLI  The CLI gives you full control of sonarwhal: what rules to use, tweaks to them, domains that are out of your control, and so on. You will need the latest node LTS (v8) or Stable (v9) and your favorite package manager, such as npm: npm install -g sonarwhal You can now run sonarwhal from anywhere via: sonarwhal https://example.com Using the CLI The configuration is done via a .sonarwhalrc file. When analyzing a site, if no file is available, you will be prompted to answer a series of questions: What connector do you want to use? Connectors are what sonarwhal uses to access a website and gather all the information about the requests, resources, HTML, etc. Currently it supports jsdom, Microsoft Edge, and Google Chrome. What formatter? This is how you want to see the results: summary, stylish, etc. Make sure to look at the full list. Some are concise for, perfect for a quick build assessment, while others are more verbose and informative. Do you want to use the recommended rules configuration? Rules are the things we are validating. Unless you’ve read the documentation and know what you are doing, first timers should probably use the recommended configuration. What browsers are you targeting? One of the best features of sonarwhal is that rules can adapt their feedback depending on your targeted browsers, suggesting to add or remove things. For example, the rule “Highest Document Mode” will tell you to add the “X-UA-Compatible” header if IE10 or lower is targeted or remove if the opposite is true. sonarwhal configuration generator questions Once you answer all these questions the scan will start and you will have a .sonarwhalrc file similar to the following: { "connector": { "name": "jsdom", "options": { "waitFor": 1000 } }, "formatters": "stylish", "rulesTimeout": 120000, "rules": { "apple-touch-icons": "error", "axe": "error", "content-type": "error", "disown-opener": "error", "highest-available-document-mode": "error", "validate-set-cookie-header": "warning", // ... } } You should see the scan initiate in the command line and within a few seconds the results should start to appear. Remember, the scan results will look different depending on which formatter you selected so try each one out to see which one you like best. sonarwhal results on my website and hurting my feelings 💔 Now that you have a list of errors, you can get to work improving the site! Note though, that when you scan your website, it scans all the resources on that page and if you’ve added something like analytics or fonts hosted elsewhere, you are unable to change those files. You can configure the CLI to ignore files from certain domains so that you are only getting results for files you are in control of. The documentation should give enough guidance on how to fix the errors, but if it’s insufficient, please help us and suggest edits or contribute back to it. This is a community effort and chances are someone else will have the same question as you. When I scanned both my websites, sonarwhal alerted me to not having an Apple Touch Icon. If I search on the web as opposed to using the sonarwhal documentation, the first top 3 results give me outdated information: I need to include many different icon sizes. I don’t need to include all the different size icons that target different devices. Declaring one icon sized 180px x 180px will provide a large enough icon for devices and it will scale down as appropriate for people on older devices. The information at the top of the search results isn’t always the correct answer to an issue and we don’t want you to have to search through outdated documentation. As sonarwhal’s capabilities expand, the goal is for it to be the one stop shop for helping preflight your website. The journey up until now and looking forward On the Microsoft Edge team, we’re passionate about empowering developers to build great websites. Every day we see so many sites come through our issue tracker. (Thanks for filing those bugs, they help us make Microsoft Edge better and better!) Some issues we see over and over are honest mistakes or outdated ‘best practices’ that could be avoided, so we built this tool to help everyone help make the web a better place. When we decided to create sonarwhal, we wanted to create a tool that would help developers write better and more up-to-date code for their websites. We want sonarwhal to be useful to anyone so, early on, we defined three guiding principles we’ve used along the way: Community Driven. We build for the community’s best interests. The web belongs to everyone and this project should too. Not only is it open source, we’ve also donated it to the JS Foundation and have an inclusive governance model that welcomes the collaboration of anyone, individual or company. User Centric. We want to put the user at the center, making sonarwhal configurable for your needs and easy to use no matter what your skill level is. Collaborative. We didn’t want to reinvent the wheel, so we collaborated with existing tools and services that help developers build for the web. Some examples are aXe, snyk.io, Cloudinary, etc. This is just the beginning and we still have lots to do. We’re hard at work on a backlog of exciting features for future releases, such as: New rules for a variety of areas like performance, accessibility, security, progressive web apps, and more. A plug-in for Visual Studio Code: we want sonarwhal to help you write better websites, and what better moment than when you are in your editor. Configuration options for the online service: as we fine tune the infrastructure, the rule configuration for our scanner is locked, but we look forward to adding CLI customization options here in the near future. This is a tool for the web community by the web community so if you are excited about sonarwhal, making a better web, and want to contribute, we have a few issues where you might be able to help. Also, don’t forget to check the rest of the sonarwhal GitHub organization. PRs are always welcome and appreciated! Let us know what you think about the scanner at @NarwhalNellie on Twitter and we hope you’ll help us lint the web forward! 2017 Stephanie Drescher stephaniedrescher 2017-12-02T00:00:00+00:00 https://24ways.org/2017/lint-the-web-forward-with-sonarwhal/ code
43 Content Production Planning While everyone agrees that getting the content of a website right is vital to its success, unless you’re lucky enough to have an experienced editor or content strategist on board, planning content production often seems to fall through the cracks. One reason is that, for most of the team, it feels like someone else’s problem. Not necessarily a specific person’s problem. Just someone else’s. It’s only when everyone starts urgently asking when the content is going to be ready, that it becomes clear the answer is, “Not as soon as we’d like it”. The good news is that there are some quick and simple things you can do, even if you’re not the official content person on a project, to get everyone on the same content planning page. Content production planning boils down to answering three deceptively simple questions: What content do you need? How much of it do you need? Who’s going to make it? Even if it’s not your job to come up with the answers, by asking these questions early enough and agreeing who is going to come up with the answers, you’ll be a long way towards avoiding the last-minute content problems which so often plague projects. How much content do we need? People tend to underestimate two crucial things about content: how much content they need, and how long that content takes to produce. When I ask someone how big their website is – how many pages it contains – I usually double or triple the answer I get. That’s because almost everyone’s mental model of their website greatly underestimates its true size. You can see the problem for yourself if you look at a site map. Site maps are great at representing a mental model of a website. But because they’re a deliberate simplification they naturally lead us to underestimate how much content is involved in populating them. Several years ago I was asked to help a client create a new microsite (their word) which they wanted ready in two weeks for a conference they were attending. Here’s the site map they had in mind. At first glance it looks like a pretty small website. Maybe twenty to thirty pages? That’s what the client thought. But see those boxes which are multiple boxes stacked on top of one another, for product categories, descriptions and supporting material? They’re known as page stacks, and page stacks are the content strategy equivalent of Here Be Dragons. Say we have: five product categories each with five products which all have two or three supporting documents Those are still fairly small numbers. But small numbers multiplied by other small numbers tend to lead to big numbers. 5 categories = 5 category descriptions plus 5 categories × 5 products each = 25 product descriptions plus 25 products × 2.5 (average) supporting documents = 63 supporting documents equals 93 pages Suddenly our twenty- or thirty-page website is running towards one hundred. That’s probably enough to get most project teams to sit up and take notice. But there’s still the danger of underestimating how long it’s going to take to create the content. After all, assuming the supporting documents already exist in some form, there are only about twenty-five to thirty pages of new copy to write. How much work is it? Again, we have the problem that small numbers when multiplied by other small numbers tend to lead to big numbers. Let’s make a rough guess that it’ll take four hours to write each product category and description page we need. That feels a little conservative if we’re writing stuff from scratch, but assuming the person doing it already knows the products fairly well it’s not unreasonable. 30 pages × 4 hours each = 120 hours 120 hours ÷ 7.5 working hours a day = 16 days Ouch. At this point it’s pretty clear we’re not getting this site launched in two weeks. The goal is the conversation By breaking down the site into its content components, and putting some rough estimates on how long each might take to produce, the client instantly realised that there was no way they would be ready to launch it in two weeks. Although we still didn’t know exactly when it would be ready, getting to that realisation right at the start of the project was a major win for everybody. Without it, the design agency would have bust a gut to get the design, front-end and CMS all done in double-quick time, only to find it was all for nothing as barely half the content was ready. As it was, an early discussion about content, albeit a brief one, bought everyone time to tackle the project properly, without pulling any long nights or working weekends. If you haven’t been able to get people to discuss content plans for the project, these kinds of rough estimates should give you enough evidence to get everyone to start taking it seriously. Your goal is to get everyone on the project to a place where they are ready to talk in detail about who is going to create this content, and how long it’s really going to take them, and to get to those conversations before lack of content becomes a problem. Be careful though. It’s best to talk in ranges and round numbers when your estimates are this uncertain. And watch those multipliers. Given small numbers multiplied by other small numbers lead to big numbers, changing just one number can greatly change the overall estimate. I like to run a couple of different scenarios to check what things look like if I’ve under- or overestimated either how many pages we’re going to need, or how long they’re going to take to create. For example: Top end: 30 pages × 5 hours = 150 hours, or 20 days Bottom end: 25 pages × 4 hours = 100 hours, or 13.3 days So rather than say, “I estimate the content will take around sixteen days to produce”, I’m going to say, “I think the content will take about three to four weeks to produce”. Even with qualifiers like estimate and around, sixteen days sounds too precise. Whereas three to four weeks instantly conveys that this is just a rough figure. Who’s going to make it? So, people tend to underestimate two crucial things about content: how much content they need, and how long content takes to write. At this stage, you’re still in danger of the latter, because it’s tempting to simply estimate how much time content takes to write (or record, if we’re talking audio or visual content), and overlook all the other work that needs to goes on around it. Take 24 ways as an example. In terms of our three deceptively simple questions: what is practical articles about web design; how many is twenty-four, one for each day of Advent; and who are experts working on the web, one to write each article. But there’s another who you might not have considered. Someone needs to select those authors in the first place, make sure they deliver their articles on time (and find someone to replace them if they don’t), review drafts, copy-edit and proofread final versions, upload them to the site, promote them, keep an eye on the comments and make sure there are still presents under the tree on Christmas morning. Even if each of those tasks only takes an hour or so, it then needs multiplying by twenty-four (except the presents, obviously). And as we’ve already seen, small numbers multiplied by small numbers quickly turn into much bigger numbers. Just a few hours per article, when multiplied by twenty-four articles, easily multiplies up to days or even weeks of effort. To get a more accurate estimate of how long the different kinds of content are going to take, you need to break down the content production work into its constituent stages, starting with planning, moving on through the main work of creation, to reviewing, approvals and finally publishing. You need to think about who needs to be involved at each step, and how much time they’ll need to do their bit. Taken together, these things make up your content workflow. The workflow will be different for each organisation, but might look something like this: Eddie the web editor will work out the key messages and objectives for each page, and agree them with Mo the marketing director. Eddie will then get Cal, the copywriter, to write the first draft. As part of that, Cal will interview Sam the subject expert to understand the intricacies of the subject and get all the facts straight. Once Cal’s done the first draft, it’ll go to Sam to check for accuracy, while Eddie reviews it for style and message. Once Cal has incorporated their feedback it’s time to get Mo to have a look at the final draft. If Mo’s happy, it’ll get a final proofread, be uploaded to the CMS, and Mo will give the final sign-off and release it for publishing. You can plot this on a table, with the stages of the content production process down the side, and the key roles or personnel along with top. Then the team can estimate how much time they think each of them needs at each stage. Mo (marketing director) Sam (subject expert) Eddie (web editor) Cal (copywriter) Outline: define key messages and objectives 30 min Review outline 15 min First draft 30 min 3 hours Review 1st draft 30 min 30 min 2nd draft 1 hour Review 2nd draft 15 min 15 min 15 min Final amendments 30 min Proofread 15 min Upload 15 min Sign-off 10 min TOTAL 40 min 1 hour 15 min 1 hour 30 min 4 hours 45 min You can then bring out your calculator again, and come up with some more big scary numbers showing how much time it’s going to take for the whole team to get all the content needed not just written, but also planned, reviewed, approved and published. With an experienced team you can run this exercise as a group workshop and get some fairly accurate estimates pretty quickly. If this is all a bit new to you, check out Gather Content’s Content Production Planning for Agencies ebook for a useful guide to common content roles, ballpark estimates for how much time each one needs on a typical piece of content, and how to run a process and estimating workshop to dig into them in more detail. On a small team, one person might play many roles, but you should still sanity-check your estimates by breaking down the process and putting a rough estimate on each stage. With only a couple of people involved, it’s even easier to only include the core activity like writing or recording in your estimates, and forget to allow time for the planning, reviewing, proofreading, publishing and promoting you’ll still need to do. And even in a team of one, if at all possible you should find at least one other person to act as a second pair of eyes, and give anything you produce a quick once-over and proofread before it’s published. Depending on the kind of content you’re making, you should also consider what will happen after it’s published. The full content life cycle should include promotion, monitoring and regular reviews to make sure content stays accurate and up to date. Making sure you have the time and resources available to do all those things for each piece of content is essential for creating a sustainable content programme. The proof of the pudding Even after digging into workflow and getting the whole team involved in estimating, you’re still largely in the realm of the guesstimate. The good news, though, is that you can quite quickly start finding out if your guesstimates are right or not. As soon as you can, pilot the production process with some real content. This is a double-win: you start finding out how long it really takes to produce all this fab new content, and you get real content to work with in designs and prototypes. Once you’ve run a few things through your process, you’ll be able to refine your estimates, confirm your workflow, and give everyone involved a clear idea of when it will all be ready, and what you need from them. Keeping it all on track At this point I like to pull everything together into the content strategist’s favourite tool: the spreadsheet. A simple content production checklist is a bit like a content inventory or audit, but for the content you don’t yet have, not the stuff already done. You can grab an example here. Each piece of content gets its own row, with columns for basic information like page title, ID (which should match the site map), and who’s responsible for making it. You can capture simple details like target audience and key messages here too, though for more complex content, page description tables like those described by Relly Annett-Baker in “Extracting the Content” may be a better tool to use. Just adapt these columns to whatever makes sense for your content. I then have columns to track where each piece is in the production process. I usually keep this simple, with a column each to mark whether it’s draft, final or uploaded. The status column on the left automatically shows the item’s status, using a simple traffic light colour scheme for whether the item is still to do (red), in draft (amber), or done (green). Seeing the whole thing slowly turn from red to green is a nice motivator. If you want to track the workflow in more detail, a kanban board in a tool like Trello is a great way for a team to collaborate on content production, track each item’s progress, and keep an eye out for bottlenecks and delays. Getting to the content strategy conversation It’s a relatively simple exercise, then, to decide not just what kinds of pages you need, but also how many of them: put some rough estimates of effort on the tasks needed to create those pages – not just the writing, but all the other stages of planning, reviewing, approving, publishing and promoting – and then multiply all those things together. This will quickly bring some reality to grand visions and overambitious plans. Do it early enough, and even when the final big scary number is a lot bigger and scarier than everyone thought, you’ll still have time to do something about it. As well as getting everyone on board for some proper content planning activities, that big scary number is your opportunity to get to the real core questions of content strategy: do we really need all this content? Where can existing content be reused and repurposed? How do we prioritise our efforts? What really matters to our readers and users? Time and again, case studies show that less content delivers more: more leads, more sales, more self-service support and savings in the call centre. Although that argument is primarily one you should make from a good-for-the-users perspective, it doesn’t hurt to be able to make it from the cheaper-for-the-business perspective as well, and to have some big scary numbers to back that up. 2014 Sophie Dennis sophiedennis 2014-12-17T00:00:00+00:00 https://24ways.org/2014/content-production-planning/ content
168 Unobtrusively Mapping Microformats with jQuery Microformats are everywhere. You can’t shake an electronic stick these days without accidentally poking a microformat-enabled site, and many developers use microformats as a matter of course. And why not? After all, why invent your own class names when you can re-use pre-defined ones that give your site extra functionality for free? Nevertheless, while it’s good to know that users of tools such as Tails and Operator will derive added value from your shiny semantics, it’s nice to be able to reuse that effort in your own code. We’re going to build a map of some of my favourite restaurants in Brighton. Fitting with the principles of unobtrusive JavaScript, we’ll start with a semantically marked up list of restaurants, then use JavaScript to add the map, look up the restaurant locations and plot them as markers. We’ll be using a couple of powerful tools. The first is jQuery, a JavaScript library that is ideally suited for unobtrusive scripting. jQuery allows us to manipulate elements on the page based on their CSS selector, which makes it easy to extract information from microformats. The second is Mapstraction, introduced here by Andrew Turner a few days ago. We’ll be using Google Maps in the background, but Mapstraction makes it easy to change to a different provider if we want to later. Getting Started We’ll start off with a simple collection of microformatted restaurant details, representing my seven favourite restaurants in Brighton. The full, unstyled list can be seen in restaurants-plain.html. Each restaurant listing looks like this: <li class="vcard"> <h3><a class="fn org url" href="http://www.riddleandfinns.co.uk/">Riddle & Finns</a></h3> <div class="adr"> <p class="street-address">12b Meeting House Lane</p> <p><span class="locality">Brighton</span>, <abbr class="country-name" title="United Kingdom">UK</abbr></p> <p class="postal-code">BN1 1HB</p> </div> <p>Telephone: <span class="tel">+44 (0)1273 323 008</span></p> <p>E-mail: <a href="mailto:info@riddleandfinns.co.uk" class="email">info@riddleandfinns.co.uk</a></p> </li> Since we’re dealing with a list of restaurants, each hCard is marked up inside a list item. Each restaurant is an organisation; we signify this by placing the classes fn and org on the element surrounding the restaurant’s name (according to the hCard spec, setting both fn and org to the same value signifies that the hCard represents an organisation rather than a person). The address information itself is contained within a div of class adr. Note that the HTML <address> element is not suitable here for two reasons: firstly, it is intended to mark up contact details for the current document rather than generic addresses; secondly, address is an inline element and as such cannot contain the paragraphs elements used here for the address information. A nice thing about microformats is that they provide us with automatic hooks for our styling. For the moment we’ll just tidy up the whitespace a bit; for more advanced style tips consult John Allsop’s guide from 24 ways 2006. .vcard p { margin: 0; } .adr { margin-bottom: 0.5em; } To plot the restaurants on a map we’ll need latitude and longitude for each one. We can find this out from their address using geocoding. Most mapping APIs include support for geocoding, which means we can pass the API an address and get back a latitude/longitude point. Mapstraction provides an abstraction layer around these APIs which can be included using the following script tag: <script type="text/javascript" src="http://mapstraction.com/src/mapstraction-geocode.js"></script> While we’re at it, let’s pull in the other external scripts we’ll be using: <script type="text/javascript" src="jquery-1.2.1.js"></script> <script src="http://maps.google.com/maps?file=api&v=2&key=YOUR_KEY" type="text/javascript"></script> <script type="text/javascript" src="http://mapstraction.com/src/mapstraction.js"></script> <script type="text/javascript" src="http://mapstraction.com/src/mapstraction-geocode.js"></script> That’s everything set up: let’s write some JavaScript! In jQuery, almost every operation starts with a call to the jQuery function. The function simulates method overloading to behave in different ways depending on the arguments passed to it. When writing unobtrusive JavaScript it’s important to set up code to execute when the page has loaded to the point that the DOM is available to be manipulated. To do this with jQuery, pass a callback function to the jQuery function itself: jQuery(function() { // This code will be executed when the DOM is ready }); Initialising the map The first thing we need to do is initialise our map. Mapstraction needs a div with an explicit width, height and ID to show it where to put the map. Our document doesn’t currently include this markup, but we can insert it with a single line of jQuery code: jQuery(function() { // First create a div to host the map var themap = jQuery('<div id="themap"></div>').css({ 'width': '90%', 'height': '400px' }).insertBefore('ul.restaurants'); }); While this is technically just a single line of JavaScript (with line-breaks added for readability) it’s actually doing quite a lot of work. Let’s break it down in to steps: var themap = jQuery('<div id="themap"></div>') Here’s jQuery’s method overloading in action: if you pass it a string that starts with a < it assumes that you wish to create a new HTML element. This provides us with a handy shortcut for the more verbose DOM equivalent: var themap = document.createElement('div'); themap.id = 'themap'; Next we want to apply some CSS rules to the element. jQuery supports chaining, which means we can continue to call methods on the object returned by jQuery or any of its methods: var themap = jQuery('<div id="themap"></div>').css({ 'width': '90%', 'height': '400px' }) Finally, we need to insert our new HTML element in to the page. jQuery provides a number of methods for element insertion, but in this case we want to position it directly before the <ul> we are using to contain our restaurants. jQuery’s insertBefore() method takes a CSS selector indicating an element already on the page and places the current jQuery selection directly before that element in the DOM. var themap = jQuery('<div id="themap"></div>').css({ 'width': '90%', 'height': '400px' }).insertBefore('ul.restaurants'); Finally, we need to initialise the map itself using Mapstraction. The Mapstraction constructor takes two arguments: the first is the ID of the element used to position the map; the second is the mapping provider to use (in this case google ): // Initialise the map var mapstraction = new Mapstraction('themap','google'); We want the map to appear centred on Brighton, so we’ll need to know the correct co-ordinates. We can use www.getlatlon.com to find both the co-ordinates and the initial map zoom level. // Show map centred on Brighton mapstraction.setCenterAndZoom( new LatLonPoint(50.82423734980143, -0.14007568359375), 15 // Zoom level appropriate for Brighton city centre ); We also want controls on the map to allow the user to zoom in and out and toggle between map and satellite view. mapstraction.addControls({ zoom: 'large', map_type: true }); Adding the markers It’s finally time to parse some microformats. Since we’re using hCard, the information we want is wrapped in elements with the class vcard. We can use jQuery’s CSS selector support to find them: var vcards = jQuery('.vcard'); Now that we’ve found them, we need to create a marker for each one in turn. Rather than using a regular JavaScript for loop, we can instead use jQuery’s each() method to execute a function against each of the hCards. jQuery('.vcard').each(function() { // Do something with the hCard }); Within the callback function, this is set to the current DOM element (in our case, the list item). If we want to call the magic jQuery methods on it we’ll need to wrap it in another call to jQuery: jQuery('.vcard').each(function() { var hcard = jQuery(this); }); The Google maps geocoder seems to work best if you pass it the street address and a postcode. We can extract these using CSS selectors: this time, we’ll use jQuery’s find() method which searches within the current jQuery selection: var streetaddress = hcard.find('.street-address').text(); var postcode = hcard.find('.postal-code').text(); The text() method extracts the text contents of the selected node, minus any HTML markup. We’ve got the address; now we need to geocode it. Mapstraction’s geocoding API requires us to first construct a MapstractionGeocoder, then use the geocode() method to pass it an address. Here’s the code outline: var geocoder = new MapstractionGeocoder(onComplete, 'google'); geocoder.geocode({'address': 'the address goes here'); The onComplete function is executed when the geocoding operation has been completed, and will be passed an object with the resulting point on the map. We just want to create a marker for the point: var geocoder = new MapstractionGeocoder(function(result) { var marker = new Marker(result.point); mapstraction.addMarker(marker); }, 'google'); For our purposes, joining the street address and postcode with a comma to create the address should suffice: geocoder.geocode({'address': streetaddress + ', ' + postcode}); There’s one last step: when the marker is clicked, we want to display details of the restaurant. We can do this with an info bubble, which can be configured by passing in a string of HTML. We’ll construct that HTML using jQuery’s html() method on our hcard object, which extracts the HTML contained within that DOM node as a string. var marker = new Marker(result.point); marker.setInfoBubble( '<div class="bubble">' + hcard.html() + '</div>' ); mapstraction.addMarker(marker); We’ve wrapped the bubble in a div with class bubble to make it easier to style. Google Maps can behave strangely if you don’t provide an explicit width for your info bubbles, so we’ll add that to our CSS now: .bubble { width: 300px; } That’s everything we need: let’s combine our code together: jQuery(function() { // First create a div to host the map var themap = jQuery('<div id="themap"></div>').css({ 'width': '90%', 'height': '400px' }).insertBefore('ul.restaurants'); // Now initialise the map var mapstraction = new Mapstraction('themap','google'); mapstraction.addControls({ zoom: 'large', map_type: true }); // Show map centred on Brighton mapstraction.setCenterAndZoom( new LatLonPoint(50.82423734980143, -0.14007568359375), 15 // Zoom level appropriate for Brighton city centre ); // Geocode each hcard and add a marker jQuery('.vcard').each(function() { var hcard = jQuery(this); var streetaddress = hcard.find('.street-address').text(); var postcode = hcard.find('.postal-code').text(); var geocoder = new MapstractionGeocoder(function(result) { var marker = new Marker(result.point); marker.setInfoBubble( '<div class="bubble">' + hcard.html() + '</div>' ); mapstraction.addMarker(marker); }, 'google'); geocoder.geocode({'address': streetaddress + ', ' + postcode}); }); }); Here’s the finished code. There’s one last shortcut we can add: jQuery provides the $ symbol as an alias for jQuery. We could just go through our code and replace every call to jQuery() with a call to $(), but this would cause incompatibilities if we ever attempted to use our script on a page that also includes the Prototype library. A more robust approach is to start our code with the following: jQuery(function($) { // Within this function, $ now refers to jQuery // ... }); jQuery cleverly passes itself as the first argument to any function registered to the DOM ready event, which means we can assign a local $ variable shortcut without affecting the $ symbol in the global scope. This makes it easy to use jQuery with other libraries. Limitations of Geocoding You may have noticed a discrepancy creep in to the last example: whereas my original list included seven restaurants, the geocoding example only shows five. This is because the Google Maps geocoder incorporates a rate limit: more than five lookups in a second and it starts returning error messages instead of regular results. In addition to this problem, geocoding itself is an inexact science: while UK postcodes generally get you down to the correct street, figuring out the exact point on the street from the provided address usually isn’t too accurate (although Google do a pretty good job). Finally, there’s the performance overhead. We’re making five geocoding requests to Google for every page served, even though the restaurants themselves aren’t likely to change location any time soon. Surely there’s a better way of doing this? Microformats to the rescue (again)! The geo microformat suggests simple classes for including latitude and longitude information in a page. We can add specific points for each restaurant using the following markup: <li class="vcard"> <h3 class="fn org">E-Kagen</h3> <div class="adr"> <p class="street-address">22-23 Sydney Street</p> <p><span class="locality">Brighton</span>, <abbr class="country-name" title="United Kingdom">UK</abbr></p> <p class="postal-code">BN1 4EN</p> </div> <p>Telephone: <span class="tel">+44 (0)1273 687 068</span></p> <p class="geo">Lat/Lon: <span class="latitude">50.827917</span>, <span class="longitude">-0.137764</span> </p> </li> As before, I used www.getlatlon.com to find the exact locations – I find satellite view is particularly useful for locating individual buildings. Latitudes and longitudes are great for machines but not so useful for human beings. We could hide them entirely with display: none, but I prefer to merely de-emphasise them (someone might want them for their GPS unit): .vcard .geo { margin-top: 0.5em; font-size: 0.85em; color: #ccc; } It’s probably a good idea to hide them completely when they’re displayed inside an info bubble: .bubble .geo { display: none; } We can extract the co-ordinates in the same way we extracted the address. Since we’re no longer geocoding anything our code becomes a lot simpler: $('.vcard').each(function() { var hcard = $(this); var latitude = hcard.find('.geo .latitude').text(); var longitude = hcard.find('.geo .longitude').text(); var marker = new Marker(new LatLonPoint(latitude, longitude)); marker.setInfoBubble( '<div class="bubble">' + hcard.html() + '</div>' ); mapstraction.addMarker(marker); }); And here’s the finished geo example. Further reading We’ve only scratched the surface of what’s possible with microformats, jQuery (or just regular JavaScript) and a bit of imagination. If this example has piqued your interest, the following links should give you some more food for thought. The hCard specification Notes on parsing hCards jQuery for JavaScript programmers – my extended tutorial on jQuery. Dann Webb’s Sumo – a full JavaScript library for parsing microformats, based around some clever metaprogramming techniques. Jeremy Keith’s Adactio Austin – the first place I saw using microformats to unobtrusively plot locations on a map. Makes clever use of hEvent as well. 2007 Simon Willison simonwillison 2007-12-12T00:00:00+00:00 https://24ways.org/2007/unobtrusively-mapping-microformats-with-jquery/ code
249 Fast Autocomplete Search for Your Website Every website deserves a great search engine - but building a search engine can be a lot of work, and hosting it can quickly get expensive. I’m going to build a search engine for 24 ways that’s fast enough to support autocomplete (a.k.a. typeahead) search queries and can be hosted for free. I’ll be using wget, Python, SQLite, Jupyter, sqlite-utils and my open source Datasette tool to build the API backend, and a few dozen lines of modern vanilla JavaScript to build the interface. Try it out here, then read on to see how I built it. First step: crawling the data The first step in building a search engine is to grab a copy of the data that you plan to make searchable. There are plenty of potential ways to do this: you might be able to pull it directly from a database, or extract it using an API. If you don’t have access to the raw data, you can imitate Google and write a crawler to extract the data that you need. I’m going to do exactly that against 24 ways: I’ll build a simple crawler using wget, a command-line tool that features a powerful “recursive” mode that’s ideal for scraping websites. We’ll start at the https://24ways.org/archives/ page, which links to an archived index for every year that 24 ways has been running. Then we’ll tell wget to recursively crawl the website, using the --recursive flag. We don’t want to fetch every single page on the site - we’re only interested in the actual articles. Luckily, 24 ways has nicely designed URLs, so we can tell wget that we only care about pages that start with one of the years it has been running, using the -I argument like this: -I /2005,/2006,/2007,/2008,/2009,/2010,/2011,/2012,/2013,/2014,/2015,/2016,/2017 We want to be polite, so let’s wait for 2 seconds between each request rather than hammering the site as fast as we can: --wait 2 The first time I ran this, I accidentally downloaded the comments pages as well. We don’t want those, so let’s exclude them from the crawl using -X "/*/*/comments". Finally, it’s useful to be able to run the command multiple times without downloading pages that we have already fetched. We can use the --no-clobber option for this. Tie all of those options together and we get this command: wget --recursive --wait 2 --no-clobber -I /2005,/2006,/2007,/2008,/2009,/2010,/2011,/2012,/2013,/2014,/2015,/2016,/2017 -X "/*/*/comments" https://24ways.org/archives/ If you leave this running for a few minutes, you’ll end up with a folder structure something like this: $ find 24ways.org 24ways.org 24ways.org/2013 24ways.org/2013/why-bother-with-accessibility 24ways.org/2013/why-bother-with-accessibility/index.html 24ways.org/2013/levelling-up 24ways.org/2013/levelling-up/index.html 24ways.org/2013/project-hubs 24ways.org/2013/project-hubs/index.html 24ways.org/2013/credits-and-recognition 24ways.org/2013/credits-and-recognition/index.html ... As a quick sanity check, let’s count the number of HTML pages we have retrieved: $ find 24ways.org | grep index.html | wc -l 328 There’s one last step! We got everything up to 2017, but we need to fetch the articles for 2018 (so far) as well. They aren’t linked in the /archives/ yet so we need to point our crawler at the site’s front page instead: wget --recursive --wait 2 --no-clobber -I /2018 -X "/*/*/comments" https://24ways.org/ Thanks to --no-clobber, this is safe to run every day in December to pick up any new content. We now have a folder on our computer containing an HTML file for every article that has ever been published on the site! Let’s use them to build ourselves a search index. Building a search index using SQLite There are many tools out there that can be used to build a search engine. You can use an open-source search server like Elasticsearch or Solr, a hosted option like Algolia or Amazon CloudSearch or you can tap into the built-in search features of relational databases like MySQL or PostgreSQL. I’m going to use something that’s less commonly used for web applications but makes for a powerful and extremely inexpensive alternative: SQLite. SQLite is the world’s most widely deployed database, even though many people have never even heard of it. That’s because it’s designed to be used as an embedded database: it’s commonly used by native mobile applications and even runs as part of the default set of apps on the Apple Watch! SQLite has one major limitation: unlike databases like MySQL and PostgreSQL, it isn’t really designed to handle large numbers of concurrent writes. For this reason, most people avoid it for building web applications. This doesn’t matter nearly so much if you are building a search engine for infrequently updated content - say one for a site that only publishes new content on 24 days every year. It turns out SQLite has very powerful full-text search functionality built into the core database - the FTS5 extension. I’ve been doing a lot of work with SQLite recently, and as part of that, I’ve been building a Python utility library to make building new SQLite databases as easy as possible, called sqlite-utils. It’s designed to be used within a Jupyter notebook - an enormously productive way of interacting with Python code that’s similar to the Observable notebooks Natalie described on 24 ways yesterday. If you haven’t used Jupyter before, here’s the fastest way to get up and running with it - assuming you have Python 3 installed on your machine. We can use a Python virtual environment to ensure the software we are installing doesn’t clash with any other installed packages: $ python3 -m venv ./jupyter-venv $ ./jupyter-venv/bin/pip install jupyter # ... lots of installer output # Now lets install some extra packages we will need later $ ./jupyter-venv/bin/pip install beautifulsoup4 sqlite-utils html5lib # And start the notebook web application $ ./jupyter-venv/bin/jupyter-notebook # This will open your browser to Jupyter at http://localhost:8888/ You should now be in the Jupyter web application. Click New -> Python 3 to start a new notebook. A neat thing about Jupyter notebooks is that if you publish them to GitHub (either in a regular repository or as a Gist), it will render them as HTML. This makes them a very powerful way to share annotated code. I’ve published the notebook I used to build the search index on my GitHub account. ​ Here’s the Python code I used to scrape the relevant data from the downloaded HTML files. Check out the notebook for a line-by-line explanation of what’s going on. from pathlib import Path from bs4 import BeautifulSoup as Soup base = Path("/Users/simonw/Dropbox/Development/24ways-search") articles = list(base.glob("*/*/*/*.html")) # articles is now a list of paths that look like this: # PosixPath('...24ways-search/24ways.org/2013/why-bother-with-accessibility/index.html') docs = [] for path in articles: year = str(path.relative_to(base)).split("/")[1] url = 'https://' + str(path.relative_to(base).parent) + '/' soup = Soup(path.open().read(), "html5lib") author = soup.select_one(".c-continue")["title"].split( "More information about" )[1].strip() author_slug = soup.select_one(".c-continue")["href"].split( "/authors/" )[1].split("/")[0] published = soup.select_one(".c-meta time")["datetime"] contents = soup.select_one(".e-content").text.strip() title = soup.find("title").text.split(" ◆")[0] try: topic = soup.select_one( '.c-meta a[href^="/topics/"]' )["href"].split("/topics/")[1].split("/")[0] except TypeError: topic = None docs.append({ "title": title, "contents": contents, "year": year, "author": author, "author_slug": author_slug, "published": published, "url": url, "topic": topic, }) After running this code, I have a list of Python dictionaries representing each of the documents that I want to add to the index. The list looks something like this: [ { "title": "Why Bother with Accessibility?", "contents": "Web accessibility (known in other fields as inclus...", "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" }, { "title": "Levelling Up", "contents": "Hello, 24 ways. Iu2019m Ashley and I sell property ins...", "year": "2013", "author": "Ashley Baxter", "author_slug": "ashleybaxter", "published": "2013-12-06T00:00:00+00:00", "url": "https://24ways.org/2013/levelling-up/", "topic": "business" }, ... My sqlite-utils library has the ability to take a list of objects like this and automatically create a SQLite database table with the right schema to store the data. Here’s how to do that using this list of dictionaries. import sqlite_utils db = sqlite_utils.Database("/tmp/24ways.db") db["articles"].insert_all(docs) That’s all there is to it! The library will create a new database and add a table to it called articles with the necessary columns, then insert all of the documents into that table. (I put the database in /tmp/ for the moment - you can move it to a more sensible location later on.) You can inspect the table using the sqlite3 command-line utility (which comes with OS X) like this: $ sqlite3 /tmp/24ways.db sqlite> .headers on sqlite> .mode column sqlite> select title, author, year from articles; title author year ------------------------------ ------------ ---------- Why Bother with Accessibility? Laura Kalbag 2013 Levelling Up Ashley Baxte 2013 Project Hubs: A Home Base for Brad Frost 2013 Credits and Recognition Geri Coady 2013 Managing a Mind Christopher 2013 Run Ragged Mark Boulton 2013 Get Started With GitHub Pages Anna Debenha 2013 Coding Towards Accessibility Charlie Perr 2013 ... <Ctrl+D to quit> There’s one last step to take in our notebook. We know we want to use SQLite’s full-text search feature, and sqlite-utils has a simple convenience method for enabling it for a specified set of columns in a table. We want to be able to search by the title, author and contents fields, so we call the enable_fts() method like this: db["articles"].enable_fts(["title", "author", "contents"]) Introducing Datasette Datasette is the open-source tool I’ve been building that makes it easy to both explore SQLite databases and publish them to the internet. We’ve been exploring our new SQLite database using the sqlite3 command-line tool. Wouldn’t it be nice if we could use a more human-friendly interface for that? If you don’t want to install Datasette right now, you can visit https://search-24ways.herokuapp.com/ to try it out against the 24 ways search index data. I’ll show you how to deploy Datasette to Heroku like this later in the article. If you want to install Datasette locally, you can reuse the virtual environment we created to play with Jupyter: ./jupyter-venv/bin/pip install datasette This will install Datasette in the ./jupyter-venv/bin/ folder. You can also install it system-wide using regular pip install datasette. Now you can run Datasette against the 24ways.db file we created earlier like so: ./jupyter-venv/bin/datasette /tmp/24ways.db This will start a local webserver running. Visit http://localhost:8001/ to start interacting with the Datasette web application. If you want to try out Datasette without creating your own 24ways.db file you can download the one I created directly from https://search-24ways.herokuapp.com/24ways-ae60295.db Publishing the database to the internet One of the goals of the Datasette project is to make deploying data-backed APIs to the internet as easy as possible. Datasette has a built-in command for this, datasette publish. If you have an account with Heroku or Zeit Now, you can deploy a database to the internet with a single command. Here’s how I deployed https://search-24ways.herokuapp.com/ (running on Heroku’s free tier) using datasette publish: $ ./jupyter-venv/bin/datasette publish heroku /tmp/24ways.db --name search-24ways -----> Python app detected -----> Installing requirements with pip -----> Running post-compile hook -----> Discovering process types Procfile declares types -> web -----> Compressing... Done: 47.1M -----> Launching... Released v8 https://search-24ways.herokuapp.com/ deployed to Heroku If you try this out, you’ll need to pick a different --name, since I’ve already taken search-24ways. You can run this command as many times as you like to deploy updated versions of the underlying database. Searching and faceting Datasette can detect tables with SQLite full-text search configured, and will add a search box directly to the page. Take a look at http://search-24ways.herokuapp.com/24ways-b607e21/articles to see this in action. ​ SQLite search supports wildcards, so if you want autocomplete-style search where you don’t need to enter full words to start getting results you can add a * to the end of your search term. Here’s a search for access* which returns articles on accessibility: http://search-24ways.herokuapp.com/24ways-ae60295/articles?_search=acces%2A A neat feature of Datasette is the ability to calculate facets against your data. Here’s a page showing search results for svg with facet counts calculated against both the year and the topic columns: http://search-24ways.herokuapp.com/24ways-ae60295/articles?_search=svg&_facet=year&_facet=topic Every page visible via Datasette has a corresponding JSON API, which can be accessed using the JSON link on the page - or by adding a .json extension to the URL: http://search-24ways.herokuapp.com/24ways-ae60295/articles.json?_search=acces%2A Better search using custom SQL The search results we get back from ../articles?_search=svg are OK, but the order they are returned in is not ideal - they’re actually being returned in the order they were inserted into the database! You can see why this is happening by clicking the View and edit SQL link on that search results page. This exposes the underlying SQL query, which looks like this: select rowid, * from articles where rowid in ( select rowid from articles_fts where articles_fts match :search ) order by rowid limit 101 We can do better than this by constructing a custom SQL query. Here’s the query we will use instead: select snippet(articles_fts, -1, 'b4de2a49c8', '8c94a2ed4b', '...', 100) as snippet, articles_fts.rank, articles.title, articles.url, articles.author, articles.year from articles join articles_fts on articles.rowid = articles_fts.rowid where articles_fts match :search || "*" order by rank limit 10; You can try this query out directly - since Datasette opens the underling SQLite database in read-only mode and enforces a one second time limit on queries, it’s safe to allow users to provide arbitrary SQL select queries for Datasette to execute. There’s a lot going on here! Let’s break the SQL down line-by-line: select snippet(articles_fts, -1, 'b4de2a49c8', '8c94a2ed4b', '...', 100) as snippet, We’re using snippet(), a built-in SQLite function, to generate a snippet highlighting the words that matched the query. We use two unique strings that I made up to mark the beginning and end of each match - you’ll see why in the JavaScript later on. articles_fts.rank, articles.title, articles.url, articles.author, articles.year These are the other fields we need back - most of them are from the articles table but we retrieve the rank (representing the strength of the search match) from the magical articles_fts table. from articles join articles_fts on articles.rowid = articles_fts.rowid articles is the table containing our data. articles_fts is a magic SQLite virtual table which implements full-text search - we need to join against it to be able to query it. where articles_fts match :search || "*" order by rank limit 10; :search || "*" takes the ?search= argument from the page querystring and adds a * to the end of it, giving us the wildcard search that we want for autocomplete. We then match that against the articles_fts table using the match operator. Finally, we order by rank so that the best matching results are returned at the top - and limit to the first 10 results. How do we turn this into an API? As before, the secret is to add the .json extension. Datasette actually supports multiple shapes of JSON - we’re going to use ?_shape=array to get back a plain array of objects: JSON API call to search for articles matching SVG The HTML version of that page shows the time taken to execute the SQL in the footer. Hitting refresh a few times, I get response times between 2 and 5ms - easily fast enough to power a responsive autocomplete feature. A simple JavaScript autocomplete search interface I considered building this using React or Svelte or another of the myriad of JavaScript framework options available today, but then I remembered that vanilla JavaScript in 2018 is a very productive environment all on its own. We need a few small utility functions: first, a classic debounce function adapted from this one by David Walsh: function debounce(func, wait, immediate) { let timeout; return function() { let context = this, args = arguments; let later = () => { timeout = null; if (!immediate) func.apply(context, args); }; let callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; We’ll use this to only send fetch() requests a maximum of once every 100ms while the user is typing. Since we’re rendering data that might include HTML tags (24 ways is a site about web development after all), we need an HTML escaping function. I’m amazed that browsers still don’t bundle a default one of these: const htmlEscape = (s) => s.replace( />/g, '&gt;' ).replace( /</g, '&lt;' ).replace( /&/g, '&' ).replace( /"/g, '&quot;' ).replace( /'/g, '&#039;' ); We need some HTML for the search form, and a div in which to render the results: <h1>Autocomplete search</h1> <form> <p><input id="searchbox" type="search" placeholder="Search 24ways" style="width: 60%"></p> </form> <div id="results"></div> And now the autocomplete implementation itself, as a glorious, messy stream-of-consciousness of JavaScript: // Embed the SQL query in a multi-line backtick string: const sql = `select snippet(articles_fts, -1, 'b4de2a49c8', '8c94a2ed4b', '...', 100) as snippet, articles_fts.rank, articles.title, articles.url, articles.author, articles.year from articles join articles_fts on articles.rowid = articles_fts.rowid where articles_fts match :search || "*" order by rank limit 10`; // Grab a reference to the <input type="search"> const searchbox = document.getElementById("searchbox"); // Used to avoid race-conditions: let requestInFlight = null; searchbox.onkeyup = debounce(() => { const q = searchbox.value; // Construct the API URL, using encodeURIComponent() for the parameters const url = ( "https://search-24ways.herokuapp.com/24ways-866073b.json?sql=" + encodeURIComponent(sql) + `&search=${encodeURIComponent(q)}&_shape=array` ); // Unique object used just for race-condition comparison let currentRequest = {}; requestInFlight = currentRequest; fetch(url).then(r => r.json()).then(d => { if (requestInFlight !== currentRequest) { // Avoid race conditions where a slow request returns // after a faster one. return; } let results = d.map(r => ` <div class="result"> <h3><a href="${r.url}">${htmlEscape(r.title)}</a></h3> <p><small>${htmlEscape(r.author)} - ${r.year}</small></p> <p>${highlight(r.snippet)}</p> </div> `).join(""); document.getElementById("results").innerHTML = results; }); }, 100); // debounce every 100ms There’s just one more utility function, used to help construct the HTML results: const highlight = (s) => htmlEscape(s).replace( /b4de2a49c8/g, '<b>' ).replace( /8c94a2ed4b/g, '</b>' ); This is what those unique strings passed to the snippet() function were for. Avoiding race conditions in autocomplete One trick in this code that you may not have seen before is the way race-conditions are handled. Any time you build an autocomplete feature, you have to consider the following case: User types acces Browser sends request A - querying documents matching acces* User continues to type accessibility Browser sends request B - querying documents matching accessibility* Request B returns. It was fast, because there are fewer documents matching the full term The results interface updates with the documents from request B, matching accessibility* Request A returns results (this was the slower of the two requests) The results interface updates with the documents from request A - results matching access* This is a terrible user experience: the user saw their desired results for a brief second, and then had them snatched away and replaced with those results from earlier on. Thankfully there’s an easy way to avoid this. I set up a variable in the outer scope called requestInFlight, initially set to null. Any time I start a new fetch() request, I create a new currentRequest = {} object and assign it to the outer requestInFlight as well. When the fetch() completes, I use requestInFlight !== currentRequest to sanity check that the currentRequest object is strictly identical to the one that was in flight. If a new request has been triggered since we started the current request we can detect that and avoid updating the results. It’s not a lot of code, really And that’s the whole thing! The code is pretty ugly, but when the entire implementation clocks in at fewer than 70 lines of JavaScript, I honestly don’t think it matters. You’re welcome to refactor it as much you like. How good is this search implementation? I’ve been building search engines for a long time using a wide variety of technologies and I’m happy to report that using SQLite in this way is genuinely a really solid option. It scales happily up to hundreds of MBs (or even GBs) of data, and the fact that it’s based on SQL makes it easy and flexible to work with. A surprisingly large number of desktop and mobile applications you use every day implement their search feature on top of SQLite. More importantly though, I hope that this demonstrates that using Datasette for an API means you can build relatively sophisticated API-backed applications with very little backend programming effort. If you’re working with a small-to-medium amount of data that changes infrequently, you may not need a more expensive database. Datasette-powered applications easily fit within the free tier of both Heroku and Zeit Now. For more of my writing on Datasette, check out the datasette tag on my blog. And if you do build something fun with it, please let me know on Twitter. 2018 Simon Willison simonwillison 2018-12-19T00:00:00+00:00 https://24ways.org/2018/fast-autocomplete-search-for-your-website/ code
326 Don't be eval() JavaScript is an interpreted language, and like so many of its peers it includes the all powerful eval() function. eval() takes a string and executes it as if it were regular JavaScript code. It’s incredibly powerful and incredibly easy to abuse in ways that make your code slower and harder to maintain. As a general rule, if you’re using eval() there’s probably something wrong with your design. Common mistakes Here’s the classic misuse of eval(). You have a JavaScript object, foo, and you want to access a property on it – but you don’t know the name of the property until runtime. Here’s how NOT to do it: var property = 'bar'; var value = eval('foo.' + property); Yes it will work, but every time that piece of code runs JavaScript will have to kick back in to interpreter mode, slowing down your app. It’s also dirt ugly. Here’s the right way of doing the above: var property = 'bar'; var value = foo[property]; In JavaScript, square brackets act as an alternative to lookups using a dot. The only difference is that square bracket syntax expects a string. Security issues In any programming language you should be extremely cautious of executing code from an untrusted source. The same is true for JavaScript – you should be extremely cautious of running eval() against any code that may have been tampered with – for example, strings taken from the page query string. Executing untrusted code can leave you vulnerable to cross-site scripting attacks. What’s it good for? Some programmers say that eval() is B.A.D. – Broken As Designed – and should be removed from the language. However, there are some places in which it can dramatically simplify your code. A great example is for use with XMLHttpRequest, a component of the set of tools more popularly known as Ajax. XMLHttpRequest lets you make a call back to the server from JavaScript without refreshing the whole page. A simple way of using this is to have the server return JavaScript code which is then passed to eval(). Here is a simple function for doing exactly that – it takes the URL to some JavaScript code (or a server-side script that produces JavaScript) and loads and executes that code using XMLHttpRequest and eval(). function evalRequest(url) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { eval(xmlhttp.responseText); } } xmlhttp.open("GET", url, true); xmlhttp.send(null); } If you want this to work with Internet Explorer you’ll need to include this compatibility patch. 2005 Simon Willison simonwillison 2005-12-07T00:00:00+00:00 https://24ways.org/2005/dont-be-eval/ code
230 The Articulate Web Designer of Tomorrow You could say that we design to communicate, and that we seek emotive responses. It sounds straightforward, and it can be, but leaving it to chance isn’t wise. Many wander into web design without formal training, and whilst that certainly isn’t essential, we owe it to ourselves to draw on wider influences, learn from the past, and think smarter. What knowledge can we ourselves explore in order to become better designers? In addition, how can we take this knowledge, investigate it through our unique discipline, and in turn speak more eloquently about what we do on the web? Below, I outline a number of things that I personally believe all designers should be using and exploring collectively. Taking stock Where we’re at is good. Finding clarity through web standards, we’ve ended up quite modernist in our approach, pursuing function, elegance and reduction. However, we’re not great at articulating our own design processes and principles to outsiders. Equally, we rely heavily on our instincts when deciding if something is or isn’t good. That’s fine, but we can better understand why things are the way they are by looking a little deeper, thereby helping us articulate what goes on in our design brains to our peers, our clients and to normal humans. As designers we use ideas, concepts, text and images. We apply our ideas and experience, imposing order and structure to content, hoping to ease the communication of an idea to the largest possible audience or to a specific audience. We consciously manipulate most of what is available to us, but not all. There is something else we can use. I often think that brilliant work demands a keen understanding of the magical visual language that informs design. Embracing an established visual language This is a language whose alphabet is shapes, structures, colours, lines and rhythms. When effective, it is somewhat invisible, subliminally enforcing messages and evoking meaning, using methods solidly rooted in a grammar perceptible in virtually all extraordinary creative work. The syntax for art, architecture, film, and furniture, industrial and graphic design (think Bauhaus and the Swiss style perhaps), this language urges us to become fluent if we aim for a more powerful dialogue with our audience. Figure 1: Structures (clockwise from top-left): Informal; Formal; Active; Visible. The greatest creative minds our world has produced could understand some or all of this language. Line and point, form and shape. Abstract objects. Formal and informal structures. Visual distribution. Balance, composition and the multitudinous approaches to symmetry. Patterns and texture. Movement and paths. Repetition, rhythm and frequency. Colour theory. Whitespace and the pause. The list goes on. The genius we perceive in our creative heroes is often a composite of experience, trial and error, conviction, intuition – even accident – but rarely does great work arise without an initial understanding of the nuts and bolts that help communicate an idea or emotion. Our world of interactivity As web designers, our connection with this language is most evident in graphic design. With more technological ease and power comes the responsibility to understand, wisely use, and be able to justify many of our decisions. We have moved beyond the scope of print into a world of interactivity, but we shouldn’t let go of any established principles without good reason. Figure 2: Understanding movement of objects in any direction along a defined path. For example, immersion in this visual language can improve our implementation of CSS3 and JavaScript behaviour. With CSS3, we’ve seen a resurgence in CSS experimentation, some of which has been wonderful, but much of it has appeared clumsy. In the race to make something spin, twist, flip or fly from one corner to another, the designer sometimes fails to think about the true movement they seek to emulate. What forces are supposedly affecting this movement? What is the expected path of this transition and is it being respected? Stopping to think about what is really supposed to be happening on the page compels us to use complex animations, diagrams and rotations more carefully. It helps us to better understand paths and movement. Figure 3: Repetition can occur through variations in colour, shape, direction, and so on. It can only be of greater benefit to be mindful of symmetries, depth, affordance, juxtaposition, balance, economy and reduction. A deeper understanding of basic structures can help us to say more with sketches, wireframes, layouts and composition. We’ve all experimented with grids and rhythm but, to truly benefit from these long-established principles, we are duty-bound to understand their possibilities more than we will by simply leveraging a free framework or borrowing some CSS. Design is not a science, but… Threading through all of this is what we have learned from science, and what it teaches us of the human brain. This visual language matters because technology changes but, for the most part, people don’t. For centuries, we humans have received and interpreted information in much the same way. Understanding more of how we perceive meaning can help designers make smarter decisions, and call on visual language to underpin these decisions. It is our responsibility as designers to be aware of mental models, mapping, semiotics, sensory experience and human emotion. Design itself is not a science, but the appropriate use of visual language and scientific understanding exposes the line between effective and awkward, between communicative and mute. By strengthening our mental and analytical approach to what is often done arbitrarily or “because it feels right”, we simply become better designers. A visual language for the web So, I’ve outlined numerous starting points and areas worthy of deeper investigation, and hopefully you’re eager to do some research. However, I’ve mostly discussed established ideas and principles that we as web designers can learn from. It’s my belief that our community has a shared responsibility to expand this visual language as it applies to the ebb and flow of the web. Indulge me as I conclude with a related tangent. In defining a visual language specifically for the web, we must continue to mature. The old powerfully influences the new, but we must intelligently expand the visual language of masterful work and articulate what is uniquely ours. For example, phrases like Ethan Marcotte’s Responsive Web Design aren’t merely elegant, they describe a new way of thinking and working, of communicating about designs and interaction patterns. These phrases broaden our vocabulary and are immediately adopted by designers worldwide, in both conversation and execution. Our legacy Our new definitions should flex and not be tied to specific devices or methods which fade away or morph with time. Our legacy is perhaps more about robust and flexible patterns and systems than it is about specific devices or programming languages. Figure 4: As web designers, we should think about systems, not pages. The established principles we adopt and whatever new ways of thinking we define should slip neatly into a wider philosophy about our approach to web design. We’re called, as a community, to define what is distinctive about the visual language of the web, create this vocabulary, this dialect that resonates with us and moves us forward as we tackle each day’s work. Let’s give it some thought. Further reading This is my immediate “go-to” list of books that I bullishly believe all web designers should own, but there is so much more out there to read. Sadly, many great texts relating to this stuff are often out of print. Feel free to share your recommendations. Don Norman, The Design of Everyday Things Christian Leborg, Visual Grammar Scott McCloud, Understanding Comics David Crow, Visible Signs William Lidwell and Katrina Holden, Universal Principles of Design 2010 Simon Collison simoncollison 2010-12-16T00:00:00+00:00 https://24ways.org/2010/the-articulate-web-designer-of-tomorrow/ process
267 Taming Complexity I’m going to step into my UX trousers for this one. I wouldn’t usually wear them in public, but it’s Christmas, so there’s nothing wrong with looking silly. Anyway, to business. Wherever I roam, I hear the familiar call for simplicity and the denouncement of complexity. I read often that the simpler something is, the more usable it will be. We understand that simple is hard to achieve, but we push for it nonetheless, convinced it will make what we build easier to use. Simple is better, right? Well, I’ll try to explore that. Much of what follows will not be revelatory to some but, like all good lessons, I think this serves as a welcome reminder that as we live in a complex world it’s OK to sometimes reflect that complexity in the products we build. Myths and legends Less is more, we’ve been told, ever since master of poetic verse Robert Browning used the phrase in 1855. Well, I’ve conducted some research, and it appears he knew nothing of web design. Neither did modernist architect Ludwig Mies van der Rohe, a later pedlar of this worthy yet contradictory notion. Broad is narrow. Tall is short. Eggs are chips. See: anyone can come up with this stuff. To paraphrase Einstein, simple doesn’t have to be simpler. In other words, simple doesn’t dictate that we remove the complexity. Complex doesn’t have to be confusing; it can be beautiful and elegant. On the web, complex can be necessary and powerful. A website that simplifies the lives of its users by offering them everything they need in one site or screen is powerful. For some, the greater the density of information, the more useful the site. In our decision-making process, principles such as Occam’s razor’s_razor (in a nutshell: simple is better than complex) are useful, but simple is for the user to determine through their initial impression and subsequent engagement. What appears simple to me or you might appear very complex to someone else, based on their own mental model or needs. We can aim to deliver simple, but they’ll be the judge. As a designer, developer, content alchemist, user experience discombobulator, or whatever you call yourself, you’re often wrestling with a wealth of material, a huge number of features, and numerous objectives. In many cases, much of that stuff is extraneous, and goes in the dustbin. However, it can be just as likely that there’s a truckload of suggested features and content because it all needs to be there. Don’t be afraid of that weight. In the right hands, less can indeed mean more, but it’s just as likely that less can very often lead to, well… less. Complexity is powerful Simple is the ability to offer a powerful experience without overwhelming the audience or inducing information anxiety. Giving them everything they need, without having them ferret off all over a site to get things done, is important. It’s useful to ask throughout a site’s lifespan, “does the user have everything they need?” It’s so easy to let our designer egos get in the way and chop stuff out, reduce down to only the things we want to see. That benefits us in the short term, but compromises the audience long-term. The trick is not to be afraid of complexity in itself, but to avoid creating the perception of complexity. Give a user a flight simulator and they’ll crash the plane or jump out. Give them everything they need and more, but make it feel simple, and you’re building a relationship, empowering people. This can be achieved carefully with what some call gradual engagement, and often the sensible thing might be to unleash complexity in carefully orchestrated phases, initially setting manageable levels of engagement and interaction, gradually increasing the inherent power of the product and fostering an empowered community. The design aesthetic Here’s a familiar scenario: the client or project lead gets overexcited and skips most of the important decision-making, instead barrelling straight into a bout of creative direction Tourette’s. Visually, the design needs to be minimal, white, crisp, full of white space, have big buttons, and quite likely be “clean”. Of course, we all like our websites to be clean as that’s more hygienic. But what do these words even mean, really? Early in a project they’re abstract distractions, unnecessary constraints. This premature narrowing forces us to think much more about throwing stuff out rather than acknowledging that what we’re building is complex, and many of the components perhaps necessary. Simple is not a formula. It cannot be achieved just by using a white background, by throwing things away, or by breathing a bellowsful of air in between every element and having it all float around in space. Simple is not a design treatment. Simple is hard. Simple requires deep investigation, a thorough understanding of every aspect of a project, in line with the needs and expectations of the audience. Recognizing this helps us empathize a little more with those most vocal of UX practitioners. They usually appreciate that our successes depend on a thorough understanding of the user’s mental models and expected outcomes. I personally still consider UX people to be web designers like the rest of us (mainly to wind them up), but they’re web designers that design every decision, and by putting the user experience at the heart of their process, they have a greater chance of finding simplicity in complexity. The visual design aesthetic — the façade — is only a part of that. Divide and conquer I’m currently working on an app that’s complex in architecture, and complex in ambition. We’ll be releasing in carefully orchestrated private phases, gradually introducing more complexity in line with the unavoidably complex nature of the objective, but my job is to design the whole, the complete system as it will be when it’s out of beta and beyond. I’ve noticed that I’m not throwing much out; most of it needs to be there. Therefore, my responsibility is to consider interesting and appropriate methods of navigation and bring everything together logically. I’m using things like smart defaults, graphical timelines and colour keys to make sense of the complexity, techniques that are sympathetic to the content. They act as familiar points of navigation and reference, yet are malleable enough to change subtly to remain relevant to the information they connect. It’s really OK to have a lot of stuff, so long as we make each component work smartly. It’s a divide and conquer approach. By finding simplicity and logic in each content bucket, I’ve made more sense of the whole, allowing me to create key layouts where most of the simplified buckets are collated and sometimes combined, providing everything the user needs and expects in the appropriate places. I’m also making sure I don’t reduce the app’s power. I need to reflect the scale of opportunity, and provide access to or knowledge of the more advanced tools and features for everyone: a window into what they can do and how they can help. I know it’s the minority who will be actively building the content, but the power is in providing those opportunities for all. Much of this will be familiar to the responsible practitioners who build websites for government, local authorities, utility companies, newspapers, magazines, banking, and we-sell-everything-ever-made online shops. Across the web, there are sites and tools that thrive on complexity. Alas, the majority of such sites have done little to make navigation intuitive, or empower audiences. Where we can make a difference is by striving to make our UIs feel simple, look wonderful, not intimidating — even if they’re mind-meltingly complex behind that façade. Embrace, empathize and tame So, there are loads of ways to exploit complexity, and make it seem simple. I’ve hinted at some methods above, and we’ve already looked at gradual engagement as a way to make sense of complexity, so that’s a big thumbs-up for a release cycle that increases audience power. Prior to each and every release, it’s also useful to rest on the finished thing for a while and use it yourself, even if you’re itching to release. ‘Ready’ often isn’t, and ‘finished’ never is, and the more time you spend browsing around the sites you build, the more you learn what to question, where to add, or subtract. It’s definitely worth building in some contingency time for sitting on your work, so to speak. One thing I always do is squint at my layouts. By squinting, I get a sort of abstract idea of the overall composition, and general feel for the thing. It makes my face look stupid, but helps me see how various buckets fit together, and how simple or complex the site feels overall. I mentioned the need to put our design egos to one side and not throw out anything useful, and I think that’s vital. I’m a big believer in economy, reduction, and removing the extraneous, but I’m usually referring to decoration, bells and whistles, and fluff. I wouldn’t ever advocate the complete removal of powerful content from a project roadmap. Above all, don’t fear complexity. Embrace and tame it. Work hard to empathize with audience needs, and you can create elegant, playful, risky, surprising, emotive, delightful, and ultimately simple things. 2011 Simon Collison simoncollison 2011-12-21T00:00:00+00:00 https://24ways.org/2011/taming-complexity/ ux
328 Swooshy Curly Quotes Without Images The problem Take a quote and render it within blockquote tags, applying big, funky and stylish curly quotes both at the beginning and the end without using any images – at all. The traditional way Feint background images under the text, or an image in the markup housed in a little float. Often designers only use the opening curly quote as it’s just too difficult to float a closing one. Why is the traditional way bad? Well, for a start there are no actual curly quotes in the text (unless you’re doing some nifty image replacement). Thus with CSS disabled you’ll only have default blockquote styling to fall back on. Secondly, images don’t resize, so scaling text will have no affect on your graphic curlies. The solution Use really big text. Then it can be resized by the browser, resized using CSS, and even be restyled with a new font style if you fancy it. It’ll also make sense when CSS is unavailable. The problem Creating “Drop Caps” with CSS has been around for a while (Big Dan Cederholm discusses a neat solution in that first book of his), but drop caps are normal characters – the A to Z or 1 to 10 – and these can all be pulled into a set space and do not serve up a ton of whitespace, unlike punctuation characters. Curly quotes aren’t like traditional characters. Like full stops, commas and hashes they float within the character space and leave lots of dead white space, making it bloody difficult to manipulate them with CSS. Styles generally fit around text, so cutting into that character is tricky indeed. Also, all that extra white space is going to push into the quote text and make it look pretty uneven. This grab highlights the actual character space: See how this is emphasized when we add a normal alphabetical character within the span. This is what we’re dealing with here: Then, there’s size. Call in a curly quote at less than 300% font-size and it ain’t gonna look very big. The white space it creates will be big enough, but the curlies will be way too small. We need more like 700% (as in this example) to make an impression, but that sure makes for a big character space. Prepare the curlies Firstly, remove the opening “ from the quote. Replace it with the opening curly quote character entity “. Then replace the closing “ with the entity reference for that, which is ”. Now at least the curlies will look nice and swooshy. Add the hooks Two reasons why we aren’t using :first-letter pseudo class to manipulate the curlies. Firstly, only CSS2-friendly browsers would get what we’re doing, and secondly we need to affect the last “letter” of our text also – the closing curly quote. So, add a span around the opening curly, and a second span around the closing curly, giving complete control of the characters: <blockquote><span class="bqstart">“</span>Speech marks. Curly quotes. That annoying thing cool people do with their fingers to emphasize a buzzword, shortly before you hit them.<span class="bqend">”</span></blockquote> So far nothing will look any different, aside form the curlies looking a bit nicer. I know we’ve just added extra markup, but the benefits as far as accessibility are concerned are good enough for me, and of course there are no images to download. The CSS OK, easy stuff first. Our first rule .bqstart floats the span left, changes the color, and whacks the font-size up to an exuberant 700%. Our second rule .bqend does the same tricks aside from floating the curly to the right. .bqstart { float: left; font-size: 700%; color: #FF0000; } .bqend { float: right; font-size: 700%; color: #FF0000; } That gives us this, which is rubbish. I’ve highlighted the actual span area with outlines: Note that the curlies don’t even fit inside the span! At this stage on IE 6 PC you won’t even see the quotes, as it only places focus on what it thinks is in the div. Also, the quote text is getting all spangled. Fiddle with margin and padding Think of that span outline box as a window, and that you need to position the curlies within that window in order to see them. By adding some small adjustments to the margin and padding it’s possible to position the curlies exactly where you want them, and remove the excess white space by defining a height: .bqstart { float: left; height: 45px; margin-top: -20px; padding-top: 45px; margin-bottom: -50px; font-size: 700%; color: #FF0000; } .bqend { float: right; height: 25px; margin-top: 0px; padding-top: 45px; font-size: 700%; color: #FF0000; } I wanted the blocks of my curlies to align with the quote text, whereas you may want them to dig in or stick out more. Be aware however that my positioning works for IE PC and Mac, Firefox and Safari. Too much tweaking seems to break the magic in various browsers at various times. Now things are fitting beautifully: I must admit that the heights, margins and spacing don’t make a lot of sense if you analyze them. This was a real trial and error job. Get it working on Safari, and IE would fail. Sort IE, and Firefox would go weird. Finished The final thing looks ace, can be resized, looks cool without styles, and can be edited with CSS at any time. Here’s a real example (note that I’m specifying Lucida Grande and then Verdana for my curlies): “Speech marks. Curly quotes. That annoying thing cool people do with their fingers to emphasize a buzzword, shortly before you hit them.” Browsers happy As I said, too much tweaking of margins and padding can break the effect in some browsers. Even now, Firefox insists on dropping the closing curly by approximately 6 or 7 pixels, and if I adjust the padding for that, it’ll crush it into the text on Safari or IE. Weird. Still, as I close now it seems solid through resizing tests on Safari, Firefox, Camino, Opera and IE PC and Mac. Lovely. It’s probably not perfect, but together we can beat the evil typographic limitations of the web and walk together towards a brighter, more aligned world. Merry Christmas. 2005 Simon Collison simoncollison 2005-12-21T00:00:00+00:00 https://24ways.org/2005/swooshy-curly-quotes-without-images/ business
34 Collaborative Responsive Design Workflows Much has been written about workflow and designer-developer collaboration in web design, but many teams still struggle with this issue; either with how to adapt their internal workflow, or how to communicate the need for best practices like mobile first and progressive enhancement to their teams and clients. Christmas seems like a good time to have another look at what doesn’t work between us and how we can improve matters. Why is it so difficult? We’re still beginning to understand responsive design workflows, acknowledging the need to move away from static design tools and towards best practices in development. It’s not that we don’t want to change – so why is it so difficult? Changing the way we do something that has become routine is always problematic, even with small things, and the changes today’s web environment requires from web design and development teams are anything but small. Although developers also have a host of new skills to learn and things to consider, designers are probably the ones pushed furthest out of their comfort zones: as well as graphic design, a web designer today also needs an understanding of interaction design and ergonomics, because more and more websites are becoming tools rather than pages meant to be read like a book or magazine. In addition to that there are thousands of different devices and screen sizes on the market today that layout and interactions need to work on. These aspects make it impossible to design in a static design tool, so beyond having to learn about new aspects of design, the designer has to either learn how to code or learn to work with a responsive design tool. Why do it That alone is enough to leave anyone overwhelmed, as learning a new skill takes time and slows you down in a project – and on most projects time is in short supply. Yet we have to make time or fall behind in the industry as others pitch better, interactive designs. For an efficient workflow, both designers and developers must familiarise themselves with new tools and techniques. A designer has to be able to play with ideas, make small adjustments here and there, look at the result, go back to the settings and make further adjustments, and so on. You can only realistically do that if you are able to play with all the elements of a design, including interactivity, accessibility and responsiveness. Figuring out the right breakpoints in a layout is one of the foremost reasons for designing in a responsive design tool. Even if you create layouts for three viewport sizes (i.e. smartphone, tablet and the most common desktop size), you’d only cover around 30% of visitors and you might miss problems like line breaks and padding at other viewport sizes. Another advantage is consistency. In static design tools changes will not be applied across all your other layouts. A developer referring back to last week’s comps might work with outdated metrics. Furthermore, you cannot easily test what impact changes might have on previously designed areas. In a dynamic design tool such changes will be applied to the entire design and allow you to test things in site areas you had already finished. No static design tool allows you to do this, and having somebody else produce a mockup from your static designs or wireframes will duplicate work and is inefficient. How to do it When working in a responsive design tool rather than in the browser, there is still the question of how and when to communicate with the developer. I have found that working with Sass in combination with a visual style guide is very efficient, but it does need careful planning: fundamental metrics for padding, margins and font sizes, but also design elements like sliders, forms, tabs, buttons and navigational elements, should be defined at the beginning of a project and used consistently across the site. Working with a grid can help you develop a consistent design language across your site. Create a visual style guide that shows what the elements look like and how they behave across different screen sizes – and when interacted with. Put all metrics on paddings, margins, breakpoints, widths, colours and so on in a text document, ideally with names that your developer can use as Sass variables in the CSS. For example: $padding-default-vertical: 1.5em; Developers, too, need an efficient workflow to keep code maintainable and speed up the time needed for more complex interactions with an eye on accessibility and performance. CSS preprocessors like Sass allow you to work with variables and mixins for default rules, as well as style sheet partials for different site areas or design elements. Create your own boilerplate to use for your projects and then update your variables with the information from your designer for each individual project. How to get buy-in One obstacle when implementing responsive design, accessibility and content strategy is the logistics of learning new skills and iterating on your workflow. Another is how to sell it. You might expect everyone on a project (including the client) to want to design and develop the best website possible: ultimately, a great site will lead to more conversions. However, we often hear that people find it difficult to convince their teammates, bosses or clients to implement best practices. Why is that? Well, I believe a lot of it is down to how we sell it. You will have experienced this yourself: some people you trust to know what they are talking about, and others you don’t. Think about why you trust that first person but don’t buy what the other one is telling you. It is likely because person A has a self-assured, calm and assertive demeanour, while person B seems insecure and apologetic. To sell our ideas, we need to become person A! For a timid designer or developer suffering from imposter syndrome (like many of us do in this industry) that is a difficult task. So how can we become more confident in selling our expertise? Write We need to become experts. And I mean not just in writing great code or coming up with beautiful designs but at explaining why we’re doing what we’re doing. Why do you code this way or that? Why is this the best layout? Why does a website have to be accessible and responsive? Write about it. Putting your thoughts down on paper or screen is a really efficient way of getting your head around a topic and learning to make a case for something. You may even find that you come up with new ideas as you are writing, so you’ll become a better designer or developer along the way. Talk Then, talk about it. Start out in front of your team, then do a lightning talk at a web event near you, then a longer talk or workshop. Having to talk about a topic is going to help you put into spoken words the argument that you’ve previously put together in writing. Writing comes more easily when you’re starting out but we use a different register when writing than talking and you need to learn how to speak your case. Do the talk a couple of times and after each talk make adjustments where you found it didn’t work well. By this time, you are more than ready to make your case to the client. In fact, you’ve been ready since that first talk in front of your colleagues ;) Pitch Pitches used to be based on a presentation of static layouts for for three to five typical pages and three different designs. But if we want to sell interactivity, structure, usability, accessibility and responsiveness, we need to demonstrate these things and I believe that it can only do us good. I have seen a few pitches sitting in the client’s chair and static layouts are always sort of dull. What makes a website a website is the fact that I can interact with it and smooth interactions or animations add that extra sparkle. I can’t claim personal experience for this one but I’d be bold and go for only one design. One demo page matching the client’s corporate design but not any specific page for the final site. Include design elements like navigation, photography, typefaces, article layout (with real content), sliders, tabs, accordions, buttons, forms, tables (yes, tables) – everything you would include in a style tiles document, only interactive. Demonstrate how the elements behave when clicked, hovered and touched, and how they change across different screen sizes. You may even want to demonstrate accessibility features like tabbed navigation and screen reader use. Obviously, there are many approaches that will work in different situations but don’t give up on finding a process that works for you and that ultimately allows you to build delightful, accessible, responsive user experiences for the web. Make time to try new tools and techniques and don’t just work on them on the side – start using them on an actual project. It is only when we use a tool or process in the real world that we become true experts. Remember your driving lessons: once the instructor had explained how to operate the car, you were sent to practise driving on the road in actual traffic! 2014 Sibylle Weber sibylleweber 2014-12-07T00:00:00+00:00 https://24ways.org/2014/collaborative-responsive-design-workflows/ process
129 Knockout Type - Thin Is Always In OS X has gorgeous native anti-aliasing (although I will admit to missing 10px aliased Geneva — *sigh*). This is especially true for dark text on a light background. However, things can go awry when you start using light text on a dark background. Strokes thicken. Counters constrict. Letterforms fill out like seasonal snackers. So how do we combat the fat? In Safari and other Webkit-based browsers we can use the CSS ‘text-shadow’ property. While trying to add a touch more contrast to the navigation on haveamint.com I noticed an interesting side-effect on the weight of the type. The second line in the example image above has the following style applied to it: This creates an invisible drop-shadow. (Why is it invisible? The shadow is positioned directly behind the type (the first two zeros) and has no spread (the third zero). So the color, black, is completely eclipsed by the type it is supposed to be shadowing.) Why applying an invisible drop-shadow effectively lightens the weight of the type is unclear. What is clear is that our light-on-dark text is now of a comparable weight to its dark-on-light counterpart. You can see this trick in effect all over ShaunInman.com and in the navigation on haveamint.com and Subtraction.com. The HTML and CSS source code used to create the example images used in this article can be found here. 2006 Shaun Inman shauninman 2006-12-17T00:00:00+00:00 https://24ways.org/2006/knockout-type/ code
316 Have Your DOM and Script It Too When working with the XMLHttpRequest object it appears you can only go one of three ways: You can stay true to the colorful moniker du jour and stick strictly to the responseXML property You can play with proprietary – yet widely supported – fire and inject the value of responseText property into the innerHTML of an element of your choosing Or you can be eval() and parse JSON or arbitrary JavaScript delivered via responseText But did you know that there’s a fourth option giving you the best of the latter two worlds? Mint uses this unmentioned approach to grab fresh HTML and run arbitrary JavaScript simultaneously. Without relying on eval(). “But wait-”, you might say, “when would I need to do this?” Besides the example below this technique is handy for things like tab groups that need initialization onload but miss the main onload event handler by a mile thanks to asynchronous scripting. Consider the problem Originally Mint used option 2 to refresh or load new tabs into individual Pepper panes without requiring a full roundtrip to the server. This was all well and good until I introduced the new Client Mode which when enabled allows anyone to view a Mint installation without being logged in. If voyeurs are afoot as Client Mode is disabled, the next time they refresh a pane the entire login page is inserted into the current document. That’s not very helpful so I needed a way to redirect the current document to the login page. Enter the solution Wouldn’t it be cool if browsers interpreted the contents of script tags crammed into innerHTML? Sure, but unfortunately, that just wasn’t meant to be. However like the body element, image elements have an onload event handler. When the image has fully loaded the handler runs the code applied to it. See where I’m going with this? By tacking a tiny image (think single pixel, transparent spacer gif – shudder) onto the end of the HTML returned by our Ajax call, we can smuggle our arbitrary JavaScript into the existing document. The image is added to the DOM, and our stowaway can go to town. <p>This is the results of our Ajax call.</p> <img src="../images/loaded.gif" alt="" onload="alert('Now that I have your attention...');" /> Please be neat So we’ve just jammed some meaningless cruft into our DOM. If our script does anything with images this addition could have some unexpected side effects. (Remember The Fly?) So in order to save that poor, unsuspecting element whose innerHTML we just swapped out from sharing Jeff Goldblum’s terrible fate we should tidy up after ourselves. And by using the removeChild method we do just that. <p>This is the results of our Ajax call.</p> <img src="../images/loaded.gif" alt="" onload="alert('Now that I have your attention...');this.parentNode.removeChild(this);" /> 2005 Shaun Inman shauninman 2005-12-24T00:00:00+00:00 https://24ways.org/2005/have-your-dom-and-script-it-too/ code
27 Putting Design on the Map The web can leave us feeling quite detached from the real world. Every site we make is really just a set of abstract concepts manifested as tools for communication and expression. At any minute, websites can disappear, overwritten by a newfangled version or simply gone. I think this is why so many of us have desires to create a product, write a book, or play with the internet of things. We need to keep in touch with the physical world and to prove (if only to ourselves) that we do make real things. I could go on and on about preserving the web, the challenges of writing a book, or thoughts about how we can deal with the need to make real things. Instead, I’m going to explore something that gives us a direct relationship between a website and the physical world – maps. A map does not just chart, it unlocks and formulates meaning; it forms bridges between here and there, between disparate ideas that we did not know were previously connected. Reif Larsen, The Selected Works of T.S. Spivet The simplest form of map on a website tends to be used for showing where a place is and often directions on how to get to it. That’s an incredibly powerful tool. So why is it, then, that so many sites just plonk in a default Google Map and leave it as that? You wouldn’t just use dark grey Helvetica on every site, would you? Where’s the personality? Where’s the tailored experience? Where is the design? Jumping into design Let’s keep this simple – we all want to be better web folk, not cartographers. We don’t need to go into the history, mathematics or technology of map making (although all of those areas are really interesting to research). For the sake of our sanity, I’m going to gloss over some of the technical areas and focus on the practical concepts. Tiles If you’ve ever noticed a map loading in sections, it’s because it uses tiles that are downloaded individually instead of requiring the user to download everything that they might need. These tiles come in many styles and can be used for anything that covers large areas, such as base maps and data. You’ve seen examples of alternative base maps when you use Google Maps as Google provides both satellite imagery and road maps, both of which are forms of base maps. They are used to provide context for the real world, or any other world for that matter. A marker on a blank page is useless. The tiles are representations of the physical; they do not have to be photographic imagery to provide context. This means you can design the map itself. The easiest way to conceive this is by comparing Google’s road maps with Ordnance Survey road maps. Everything about the two maps is different: the colours, the label fonts and the symbols used. Yet they still provide the exact same context (other maps may provide different context such as terrain contours). Comparison of Google Maps (top) and the Ordnance Survey (bottom). Carefully designing the base map tiles is as important as any other part of the website. The most obvious, yet often overlooked, aspect are aesthetics and branding. Maps could fit in with the rest of the site; for example, by matching the colours and line weights, they can enhance the full design rather than inhibiting it. You’re also able to define the exact purpose of the map, so instead of showing everything you could specify which symbols or labels to show and hide. I’ve not done any real research on the accessibility of base maps but, having looked at some of the available options, I think a focus on the typography of labels and the colour of the various elements is crucial. While you can choose to hide labels, quite often they provide the data required to make sense of the map. Therefore, make sure each zoom level is not too cluttered and shows enough to give context. Also be as careful when choosing the typeface as you are in any other design work. As for colour, you need to pay closer attention to issues like colour-blindness when using colour to convey information. Quite often a spectrum of colour will be used to show data, or to show the topography, so you need to be aware that some people struggle to see colour differences within a spectrum. A nice example of a customised base map can be found on Michael K Owens’ check-in pages: One of Michael K Owens’ check-in pages. As I’ve already mentioned, tiles are not just for base maps: they are also for data. In the screenshot below you can see how Plymouth Marine Laboratory uses tiles to show data with a spectrum of colour. A map from the Marine Operational Ecology data portal, showing data of adult cod in the North Sea. Technical You’re probably wondering how to design the base layers. I will briefly explain the concepts here and give you tools to use at the end of the article. If you’re worried about the time it takes to design the maps, don’t be – you can automate most of it. You don’t need to manually draw each tile for the entire world! We’ve learned the importance of web standards the hard way, so you’ll be glad (and I won’t have to explain the advantages) of the standard for web mapping from the Open Geospatial Consortium (OGC) called the Web Map Service (WMS). You can use conventional file formats for the imagery but you need a way to query for the particular tiles to show for the area and zoom level, that is what WMS does. Features Tiles are great for covering large areas but sometimes you need specific smaller areas. We call these features and they usually consist of polygons, lines or points. Examples include postcode boundaries and routes between places, or even something more dynamic such as borders of nations changing over time. Showing features on a map presents interesting design challenges. If the colour or shape conveys some kind of data beyond geographical boundaries then it needs to be made obvious. This is actually really hard, without building complicated user interfaces. For example, in the image below, is it obvious that there is a relationship between the colours? Does it need a way of showing what the colours represent? Choropleth map showing ranked postcode areas, using ViziCities. Features are represented by means of lines or colors; and the effective use of lines or colors requires more than knowledge of the subject – it requires artistic judgement. Erwin Josephus Raisz, cartographer (1893–1968) Where lots of boundaries are small and close together (such as a high street or shopping centre) will it be obvious where the boundaries are and what they represent? When designing maps, the hardest challenge is dealing with how the data is represented and how it is understood by the user. Technical As you probably gathered, we use WMS for tiles and another standard called the web feature service (WFS) for specific features. I need to stress that the difference between the two is that WMS is for tiling, whereas WFS is for specific features. Both can use similar file formats but should be used for their particular use cases. You may be wondering why you can’t just use a vector format such as KML, GeoJSON (or even SVG) – and you can – but the issue is the same as for WMS: you need a way to query the data to get the correct area and zoom level. User interface There is of course never a correct way to design an interface as there are so many different factors to take into consideration for each individual project. Maps can be used in a variety of ways, to provide simple information about directions or for complex visualisations to explain large amounts of data. I would like to just touch on matters that need to be taken into account when working with maps. As I mentioned at the beginning, there are so many Google Maps on the web that people seem to think that its UI is the only way you can use a map. To some degree we don’t want to change that, as people know how to use them; but does every map require a zoom slider or base map toggle? In fact, does the user need to zoom at all? The answer to that one is generally yes, zooming does provide more context to where the map is zoomed in on. In some cases you will need to let users choose what goes on the map (such as data layers or directions), so how do they show and hide the data? Does a simple drop-down box work, or do you need search? Google’s base map toggle is quite nice since it doesn’t offer many options yet provides very different contexts and styling. It isn’t until we get to this point that we realise just plonking a quick Google map is really quite ridiculous, especially when compared to the amount of effort we make in other areas such as colour, typography or how the CSS is written. Each of these is important but we need to make sure the whole site is designed, and that includes the maps as much as any other content. Putting it into practice I could ramble on for ages about what we can do to customise maps to fit a site’s personality and correctly represent the data. I wanted to focus on concepts and standards because tools constantly change and it is never good to just rely on a tool to do the work. That said, there are a large variety of tools that will help you turn these concepts into reality. This is not a comparison; I just want to show you a few of the many options you have for maps on the web. Google OK, I’ve been quite critical so far about Google Maps but that is only because there is such a large amount of the default maps across the web. You can style them almost as much as anything else. They may not allow you to use custom WMS layers but Google Maps does have its own version, called styled maps. Using an array of map features (in the sense of roads and lakes and landmarks rather than the kind WFS is used for), you can style the base map with JavaScript. It even lets you toggle visibility, which helps to avoid the issue of too much clutter on the map. As well as lacking WMS, it doesn’t support WFS, but it does support GeoJSON and KML so you can still show the features on the map. You should also check out Google Maps Engine (the new version of My Maps), which provides an interface for creating more advanced maps with a selection of different base maps. A premium version is available, essentially for creating map-based visualisations, and it provides a step up from the main Google Maps offering. A useful feature in some cases is that it gives you access to many datasets. Leaflet You have probably seen Leaflet before. It isn’t quite as popular as Google Maps but it is definitely used often and for good reason. Leaflet is a lightweight open source JavaScript library. It is not a service so you don’t have to worry about API throttling and longevity. It gives you two options for tiling, the ability to use WMS, or to directly get the file using variables in the filename such as /{z}/{x}/{y}.png. I would recommend using WMS over dynamic file names because it is a standard, but the ability to use variables in a file name could be useful in some situations. Leaflet has a strong community and a well-documented API. Mapbox As a freemium service, Mapbox may not be perfect for every use case but it’s definitely worth looking into. The service offers incredible customisation tools as well as lots of data sources and hosting for the maps. It also provides plenty of libraries for the various platforms, so you don’t have to only use the maps on the web. Mapbox is a service, though its map design tool is open source. Mapbox Studio is a vector-only version of their previous tool called Tilemill. Earlier I wrote about how typography and colour are as important to maps as they are to the rest of a website; if you thought, “Yes, but how on earth can I design those parts of a map?” then this is the tool for you. It is incredibly easy to use. Essentially each map has a stylesheet. If you do not want to open a paid-for Mapbox account, then you can export the tiles (as PNG, SVG etc.) to use with other map tools. OpenLayers After a long wait, OpenLayers 3 has been released. It is similar to Leaflet in that it is a library not a service, but it has a much broader scope. During the last year I worked on the GIS portal at Plymouth Marine Laboratory (which I used to show the data tiles earlier), it essentially used OpenLayers 2 to create a web-based geographic information system, taking a large amount of data and permitting analysis (such as graphs) without downloading entire datasets and complicated software. OpenLayers 3 has improved greatly on the previous version in both performance and accessibility. It is the ideal tool for complex map-based web apps, though it can be used for the simple use cases too. OpenStreetMap I couldn’t write an article about maps on the web without at least mentioning OpenStreetMap. It is the place to go for crowd-sourced data about any location, with complete road maps and a strong API. ViziCities The newest project on this list is ViziCities by Robin Hawkes and Peter Smart. It is a open source 3-D visualisation tool, currently in the very early stages of development. The basic example shows 3-D buildings around the world using OpenStreetMap data. Robin has used it to create some incredible demos such as real-time London underground trains, and planes landing at an airport. Edward Greer and I are currently working on using ViziCities to show ideal housing areas based on particular personas. We chose it because the 3-D aspect gives us interesting possibilities for the data we are able to visualise (such as bar charts on the actual map instead of in the UI). Despite not being a completely stable, fully featured system, ViziCities is worth taking a look at for some use cases and is definitely going to go from strength to strength. So there you have it – a whistle-stop tour of how maps can be customised. Now please stop plonking in maps without thinking about it and design them as you design the rest of your content. 2014 Shane Hudson shanehudson 2014-12-11T00:00:00+00:00 https://24ways.org/2014/putting-design-on-the-map/ design
298 First Steps in VR The web is all around us. As web folk, it is our responsibility to consider the impact our work can have. Part of this includes thinking about the future; the web changes lives and if we are building the web then we are the ones making decisions that affect people in every corner of the world. I find myself often torn between wanting to make the right decisions, and just wanting to have fun. To fiddle and play. We all know how important it is to sometimes just try ideas, whether they will amount to much or not. I think of these two mindsets as production and prototyping, though of course there are lots of overlap and phases in between. I mention this because virtual reality is currently seen as a toy for rich people, and in some ways at the moment it is. But with WebVR we are able to create interesting experiences with a relatively low entry point. I want us to have open minds, play around with things, and then see how we can use the tools we have at our disposal to make things that will help people. Every year we see articles saying it will be the “year of virtual reality”, that was especially prevalent this year. 2016 has been a year of progress, VR isn’t quite mainstream but with efforts like Playstation VR and Google Cardboard, we are definitely seeing much more of it. This year also saw the consumer editions of the Oculus Rift and HTC Vive. So it does seem to be a good time for an overview of how to get involved with creating virtual reality on the web. WebVR is an API for connecting to devices and retrieving continuous data such as the position and orientation. Unlike the Web Audio API and some other APIs, WebVR does not feel like a framework. You use it however you want, taking the data and using it as you wish. To make it easier, there are plenty of resources such as Three.js, A-Frame and ReactVR that help to make the heavy lifting a bit easier. Getting Started with A-Frame I like taking the opportunity to learn new things whenever I can. So while planning this article I thought that instead of trying to teach WebGL or even Three.js in a way that is approachable for all, I would create my first project using A-Frame and write about that. This is not a tutorial as such, I just want to show how to go about getting involved with VR. The beauty of A-Frame is that it is very similar to web components, you can just write HTML to build worlds that will automatically work on all the different types of devices. It uses WebGL and WebVR but in such a way that it quite drastically reduces the learning curve. That’s not to say you can’t build complex things, you have complete access to write JavaScript and shaders. I’m lazy. Whenever I learn a new language or framework I have found that the best way, personally, for me to learn is to have a project and to copy the starting code from someone else. A project lets you have a good idea of what you want to produce and it means you can ignore a lot of the irrelevant documentation, focussing purely on what you need. That reduces the stress of figuring things out. Copying code also makes it easier, because you know your boilerplate code is working. There’s nothing worse than getting stuck before anything actually works the first time. So I tinker. I take code and I modify it, I play around. It’s fun. For this project I wanted to keep things as simple as possible, so I can easily explain it without the classic “draw a circle then draw an owl”. I wrote a list of requirements, with some stretch goals that you can give a try yourself if you fancy: Must work on Google Cardboard at a minimum, because of price Therefore, it must not rely on having a controller Auto-moving around a maze would be a good example Move in direction you look Stretch goal: Scoring, time until you hit a wall or get stuck in maze Stretch goal: Levels, so the map doesn’t need to be random Stretch goal: Snow! I decided to base this project on an example, Platforms, by Don McCurdy who wrote the really useful aframe-extras. Platforms has random 3D blocks that you can jump onto, going up into the sky. So I took his code and reduced it so that the blocks are randomly spread on the ground. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>24 ways</title> <script src="https://aframe.io/releases/0.3.2/aframe.js"></script> <script src="//cdn.rawgit.com/donmccurdy/aframe-extras/v2.6.1/dist/aframe-extras.min.js"></script> </head> <body> <a-scene> <a-entity id="player" camera universal-controls kinematic-body position="0 1.8 0"> </a-entity> <a-entity id="walls"></a-entity> <a-grid id="ground" static-body></a-grid> <a-sky id="sky" color="#AADDF0"></a-sky> <!-- Lighting --> <a-light type="ambient" color="#ccc"></a-light> </a-scene> <script> document.querySelector('a-scene').addEventListener('render-target-loaded', function () { var MAP_SIZE = 10, PLATFORM_SIZE = 5, NUM_PLATFORMS = 50; var platformsEl = document.querySelector('#walls'); var v, box; for (var i = 0; i < NUM_PLATFORMS; i++) { // y: 0 is ground v = { x: (Math.floor(Math.random() * MAP_SIZE) - PLATFORM_SIZE) * PLATFORM_SIZE, y: PLATFORM_SIZE / 2, z: (Math.floor(Math.random() * MAP_SIZE) - PLATFORM_SIZE) * PLATFORM_SIZE }; box = document.createElement('a-box'); platformsEl.appendChild(box); box.setAttribute('color', '#39BB82'); box.setAttribute('width', PLATFORM_SIZE); box.setAttribute('height', PLATFORM_SIZE); box.setAttribute('depth', PLATFORM_SIZE); box.setAttribute('position', v.x + ' ' + v.y + ' ' + v.z); box.setAttribute('static-body', ''); } console.info('Platforms loaded.'); }); </script> </body> </html> As you can see, this is very readable. Especially if you ignore the JavaScript that is used to create the maze. A-Frame (with A-Frame Extras) gives you a lot of power with relatively little to learn. We start with an <a-scene> which is the container for everything that is going to show up on the screen. There are a few <a-entity> which can be compared to <div> as they are essentially non-semantic containers, able to be used for any purpose. The attributes are used to define functionality, for example the camera attribute sets the entity to function as a camera and kinematic-body makes it collide instead of go through objects. Attributes are also used to set position and sizes, often using JavaScript to dynamically define them. Styling Now we’ve got the HTML written, we need to style it. To do this we add A-Frame compatible attributes such as color and material. I recommend playing around, you can get some quite impressive effects fairly easily. Originally I wanted a light snowy maze but it ended up being dark and foggy, as I really liked the feeling it gave. Note, you will probably need a server running for images to work. You can do this by running python -m "SimpleHTTPServer" in the folder where the code is, then go to localhost:8000 in browser. Textures Unless you are going for a cartoony style, you probably want to find some textures. I found some on textures.com, one image worked well for the walls and the other for the floor. <a-assets> <img id="texture-floor" src="floor.jpg"> <img id="texture-wall" src="wall.jpg"> </a-assets> The <a-assets> is used to define (as well as preload and cache) all assets, including images, audio and video. As you can see, images in the Asset Management System just use normal img tags. The ids are important here as we can use them later for using the textures. To apply a texture to an object, you create a material. For a simple material where it just shows the image, you set the src to the id selector of the image. Replace: <a-grid id="ground" static-body></a-grid> With: <a-grid id="ground" static-body material="src: #texture-floor"></a-grid> This will automatically make the image repeat over the entire floor, in my case filling it with bricks. The walls are pretty much identical, with the slight exception that it is set in JavaScript as they are dynamically defined. box.setAttribute('material', 'src: #texture-wall'); That’s it for the textures, for now at least. These will not look completely realistic, as the light will bump off the rectangular wall rather than texture itself. This can be improved by using maps, textures that are used to modify the shape and physical properties of the object. Lighting The next part of styling is lighting. By using fog and different types of lighting, we are able to add atmospheric details to the game to make it feel that bit more realistic and polished. There are lots of types of light in A-Frame (most coming from Three.js). You can add a light either by using the <a-light> entity or by attaching a light attribute to any other entity. If there are no lights defined then A-Frame adds some by default so that the scene is always lit. To start with I wanted to light up the scene with a general light, type="ambient", so that the whole game felt slightly dark. I chose to set the light to a reddish colour #92455E. After playing around with intensity I chose 0.4, it added enough light to get the feeling I wanted without it being overly red. I also added a blue skybox (<a-sky>), as it looked a bit odd with a white sky. <a-light type="ambient" color="#92455E" intensity="0.4"></a-light> <a-sky id="sky" color="#0000ff"></a-sky> I felt that the maze looked good with a red tinge but it was a bit flat, everything was the same colour and it was a bit dark. So I added a light within the #player entity, this could have been as an attribute but I set it as a child a-light instead. By using type="point" with a high intensity and low distance, it showed close walls as being lighter. It also added a sort-of object to the player, it isn’t a walking human or anything but by moving light where the player is it feels a bit more physical. <a-light color="#fff" distance="5" intensity="0.7" type="point"></a-light> By this point it was starting to look decent, so I wanted to add the fog to really give some personality and depth to the maze. To do this I added the fog attribute to the <a-scene> with type=exponential so it looks thicker the further away it is and a mid intensity, so you feel a bit lost but can still see. I was very happy with this result. It took a lot of playing around with colours and values, which is fun in itself. I highly recommend you take the code (or write your own) and play around with the numbers. Movement One of the reasons I decided to use aframe-extras is that it has a few different camera controls built in. As you saw earlier, I am using the universal-controls which gives WASD (keyboard) controls by default. I wanted to make it automatically move in the direction that you’re looking, but I wasn’t quite sure how without rewriting the controls. So I asked Don McCurdy for advice and he very nicely gave me a small snippet of code to get it working. AFRAME.registerComponent('automove-controls', { init: function () { this.speed = 0.1; this.isMoving = true; this.velocityDelta = new THREE.Vector3(); }, isVelocityActive: function () { return this.isMoving; }, getVelocityDelta: function () { this.velocityDelta.z = this.isMoving ? -speed : 0; return this.velocityDelta.clone(); } }); Replace: universal-controls With: universal-controls="movementControls: automove, gamepad, keyboard" This works by creating a component automove-controls that adds auto-move to the player without overriding movement completely. It doesn’t even touch direction, it just checks if isMoving is true then moves the player by the set speed. Components can be creating for adding all kinds of functionality with relative ease. It makes it very powerful for people of all difficulty levels. Building a map Currently the maze is created randomly, which is great but means there will often be walls that overlap or the player gets trapped with nowhere to go. So to solve this, I decided to use a map editor (Tiled) so that we can create the mazes ourselves. This is a great start towards one of the stretch goals, levels. I made the maze in Tiled by finding a random tileset online (we don’t need to actually show the images), I used one tile for the wall and another for the player. Then I exported as a JavaScript file and modified it in my text editor to get rid of everything I didn’t need. I made it so 0 is the path, 1 is the wall and 2 is the player. I then added the script to the HTML, as a separate file so it’s easy to update in the future. var map = { "data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], "height":10, "width":10 } As you can see, this gives a simple 10x10 maze with some dead ends. The player starts in the bottom right corner (my choice, could be anywhere). I rewrote the random platforms code (from Don’s example) to instead loop over the map data and place walls where it is 1 and position the player where data is 2. I set the position so that the origin of the map would be 0,1.5,0. The y axis is in this case the height (ground being 0), but if a wall is positioned at 0 by its centre then some of it is underground. So the y needed to be the height divided by 2. document.querySelector('a-scene').addEventListener('render-target-loaded', function () { var WALL_SIZE = 5, WALL_HEIGHT = 3; var el = document.querySelector('#walls'); var wall; for (var x = 0; x < map.height; x++) { for (var y = 0; y < map.width; y++) { var i = y*map.width + x; var position = (x-map.width/2)*WALL_SIZE + ' ' + 1.5 + ' ' + (y-map.height/2)*WALL_SIZE; if (map.data[i] === 1) { // Create wall wall = document.createElement('a-box'); el.appendChild(wall); wall.setAttribute('color', '#fff'); wall.setAttribute('material', 'src: #texture-wall;'); wall.setAttribute('width', WALL_SIZE); wall.setAttribute('height', WALL_HEIGHT); wall.setAttribute('depth', WALL_SIZE); wall.setAttribute('position', position); wall.setAttribute('static-body', '); } if (map.data[i] === 2) { // Set player position document.querySelector('#player').setAttribute('position', position); } } } console.info('Walls added.'); }); With this added, it makes it nice and easy to change around the map as well as to add new features. Perhaps you want monsters or objects. Just set the number in the map data and add an if statement to the loop. In the future you could add layers, so multiple things can be in the same position. Or perhaps even make the maze go up the y axis too, with ramps or staircases. There’s a lot you can do with relative ease. As you can see, A-Frame really does reduce the learning curve of 3D and VR on the web. It’s Not All Fun And Games A lot of examples of virtual reality are games, including this one. So it is understandable to think that VR is for gaming, but actually that’s just a tiny subset. There are all sorts of applications for VR, including story telling, data visualisation and even meditation. There have been a number of cases where it has been shown virtual reality can help as a tool for therapies: Oxford study finds virtual reality can help treat severe paranoia Virtual Reality Therapy for Phobias at the Duke Faculty Practice Bravemind: Virtual Reality Exposure Therapy at the University of Southern California These are just a few examples of where virtual reality is being used around the world to help people feel better and get through some very tough times. There have also been examples of it being used for simulating war zones or medical situations, both as a teaching and journalism tool. Wrapping Up Ten years ago, on this very site, Cameron Moll wrote an article explaining the mobile web. He explained how mobile phones with data plans were becoming increasingly common, that WAP 2.0 included the XHTML Mobile Profile meaning it would be familiar with web folk. “The mobile web is rapidly becoming an XHTML environment, and thus you and I can apply our existing “desktop web” skills to understand how to develop content for it.” We can look at that and laugh a little, we have come a very long way in the last decade. Even people in developing countries with very little money have mobile phones with access to a web that is far more capable than the “desktop web” Cameron was referring to. So while I am not saying virtual reality is going to change the world or replace our phones, who knows! We can use our skills as web folk to dabble, we don’t need to learn any new languages. If on the 2026 edition of 24 ways, somebody references this article and looks at how far we have come… well, let’s hope we have used our skills well and made the world just that little bit better. And if VR is a fad? Well it’s fun… have a go anyway. 2016 Shane Hudson shanehudson 2016-12-11T00:00:00+00:00 https://24ways.org/2016/first-steps-in-vr/ code
211 Automating Your Accessibility Tests Accessibility is one of those things we all wish we were better at. It can lead to a bunch of questions like: how do we make our site better? How do we test what we have done? Should we spend time each day going through our site to check everything by hand? Or just hope that everyone on our team has remembered to check their changes are accessible? This is where automated accessibility tests can come in. We can set up automated tests and have them run whenever someone makes a pull request, and even alongside end-to-end tests, too. Automated tests can’t cover everything however; only 20 to 50% of accessibility issues can be detected automatically. For example, we can’t yet automate the comparison of an alt attribute with an image’s content, and there are some screen reader tests that need to be carried out by hand too. To ensure our site is as accessible as possible, we will still need to carry out manual tests, and I will cover these later. First, I’m going to explain how I implemented automated accessibility tests on Elsevier’s ecommerce pages, and share some of the lessons I learnt along the way. Picking the right tool One of the hardest, but most important parts of creating our automated accessibility tests was choosing the right tool. We began by investigating aXe CLI, but soon realised it wouldn’t fit our requirements. It couldn’t check pages that required a visitor to log in, so while we could test our product pages, we couldn’t test any customer account pages. Instead we moved over to Pa11y. Its beforeScript step meant we could log into the site and test pages such as the order history. The example below shows the how the beforeScript step completes a login form and then waits for the login to complete before testing the page: beforeScript: function(page, options, next) { // An example function that can be used to make sure changes have been confirmed before continuing to run Pa11y function waitUntil(condition, retries, waitOver) { page.evaluate(condition, function(err, result) { if (result || retries < 1) { // Once the changes have taken place continue with Pa11y testing waitOver(); } else { retries -= 1; setTimeout(function() { waitUntil(condition, retries, waitOver); }, 200); } }); } // The script to manipulate the page must be run with page.evaluate to be run within the context of the page page.evaluate(function() { const user = document.querySelector('#login-form input[name="email"]'); const password = document.querySelector('#login-form input[name="password"]'); const submit = document.querySelector('#login-form input[name="submit"]'); user.value = 'user@example.com'; password.value = 'password'; submit.click(); }, function() { // Use the waitUntil function to set the condition, number of retries and the callback waitUntil(function() { return window.location.href === 'https://example.com'; }, 20, next); }); } The waitUntil callback allows the test to be delayed until our test user is successfully logged in. Another thing to consider when picking a tool is the type of error messages it produces. aXe groups all elements with the same error together, so the list of issues is a lot easier to read, and it’s easier to identify the most commons problems. For example, here are some elements that have insufficient colour contrast: Violation of "color-contrast" with 8 occurrences! Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds. Correct invalid elements at: - #maincontent > .make_your_mark > div:nth-child(2) > p > span > span - #maincontent > .make_your_mark > div:nth-child(4) > p > span > span - #maincontent > .inform_your_decisions > div:nth-child(2) > p > span > span - #maincontent > .inform_your_decisions > div:nth-child(4) > p > span > span - #maincontent > .inform_your_decisions > div:nth-child(6) > p > span > span - #maincontent > .inform_your_decisions > div:nth-child(8) > p > span > span - #maincontent > .inform_your_decisions > div:nth-child(10) > p > span > span - #maincontent > .inform_your_decisions > div:nth-child(12) > p > span > span For details, see: https://dequeuniversity.com/rules/axe/2.5/color-contrast aXe also provides links to their site where they discuss the best way to fix the problem. In comparison, Pa11y lists each individual error which can lead to a very verbose list. However, it does provide helpful suggestions of how to fix problems, such as suggesting an alternative shade of a colour to use: • Error: This element has insufficient contrast at this conformance level. Expected a contrast ratio of at least 4.5:1, but text in this element has a contrast ratio of 2.96:1. Recommendation: change text colour to #767676. ⎣ WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail ⎣ #maincontent > div:nth-child(10) > div:nth-child(8) > p > span > span ⎣ <span style="color:#969696">Featured products:</span> Integrating into our build pipeline We decided the perfect time to run our accessibility tests would be alongside our end-to-end tests. We have a Jenkins job that detects changes to our staging site and then triggers the end-to-end tests, and in turn our accessibility tests. Our Jenkins job retrieves the contents of a GitHub repository containing our Pa11y script file and npm package manifest. Once Jenkins has cloned the repository, it installs any dependencies and executes the tests via: npm install && npm test Bundling the URLs to be tested into our test script means we don’t have a command line style test where we list each URL we wish to test in the Jenkins CLI. It’s an effective method but can also be cluttered, and obscure which URLs are being tested. In the middle of the office we have a monitor displaying a Jenkins dashboard and from this we can see if the accessibility tests are passing or failing. Everyone in the team has access to the Jenkins logs and when the build fails they can see why and fix the issue. Fixing the issues As mentioned earlier, Pa11y can generate a long list of areas for improvement which can be very verbose and quite overwhelming. I recommend going through the list to see which issues occur most frequently and fix those first. For example, we initially had a lot of errors around colour contrast, and one shade of grey in particular. By making this colour darker, the number of errors decreased, and we could focus on the remaining issues. Another thing I like to do is to tackle the quick fixes, such as adding alt text to images. These are small things that allow us to make an impact instantly, giving us time to fix more detailed concerns such as addressing tabindex issues, or speaking to our designers about changing the contrast of elements on the site. Manual testing Adding automated tests to check our site for accessibility is great, but as I mentioned earlier, this can only cover 20-50% of potential issues. To improve on this, we need to test by hand too, either by ourselves or by asking others. One way we can test our site is to throw our mouse or trackpad away and interact with the site using only a keyboard. This allows us to check items such as tab order, and ensure menu items, buttons etc. can be used without a mouse. The commands may be different on different operating systems, but there are some great guides online for learning more about these. It’s tempting to add alt text and aria-labels to make errors go away, but if they don’t make any sense, what use are they really? Using a screenreader we can check that alt text accurately represents the image. This is also a great way to double check that our ARIA roles make sense, and that they correctly identify elements and how to interact with them. When testing our site with screen readers, it’s important to remember that not all screen readers are the same and some may interact with our site differently to others. Consider asking a range of people with different needs and abilities to test your site, too. People experience the web in numerous ways, be they permanent, temporary or even situational. They may interact with your site in ways you hadn’t even thought about, so this is a good way to broaden your knowledge and awareness. Tips and tricks One of our main issues with Pa11y is that it may find issues we don’t have the power to solve. A perfect example of this is the one pixel image Facebook injects into our site. So, we wrote a small function to go though such errors and ignore the ones that we cannot fix. const test = pa11y({ .... hideElements: '#ratings, #js-bigsearch', ... }); const ignoreErrors: string[] = [ '<img src="https://books.google.com/intl/en/googlebooks/images/gbs_preview_button1.gif" border="0" style="cursor: pointer;" class="lightbox-is-image">', '<script type="text/javascript" id="">var USI_orderID=google_tag_mana...</script>', '<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=123456789012345&ev=PageView&noscript=1">' ]; const filterResult = result => { if (ignoreErrors.indexOf(result.context) > -1) { return false; } return true; }; Initially we wanted to focus on fixing the major problems, so we added a rule to ignore notices and warnings. This made the list or errors much smaller and allowed us focus on fixing major issues such as colour contrast and missing alt text. The ignored notices and warnings can be added in later after these larger issues have been resolved. const test = pa11y({ ignore: [ 'notice', 'warning' ], ... }); Jenkins gotchas While using Jenkins we encountered a few problems. Sometimes Jenkins would indicate a build had passed when in reality it had failed. This was because Pa11y had timed out due to PhantomJS throwing an error, or the test didn’t go past the first URL. Pa11y has recently released a new beta version that uses headless Chrome instead of PhantomJS, so hopefully these issues will less occur less often. We tried a few approaches to solve these issues. First we added error handling, iterating over the array of test URLs so that if an unexpected error happened, we could catch it and exit the process with an error indicating that the job had failed (using process.exit(1)). for (const url of urls) { try { console.log(url); let urlResult = await run(url); urlResult = urlResult.filter(filterResult); urlResult.forEach(result => console.log(result)); } catch (e) { console.log('Error:', e); process.exit(1); } } We also had issues with unhandled rejections sometimes caused by a session disconnecting or similar errors. To avoid Jenkins indicating our site was passing with 100% accessibility, when in reality it had not executed any tests, we instructed Jenkins to fail the job when an unhandled rejection or uncaught exception occurred: process.on('unhandledRejection', (reason, p) => { console.log('Unhandled Rejection at:', p, 'reason:', reason); process.exit(1); }); process.on('uncaughtException', (err) => { console.log('Caught exception: ${err}n'); process.exit(1); }); Now it’s your turn That’s it! That’s how we automated accessibility testing for Elsevier ecommerce pages, allowing us to improve our site and make it more accessible for everyone. I hope our experience can help you automate accessibility tests on your own site, and bring the web a step closer to being accessible to all. 2017 Seren Davies serendavies 2017-12-07T00:00:00+00:00 https://24ways.org/2017/automating-your-accessibility-tests/ code
295 Internet of Stranger Things This year I’ve been running a workshop about using JavaScript and Node.js to work with all different kinds of electronics on the Raspberry Pi. So especially for 24 ways I’m going to show you how I made a very special Raspberry Pi based internet connected project! And nothing says Christmas quite like a set of fairy lights connected to another dimension1. What you’ll see You can rig up the fairy lights in your home, with the scrawly letters written under each one. The people from the other side (i.e. the internet) will be able to write messages to you from their browser in real time. In fact why not try it now; check this web page. When you click the lights in your browser, my lights (and yours) will turn on and off in real life! (There may be a queue if there are lots of people accessing it, hit the “Send a message” button and wait your turn.) It’s all done with JavaScript, using Node.js running on both the Raspberry Pi and on the server. I’m using WebSockets to communicate in real time between the browser, server and Raspberry Pi. What you’ll need Raspberry Pi any of the following models: Zero (will need straight male header pins soldered2 and Micro USB OTG adaptor), A+, B+, 2, or 3 Micro SD card at least 4Gb Class 10 speed3 Micro USB power supply at least 2A USB Wifi dongle (unless you have a Pi 3 - that has wifi built in). Addressable fairy lights Logic level shifter (with pins soldered unless you want to do it!) Breadboard Jumper wires (3x male to male and 4x female to male) Optional but recommended Base board to hold the Pi and Breadboard (often comes with a breadboard!) Find links for where to buy all of these items that goes along with this tutorial. The total price should be around $1004. Setting up the Raspberry Pi You’ll need to install the SD card for the Raspberry Pi. You’ll find a link to download a disk image on the support document, ready-made with the Raspbian version of Linux, along with Node.js and all the files you need. Download it and write it to the SD card using the fantastic free software Etcher5. Next up you have to configure the wifi details on the SD card. If you plug the card into your computer you should see a drive called BOOT. There’s a text file on there called wpa_supplicant.conf. Open it up in your favourite text editor and replace mywifi and mypassword with your wifi details6. network={ ssid="mywifi" psk="mypassword" } Save the file, eject the card from your computer and plug it into the Raspberry Pi. If you have a base board or holder for the Raspberry Pi, attach it now. Then connect the wifi USB dongle7 and power supply, but don’t plug it in yet! Wiring! Time to wire everything up! First of all, push the Logic Level Converter into the middle of the breadboard: Logic Level Converter The logic level converter may be labelled differently from the one in the diagram but the pins are usually exactly the same internally. I would just make sure the pins marked HV (High Voltage) are on the bottom and LV (Low Voltage) are on the top. Raspberry Pi pins only output 3.3v but the lights need 5v. That’s why we need the logic level converter in there to boost up the signal. Connect the first two wires between the Raspberry Pi pins and the breadboard: Note that the pins on the Raspberry Pi are male, so you need a female to male jumper wire to connect between them and the breadboard. The colours don’t have to match but it’s easier to follow (and check) if you use the same ones as in the diagram. Then the next two: This is what you should have so far: Lights Now to connect the lights! My ones have a connector with three holes in it that I can push jumper wires into, and hopefully yours will too! So I used the male-to-male jumper wires to connect them to the breadboard. Make sure that you connect the right end of the lights, mine has a male connector at the wrong end so it’s impossible to do this, but double check. Also make sure that the holes in the light connector are the same as mine. To do this, follow the wires from the connector to the first light and look at the circuit board inside. You should just about be able to make out the connections labelled + (sometimes 5V, V+ or VCC), GND (or ‘-’ or G) and DI (sometimes DIN for data in). You can just about make out the +, DI and GND on this picture. Note that on the other side of the board there is a DO for data out - that’s what takes the data along to the chip in the next light. Make sure that you’re plugging into the data-in and not the data-out! That’s it! Everything’s plugged in and ready to go! But before you plug power into your Pi, double check all your wires and make sure they’re exactly right! You could damage your Raspberry Pi if it is not wired correctly. So triple check! The Moment of Truth! Plug in the Raspberry Pi and wait around a minute or two for it to boot up. If all is well, the lights should strobe rainbow colours for one second - that’s your confirmation that it’s connected to my WebSocket server and ready to receive messages from the upside-down! However, if the first light in the string is pulsing red, it means that you’re not connected to the internet. So check the Troubleshooting section of the support document. If it’s pulsing green then you’re connected to the internet but can’t connect to my server. It must have gone down. Sorry! The code will keep trying so leave it running and maybe it’ll come back up. Rig up the lights! Fix the lights up on the wall however you want, pins, nails, tape. I’ve used cable clips. Just be careful! I’m using a 50 light string so I’ve programmed it to use the lights at the end for the letters. That way I have just under half the string to extend down to the floor where I can keep the Raspberry Pi. Check the photo here to see how the lights line up, note that there are spare unused lights in-between each row: Now visit lights.seb.ly and you’ll see this : If you’re the only one online you’ll have direct connection to the lights and any letter you click on will light up both in the browser and in real life. If there are other people there, you’ll need to click the button to join the queue and wait your turn. How it works - the geeky details! Electronics: The pins on the Raspberry Pi are known as GPIO pins, general-purpose input/output. You can connect a wide variety of electronic components to them, LED lights, buttons, switches, and sensors. You can turn the power to the pins on and off using Node.js (or Python, if you prefer). Addressable LEDs or “Neopixels” We’re only using one GPIO pin on the Raspberry Pi (the other connections are 5V, 3.3V and ground) and that single pin is controlling all of the lights in the string. The code turns the pin on and off really fast in strictly timed morse-code-like dots and dashes to transmit binary data. The chips attached to each LED decode the binary and adjust the output to the LED accordingly. That chip then sends the data on to the next light in the string. The chips on each light are the WS2811, part of the WS281x family that come in a multitude of different form factors and are often packaged with tiny LEDs in a single component. They are commonly referred to as Neopixels8 and I used them on my Laser Light Synths project. Neopixels with the chip and the LED all in one - it’s the white square shaped component and the darker square inside is the chip. These are only 5mm wide! A Laser Light Synth! Covered with around 800 super bright neopixels! Logic Level Converter The logic level converter is a really cheap and easy way to change the level from 3.3v to 5v and back again. You must be careful that you do not connect 5v into a GPIO pin or you will most likely damage the Raspberry Pi processor chip. Power Neopixels can often draw a lot of current so you need to be careful how you power them. I’ve measured the current draw from the string to be less than 800mA so you should be fine wired directly to the 5V output. But if you use more lights or have them all on really bright at once, you’ll need to use a separate 5V power supply. If you want to learn more, check out Adafruit’s Neopixel Uberguide. Node.js There are two Node.js apps running here, one on the Raspberry Pi and one on my server. You can see the code on my GitHub at github.com/sebleedelisle/stranger-lights for the Raspberry Pi and github.com/sebleedelisle/stranger-lights-server for the server. And they’re hosted on npm as stranger-lights and stranger-lights-server. The server side code sets up a standard web server to deliver the HTML for the web interface. It also sets up a WebSocket server that allows for real-time communication between the browser and the server. This server code also manages the queue and who is in control of the lights at any given time. WebSockets I’m using the excellent Socket.io library to manage the WebSocket connection. Both the browser and the Raspberry Pi Node.js app connects to my WebSocket server. When you click on a letter in the browser, a message is sent to the server, which forwards it to the connected Raspberry Pi clients and also all the web browsers9. The Raspberry Pi code The Node.js app runs automatically on startup, and I made this happen by adding this to the /etc/rc.local file: node /home/pi/strangerthings/client.js > /dev/null & Anything in the rc.local file gets executed when the Pi boots up and this line of code runs the Node.js app and routes its output to nowhere (ie /dev/null). The & means that it runs it in the background and doesn’t hold up the boot process. Working with the Raspberry Pi headless You might know that when a computer has no screen or keyboard, you would refer to it as “running headless”. So just like most web servers, you need to configure it over the network with ssh10. If you’re on a mac you can find your Pi on the network through the name raspberrypi.local11, otherwise you’ll need to find its IP address. There’s more on the guide to Remote Access instructions on the Raspberry Pi website. And if you’re very new to the terminal, I highly recommend this great online Linux command line tutorial. Improvements This is quite an early experiment and I’m sure I’ll discover lots of optimisations over the next few weeks, especially if the server gets a proper hammering today! But there are a few things you can do. Obviously I’ve just rigged up my lights with Post-it notes. It’d be a lot nicer to get a paint brush and try to recreate the Winona-in-a-manic-state text style. Where next? Finding quality resources about Node.js for electronics on the Pi can be somewhat hit and miss, but this is getting better all the time. Alternatively I am thinking about running some online courses, please let me know if that’s something you’d be interested in, or sign up to my mailing list at st4i.com. There are many many more resources for the Raspberry Pi with Python (gpiozero is a good place to start), so if that language works for you, you’ll be spoilt for choice! Also take a look at Arduino - it’s an incredibly popular platform for electronics and the internet is literally bursting with resources. I hope you enjoyed this little foray into the world of JavaScript electronics on the Raspberry Pi! If you get this working at home please let me know! Tweet me at @seb_ly. Not a particularly original idea, but I don’t think I’ve seen anyone do it quite like this before, ie using WebSockets, and Node.js on a Raspberry Pi. Other examples: Internet of Stranger Things, Strangerlights.com, and loads of examples on Instructables ↩︎ Video guide to soldering pins on to a Pi Zero and further soldering advice from Adafruit ↩︎ Slower cards will work but performance may suffer ↩︎ Or £5,000 in UK money. Sorry, Brexit joke :) ↩︎ You will need a card reader on your computer - most micro SD cards come with an adaptor that fits standard SD slots.  ↩︎ SSID and password should be all that you need but you can see all the config options on this wpa supplicant guide ↩︎ Raspberry Pi Zero will require the OTG to USB adaptor to attach the wifi dongle ↩︎ Thanks to Adafruit who invented the term neopixels so we don’t have to refer to them as WS281x any more! ↩︎ So you can see other people sending messages in the browser ↩︎ ssh is short for Secure Shell and is a way to connect to a remote computer and type in it just like you would in the terminal. ↩︎ You can change this default hostname using raspi-config ↩︎ 2016 Seb Lee-Delisle sebleedelisle 2016-12-01T00:00:00+00:00 https://24ways.org/2016/internet-of-stranger-things/ code
221 “Probably, Maybe, No”: The State of HTML5 Audio With the hype around HTML5 and CSS3 exceeding levels not seen since 2005’s Ajax era, it’s worth noting that the excitement comes with good reason: the two specifications render many years of feature hacks redundant by replacing them with native features. For fun, consider how many CSS2-based rounded corners hacks you’ve probably glossed over, looking for a magic solution. These days, with CSS3, the magic is border-radius (and perhaps some vendor prefixes) followed by a coffee break. CSS3’s border-radius, box-shadow, text-shadow and gradients, and HTML5’s <canvas>, <audio> and <video> are some of the most anticipated features we’ll see put to creative (ab)use as adoption of the ‘new shiny’ grows. Developers jumping on the cutting edge are using subsets of these features to little detriment, in most cases. The more popular CSS features are design flourishes that can degrade nicely, but the current audio and video implementations in particular suffer from a number of annoyances. The new shiny: how we got here Sound involves one of the five senses, a key part of daily life for most – and yet it has been strangely absent from HTML and much of the web by default. From a simplistic perspective, it seems odd that HTML did not include support for the full multimedia experience earlier, despite the CD-ROM-based craze of the early 1990s. In truth, standards like HTML can take much longer to bake, but eventually deliver the promise of a lowered barrier to entry, consistent implementations and shiny new features now possible ‘for free’ just about everywhere. <img> was introduced early and naturally to HTML, despite having some opponents at the time. Perhaps <audio> and <video> were avoided, given the added technical complexity of decoding various multi-frame formats, plus the hardware and bandwidth limitations of the era. Perhaps there were quarrels about choosing a standard format or – more simply – maybe these elements just weren’t considered to be applicable to the HTML-based web at the time. In any event, browser plugins from programs like RealPlayer and QuickTime eventually helped to fill the in-page audio/video gap, handling <object> and <embed> markup which pointed to .wav, .avi, .rm or .mov files. Suffice it to say, the experience was inconsistent at best and, on the standards side of the fence right now, so is HTML5 in terms of audio and video. : the theory As far as HTML goes, the code for <audio> is simple and logical. Just as with <img>, a src attribute specifies the file to load. Pretty straightforward – sounds easy, right? <audio src="mysong.ogg" controls> <!-- alternate content for unsupported case --> Download <a href="mysong.ogg">mysong.ogg</a>; </audio> Ah, if only it were that simple. The first problem is that the OGG audio format, while ‘free’, is not supported by some browsers. Conversely, nor is MP3, despite being a de facto standard used in all kinds of desktop software (and hardware). In fact, as of November 2010, no single audio format is commonly supported across all major HTML5-enabled browsers. What you end up writing, then, is something like this: <audio controls> <source src="mysong.mp3" /> <source src="mysong.ogg" /> <!-- alternate content for unsupported case, maybe Flash, etc. --> Download <a href="mysong.ogg">mysong.ogg</a> or <a href="mysong.mp3">mysong.mp3</a> </audio> Keep in mind, this is only a ‘first class’ experience for the HTML5 case; also, for non-supported browsers, you may want to look at another inline player (object/embed, or a JavaScript plus Flash API) to have inline audio. You can imagine the added code complexity in the case of supporting ‘first class’ experiences for older browsers, too. : the caveats With <img>, you typically don’t have to worry about format support – it just works – and that’s part of what makes a standard wonderful. JPEG, PNG, BMP, GIF, even TIFF images all render just fine if for no better reason, perhaps, than being implemented during the ‘wild west’ days of the web. The situation with <audio> today reflects a very different – read: business-aware – environment in 2010. (Further subtext: There’s a lot of [potential] money involved.) Regrettably, this is a collision of free and commercial interests, where the casualty is ultimately the user. Second up in the casualty list is you, the developer, who has to write additional code around this fragmented support. The HTML5 audio API as implemented in JavaScript has one of the most un-computer-like responses I’ve ever seen, and inspired the title of this post. Calling new Audio().canPlayType('audio/mp3'), which queries the system for format support according to a MIME type, is supposed to return one of “probably”, “maybe”, or “no”. Sometimes, you’ll just get a null or empty string, which is also fun. A “maybe” response does not guarantee that a format will be supported; sometimes audio/mp3 gives “maybe,” but then audio/mpeg; codecs="mp3" will give a more-solid “probably” response. This can vary by browser or platform, too, depending on native support – and finally, the user may also be able to install codecs, extending support to include other formats. (Are you excited yet?) Damn you, warring formats! New market and business opportunities go hand-in-hand with technology developments. What we have here is certainly not failure to communicate; rather, we have competing parties shouting loudly in public in attempts to influence mindshare towards a de facto standard for audio and video. Unfortunately, the current situation means that at least two formats are effectively required to serve the majority of users correctly. As it currently stands, we have the free and open source software camp of OGG Vorbis/WebM and its proponents (notably, Mozilla, Google and Opera in terms of browser makers), up against the non-free, proprietary and ‘closed’ camp of MP3 and MPEG4/HE-AAC/H.264 – which is where you’ll find commitments from Apple and Microsoft, among others. Apple is likely in with H.264 for the long haul, given its use of the format for its iTunes music store and video offerings. It is generally held that H.264 is a technically superior format in terms of file size versus quality, but it involves intellectual property and, in many use cases, requires licensing fees. To be fair, there is a business model with H.264 and much has been invested in its development, but this approach is not often the kind that wins over the web. On that front, OGG/WebM may eventually win for being a ‘free’ format that does not involve a licensing scheme. Closed software and tools ideologically clash with the open nature of the web, which exists largely thanks to free and open technology. Because of philosophical and business reasons, support for audio and video is fragmented across browsers adopting HTML5 features. It does not help that a large amount of audio and video currently exists in non-free MP3 and MPEG-4 formats. Adoption of <audio> and <video> may be slowed, since it is more complex than <img> and may feel ‘broken’ to developers when edge cases are encountered. Furthermore, the HTML5 spec does not mandate a single required format. The end result is that, as a developer, you must currently provide at least both MP3 and OGG, for example, to serve most existing HTML5-based user agents. Transitioning to There will be some growing pains as developers start to pick up the new HTML5 shiny, while balancing the needs of current and older agents that don’t support either <audio> or the preferred format you may choose (for example, MP3). In either event, Flash or other plugins can be used as done traditionally within HTML4 documents to embed and play the relevant audio. The SoundManager 2 page player demo in action. Ideally, HTML5 audio should be used whenever possible with Flash as the backup option. A few JavaScript/Flash-based audio player projects exist which balance the two; in attempting to tackle this problem, I develop and maintain SoundManager 2, a JavaScript sound API which transparently uses HTML5 Audio() and, if needed, Flash for playing audio files. The internals can get somewhat ugly, but the transition between HTML4 and HTML5 is going to be just that – and even with HTML5, you will need some form of format fall-back in addition to graceful degradation. It may be safest to fall back to MP3/MP4 formats for inline playback at this time, given wide support via Flash, some HTML5-based browsers and mobile devices. Considering the amount of MP3/MP4 media currently available, it is wiser to try these before falling through to a traditional file download process. Early findings Here is a brief list of behavioural notes, annoyances, bugs, quirks and general weirdness I have found while playing with HTML5-based audio at time of writing (November 2010): Apple iPad/iPhone (iOS 4, iPad 3.2+) Only one sound can be played at a time. If a second sound starts, the first is stopped. No auto-play allowed. Sounds follow the pop-up window security model and can only be started from within a user event handler such as onclick/touch, and so on. Otherwise, playback attempts silently fail. Once started, a sequence of sounds can be created or played via the ‘finish’ event of the previous sound (for example, advancing through a playlist without interaction after first track starts). iPad, iOS 3.2: Occasional ‘infinite loop’ bug seen where audio does not complete and stop at a sound’s logical end – instead, it plays again from the beginning. Might be specific to example file format (HE-AAC) encoded from iTunes. Apple Safari, OS X Snow Leopard 10.6.5 Critical bug: Safari 4 and 5 intermittently fail to load or play HTML5 audio on Snow Leopard due to bug(s) in QuickTime X and/or other underlying frameworks. Known Apple ‘radar’ bug: bugs.webkit.org #32159 (see also, test case.) Amusing side note: Safari on Windows is fine. Apple Safari, Windows Food for thought: if you download “Safari” alone on Windows, you will not get HTML5 audio/video support (tested in WinXP). You need to download “Safari + QuickTime” to get HTML5 audio/video support within Safari. (As far as I’m aware, Chrome, Firefox and Opera either include decoders or use system libraries accordingly. Presumably IE 9 will use OS-level APIs.) General Quirks Seeking and loading, ‘progress’ events, and calculating bytes loaded versus bytes total should not be expected to be linear, as users can arbitrarily seek within a sound. It appears that some support for HTTP ranges exists, which adds a bit of logic to UI code. Browsers seem to vary slightly in their current implementations of these features. The onload event of a sound may be of little relevance, if non-linear loading is involved (see above note re: seeking). Interestingly (perhaps I missed it), the current spec does not seem to specify a panning or left/right channel mix option. The preload attribute values may vary slightly between browsers at this time. Upcoming shiny: HTML5 Audio Data API With access to audio data, you can incorporate waveform and spectrum elements that make your designs react to music. The HTML5 audio spec does a good job covering the basics of playback, but did not initially get into manipulation or generation of audio on-the-fly, something Flash has had for a number of years now. What if JavaScript could create, monitor and change audio dynamically, like a sort of audio <canvas> element? With that kind of capability, many dynamic audio processing features become feasible and, when combined with other media, can make for some impressive demos. What started as a small idea among a small group of audio and programming enthusiasts grew to inspire a W3C audio incubator group, and continued to establish the Mozilla Audio Data API. Contributors wrote a patch for Firefox which was reviewed and revised, and is now slated to be in the public release of Firefox 4. Some background and demos are also detailed in an article from the BBC R&D blog. There are plenty of live demos to see, which give an impression of the new creative ideas this API enables. Many concepts are not new in themselves, but it is exciting to see this sort of thing happening within the native browser context. Mozilla is not alone in this effort; the WebKit folks are also working on a JavaScriptAudioNode interface, which implements similar audio buffering and sample elements. The future? It is my hope that we’ll see a common format emerge in terms of support across the major browsers for both audio and video; otherwise, support will continue to be fragmented and mildly frustrating to develop for, and that can impede growth of the feature. It’s a big call, but if <img> had lacked a common format back in the wild west era, I doubt the web would have grown to where it is today. Complaints and nitpicks aside, HTML5 brings excellent progress on the browser multimedia front, and the first signs of native support are a welcome improvement given all audio and video previously relied on plugins. There is good reason to be excited. While there is room for more, support could certainly be much worse – and as tends to happen with specifications, the implementations targeting them should improve over time. Note: Thanks to Nate Koechley, who suggested the Audio().canPlayType() response be part of the article title. 2010 Scott Schiller scottschiller 2010-12-08T00:00:00+00:00 https://24ways.org/2010/the-state-of-html5-audio/ code
255 Inclusive Considerations When Restyling Form Controls I would like to begin by saying 2018 was the year that we, as developers, visual designers, browser implementers, and inclusive design and experience specialists rallied together and achieved a long-sought goal: We now have the ability to fully style form controls, across all modern browsers, while retaining their ease of declaration, native functionality and accessibility. I would like to begin by saying all these things. However, they’re not true. I think we spent the year debating about what file extension CSS should be written in, or something. Or was that last year? Maybe I’m thinking of next year. Returning to reality, styling form controls is more tricky and time consuming these days rather than flat out “hard”. In fact, depending on the length of the styling-leash a particular browser provides, there are controls you can style quite a bit. As for browsers with shorter leashes, there are other options to force their controls closer to the visual design you’re tasked to match. However, when striving for custom styled controls, one must be careful not to forget about the inherent functionality and accessibility that many provide. People expect and deserve the products and services they use and pay for to work for them. If these services are visually pleasing, but only function for those who fit the handful of personas they’ve been designed for, then we’ve potentially deprived many people the experiences they deserve. Quick level setting Getting down to brass tacks, when creating custom styled form controls that should retain their expected semantics and functionality, we have to consider the following: Many form elements can be styled directly through standard and browser specific selectors, as well as through some clever styling of markup patterns. We should leverage these native options before reinventing any wheels. It is important to preserve the underlying semantics of interactive controls. We must not unintentionally exclude people who use assistive technologies (ATs) that rely on these semantics. Make sure you test what you create. There is a lot of underlying complexity to form controls which may not be immediately apparent if they’re judged solely by their visual presentation in a single browser, or with limited AT testing. Visually resetting and restyling form controls Over the course of 2018, I worked on a project where I tested and reported on the accessibility impact of styling various form controls. In conducting my research, I reviewed many of the form controls available in HTML, testing to see how malleable they were to direct styling from standardized CSS selectors. As I expected, controls such as the various text fields could be restyled rather easily. However, other controls like radio buttons and checkboxes, or sub-elements of special text fields like date, search, and number spinners were resistant to standard-based styling. These particular controls and their sub-elements required specific pseudo-elements to reset and allow for restyling of some of their default presentation. See the Pen form control styling comparisons by Scott (@scottohara) on CodePen. https://codepen.io/scottohara/pen/gZOrZm/ Over the years, the ability to directly style form controls has been something many people have clamored for. However, one should realize the benefits of being able to restyle some of these controls may involve more effort than originally anticipated. If you want to restyle a control from the ground up, then you must also recreate any :active, :focus, and :hover states for the control—all those things that were previously taken care of by browsers. Not only that, but anything you restyle should also work with Windows High Contrast mode, styling for dark mode, and other OS-level settings that browser respect without you even realizing. You ever try playing with the accessibility settings of your display on macOS, or similar Windows setting? It is also worth mentioning that any browser prefixed pseudo-elements are not standardized CSS selectors. As MDN mentions at the top of their pages documenting these pseudo-elements: Non-standard This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future. While this may be a deterrent for some, it’s my opinion the risks are often only skin-deep. By which I mean if a non-standard selector does change, the control may look a bit quirky, but likely won’t cease to function. A bug report which requires a CSS selector change can be an easy JIRA ticket to close, after all. Can’t make it? Fake it. Internet Explorer 11 (IE11) is still neck-and-neck with other browsers in vying for the number 2 spot in desktop browser share. Due to IE not recognizing vendor-prefixed appearance properties, some essential controls like checkboxes won’t render as intended. Additionally, some controls like select boxes, file uploads, and sub-elements of date fields (calendar popups) cannot be modified by just relying on styling their HTML selectors alone. This means that unless your company designs and develops with a progressive enhancement, or graceful degradation mindset, you’ll need to take a different approach in styling. Getting clever with markup and CSS The following CodePen demonstrates how we can create a custom checkbox markup pattern. By mindfully utilizing CSS sibling selectors and positioning of the native control, we can create custom visual styling while also retaining the functionality and accessibility expectations of a native checkbox. See the Pen Accessible Styled Native Checkbox by Scott (@scottohara) on CodePen. https://codepen.io/scottohara/pen/RqEayN/ Customizing checkboxes by visually hiding the input and styling well-placed markup with sibling selectors may seem old hat to some. However, many variations of these patterns do not take into account how their method of visually hiding the checkboxes can create discovery issues for certain screen reader navigation methods. For instance, if someone is using a mobile device and exploring by touch, how will they be able to drag their finger over an input that has been reduced to a single pixel, or positioned off screen? As we move away from the simplicity of declaring a single HTML element and using clever CSS and markup patterns to create restyled form controls, we increase the need for additional testing to ensure no expected behaviors are lost. In other words, what should work in theory may not work in practice when you introduce the various different ways people may engage with a form control. It’s worth remembering: what might be typical interactions for ourselves may be problematic if not impossible for others. Limitations to cleverness Creative coding will allow us to apply more consistent custom styles to some of the more problematic form controls. There will be a varied amount of custom markup, CSS, and sometimes JavaScript that will be needed to preserve the control’s inherent usability and accessibility for each control we take this approach to. However, this method of restyling still doesn’t solve for the lack of feature parity across different browsers. Nor is it a means to account for controls which don’t have a native HTML element equivalent, such as a switch or multi-thumb range slider? Maybe there’s a control that calls for a visual design or proposed user experience that would require too much fighting with a native control’s behavior to be worth the level of effort to implement. Here’s where we need to take another approach. Using ARIA when appropriate Sometimes we have no other option than to roll up our sleeves and start building custom form controls from scratch. Fair warning though: just because we’re not leveraging a native HTML control as our foundation, it doesn’t mean we have carte blanche to throw semantics out the window. Enter Accessible Rich Internet Applications (ARIA). ARIA is a set of attributes that can modify existing elements, or extend HTML to include roles, properties and states that aren’t native to the language. While divs and spans have no meaningful semantic information for us to leverage, with help from the ARIA specification and ARIA Authoring Practices we can incorporate these elements to help create the UI that we need while still following the first rule of Using ARIA: If you can use a native HTML element or attribute with the semantics and behavior you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so. By using these documents as guidelines, and testing our custom controls with people of various abilities, we can do our best to make sure a custom control performs as expected for as many people as possible. Exceptions to the rule One example of a control that allows for an exception to the first rule of Using ARIA would be a switch control. Switches and checkboxes are similar components, in that they have both on/checked and off/unchecked states. However, checkboxes are often expected within the context of forms, or used to filter search queries on e-commerce sites. Switches are typically used to instantly enable or deactivate a particular setting at a component or app-based level, as this is their behavior in the native mobile apps in which they were popularized. While a switch control could be created by visually restyling a checkbox, this does not automatically mean that the underlying semantics and functionality will match the visual representation of the control. For example, the following CodePen restyles checkboxes to look like a switch control, but the semantics of the checkboxes remain which communicate a different way of interacting with the control than what you might expect from a native switch control. See the Pen Switch Boxes - custom styled checkboxes posing as switches by Scott (@scottohara) on CodePen. https://codepen.io/scottohara/pen/XyvoeE/ By adding a role="switch" to these checkboxes, we can repurpose the inherent checked/unchecked states of the native control, it’s inherent ability to be focused by Tab key, and Space key to toggle state. But while this is a valid approach to take in building a switch, how does this actually match up to reality? Does it pass the test(s)? Whether deconstructing form controls to fully restyle them, or leveraging them and other HTML elements as a base to expand on, or create, a non-native form control, building it is just the start. We must test that what we’ve restyled or rebuilt works the way people expect it to, if not better. What we must do here is run a gamut of comparative tests to document the functionality and usability of native form controls. For example: Is the control implemented in all supported browsers? If not: where are the gaps? Will it be necessary to implement a custom solution for the situations that degrade to a standard text field? If so: is each browser’s implementation a good user experience? Is there room for improvement that can be tested against the native baseline? Test with multiple input devices. Where the control is implemented, what is the quality of the user experience when using different input devices, such as mouse, touchscreen, keyboard, speech recognition or switch device, to name a few. You’ll find some HTML5 controls (like date pickers and number spinners) have additional UI elements that may not be announced to AT, or even allow keyboard accessibility. Often these controls can be adjusted by other means, such as text entry, or using arrow keys to increase or decrease values. If restyling or recreating a custom version of a control like these, it may make sense to maintain these native experiences as well. How well does the control take to custom styles? If a control can be styled enough to not need to be rebuilt from scratch, that’s great! But make sure that there are no adverse affects on the accessibility of it. For instance, range sliders can be restyled and maintain their functionality and accessibility. However, elements like progress bars can be negatively affected by direct styling. Always test with different browser and AT pairings to ensure nothing is lost when controls are restyled. Do specifications match reality? If recreating controls to get around native limitations, such as the inability to style the options of a select element, or requiring a Switch control which is not native to HTML, do your solutions match user expectations? For instance, selects have unique picker interfaces on touch devices. And switches have varied levels of support for different browser and screen reader pairings. Test with real people, and check your analytics. If these experiences don’t match people’s expectations, then maybe another solution is in order? Wrapping up While styling form controls is definitely easier than it’s ever been, that doesn’t mean that it’s at all simple, nor will it likely ever be. The level of difficulty you’re going to face is going to depend entirely on what it is you’re hoping to style, add-on to, or recreate. And even if you build your custom control exactly to specification, you’ll still be reliant on browsers and assistive technologies being able to fully understand the component they’ve been presented. Forms and their controls are an incredibly important part of what we need the Internet for. Paying bills, scheduling appointments, ordering groceries, renewing your license or even ordering gifts for the holidays. These are all important tasks that people should be able to complete with as little effort as possible. Especially since for some, completing these tasks online might be their only option. 2018 didn’t end up being the year we got full customization of form controls sorted out. But that’s OK. If we can continue to mindfully work with what we have, and instead challenge ourselves to follow inclusive design principles, well thought out Form Design Patterns, and solve problems with an accessibility first approach, we may come to realize that we can get along just fine without fully branded drop downs. And hey. There’s always next year, right? 2018 Scott O'Hara scottohara 2018-12-13T00:00:00+00:00 https://24ways.org/2018/inclusive-considerations-when-restyling-form-controls/ code
276 Your jQuery: Now With 67% Less Suck Fun fact: more websites are now using jQuery than Flash. jQuery is an amazing tool that’s made JavaScript accessible to developers and designers of all levels of experience. However, as Spiderman taught us, “with great power comes great responsibility.” The unfortunate downside to jQuery is that while it makes it easy to write JavaScript, it makes it easy to write really really f*&#ing bad JavaScript. Scripts that slow down page load, unresponsive user interfaces, and spaghetti code knotted so deep that it should come with a bottle of whiskey for the next sucker developer that has to work on it. This becomes more important for those of us who have yet to move into the magical fairy wonderland where none of our clients or users view our pages in Internet Explorer. The IE JavaScript engine moves at the speed of an advancing glacier compared to more modern browsers, so optimizing our code for performance takes on an even higher level of urgency. Thankfully, there are a few very simple things anyone can add into their jQuery workflow that can clear up a lot of basic problems. When undertaking code reviews, three of the areas where I consistently see the biggest problems are: inefficient selectors; poor event delegation; and clunky DOM manipulation. We’ll tackle all three of these and hopefully you’ll walk away with some new jQuery batarangs to toss around in your next project. Selector optimization Selector speed: fast or slow? Saying that the power behind jQuery comes from its ability to select DOM elements and act on them is like saying that Photoshop is a really good tool for selecting pixels on screen and making them change color – it’s a bit of a gross oversimplification, but the fact remains that jQuery gives us a ton of ways to choose which element or elements in a page we want to work with. However, a surprising number of web developers are unaware that all selectors are not created equal; in fact, it’s incredible just how drastic the performance difference can be between two selectors that, at first glance, appear nearly identical. For instance, consider these two ways of selecting all paragraph tags inside a <div> with an ID. $("#id p"); $("#id").find("p"); Would it surprise you to learn that the second way can be more than twice as fast as the first? Knowing which selectors outperform others (and why) is a pretty key building block in making sure your code runs well and doesn’t frustrate your users waiting for things to happen. There are many different ways to select elements using jQuery, but the most common ways can be basically broken down into five different methods. In order, roughly, from fastest to slowest, these are: $("#id"); This is without a doubt the fastest selector jQuery provides because it maps directly to the native document.getElementbyId() JavaScript method. If possible, the selectors listed below should be prefaced with an ID selector in conjunction with jQuery’s .find() method to limit the scope of the page that has to be searched (as in the $("#id").find("p") example shown above). $("p");, $("input");, $("form"); and so on Selecting elements by tag name is also fast, since it maps directly to the native document.getElementsByTagname() method. $(".class"); Selecting by class name is a little trickier. While still performing very well in modern browsers, it can cause some pretty significant slowdowns in IE8 and below. Why? IE9 was the first IE version to support the native document.getElementsByClassName() JavaScript method. Older browsers have to resort to using much slower DOM-scraping methods that can really impact performance. $("[attribute=value]"); There is no native JavaScript method for this selector to use, so the only way that jQuery can perform the search is by crawling the entire DOM looking for matches. Modern browsers that support the querySelectorAll() method will perform better in certain cases (Opera, especially, runs these searches much faster than any other browser) but, generally speaking, this type of selector is Slowey McSlowersons. $(":hidden"); Like attribute selectors, there is no native JavaScript method for this one to use. Pseudo-selectors can be painfully slow since the selector has to be run against every element in your search space. Again, modern browsers with querySelectorAll() will perform slightly better here, but try to avoid these if at all possible. If you must use one, try to limit the search space to a specific portion of the page: $("#list").find(":hidden"); But, hey, proof is in the performance testing, right? It just so happens that said proof is sitting right here. Be sure to notice the class selector numbers beside IE7 and 8 compared to other browsers and then wonder how the people on the IE team at Microsoft manage to sleep at night. Yikes. Chaining Almost all jQuery methods return a jQuery object. This means that when a method is run, its results are returned and you can continue executing more methods on them. Rather than writing out the same selector multiple times over, just making a selection once allows multiple actions to be run on it. Without chaining $("#object").addClass("active"); $("#object").css("color","#f0f"); $("#object").height(300); With chaining $("#object").addClass("active").css("color", "#f0f").height(300); This has the dual effect of making your code shorter and faster. Chained methods will be slightly faster than multiple methods made on a cached selector, and both ways will be much faster than multiple methods made on non-cached selectors. Wait… “cached selector”? What is this new devilry? Caching Another easy way to speed up your code that seems to be a mystery to developers is the idea of caching your selectors. Think of how many times you end up writing the same selector over and over again in any project. Every $(".element") selector has to search the entire DOM each time, regardless of whether or not that selector had been previously run. Running the selection once and then storing the results in a variable means that the DOM only has to be searched once. Once the results of a selector have been cached, you can do anything with them. First, run your search (here we’re selecting all of the <li> elements inside <ul id="blocks">): var blocks = $("#blocks").find("li"); Now, you can use the blocks variable wherever you want without having to search the DOM every time. $("#hideBlocks").click(function() { blocks.fadeOut(); }); $("#showBlocks").click(function() { blocks.fadeIn(); }); My advice? Any selector that gets run more than once should be cached. This jsperf test shows just how much faster a cached selector runs compared to a non-cached one (and even throws some chaining love in to boot). Event delegation Event listeners cost memory. In complex websites and apps it’s not uncommon to have a lot of event listeners floating around, and thankfully jQuery provides some really easy methods for handling event listeners efficiently through delegation. In a bit of an extreme example, imagine a situation where a 10×10 cell table needs to have an event listener on each cell; let’s say that clicking on a cell adds or removes a class that defines the cell’s background color. A typical way that this might be written (and something I’ve often seen during code reviews) is like so: $('table').find('td').click(function() { $(this).toggleClass('active'); }); jQuery 1.7 has provided us with a new event listener method, .on(). It acts as a utility that wraps all of jQuery’s previous event listeners into one convenient method, and the way you write it determines how it behaves. To rewrite the above .click() example using .on(), we’d simply do the following: $('table').find('td').on('click',function() { $(this).toggleClass('active'); }); Simple enough, right? Sure, but the problem here is that we’re still binding one hundred event listeners to our page, one to each individual table cell. A far better way to do things is to create one event listener on the table itself that listens for events inside it. Since the majority of events bubble up the DOM tree, we can bind a single event listener to one element (in this case, the <table>) and wait for events to bubble up from its children. The way to do this using the .on() method requires only one change from our code above: $('table').on('click','td',function() { $(this).toggleClass('active'); }); All we’ve done is moved the td selector to an argument inside the .on() method. Providing a selector to .on() switches it into delegation mode, and the event is only fired for descendants of the bound element (table) that match the selector (td). With that one simple change, we’ve gone from having to bind one hundred event listeners to just one. You might think that the browser having to do one hundred times less work would be a good thing and you’d be completely right. The difference between the two examples above is staggering. (Note that if your site is using a version of jQuery earlier than 1.7, you can accomplish the very same thing using the .delegate() method. The syntax of how you write the function differs slightly; if you’ve never used it before, it’s worth checking the API docs for that page to see how it works.) DOM manipulation jQuery makes it very easy to manipulate the DOM. It’s trivial to create new nodes, insert them, remove other ones, move things around, and so on. While the code to do this is simple to write, every time the DOM is manipulated, the browser has to repaint and reflow content which can be extremely costly. This is no more evident than in a long loop, whether it be a standard for() loop, while() loop, or jQuery $.each() loop. In this case, let’s say we’ve just received an array full of image URLs from a database or Ajax call or wherever, and we want to put all of those images in an unordered list. Commonly, you’ll see code like this to pull this off: var arr = [reallyLongArrayOfImageURLs]; $.each(arr, function(count, item) { var newImg = '<li><img src="'+item+'"></li>'; $('#imgList').append(newImg); }); There are a couple of problems with this. For one (which you should have already noticed if you’ve read the earlier part of this article), we’re making the $("#imgList") selection once for each iteration of our loop. The other problem here is that each time the loop iterates, it’s adding a new <li> to the DOM. Each of those insertions is going to be costly, and if our array is quite large then this could lead to a massive slowdown or even the dreaded ‘A script is causing this page to run slowly’ warning. var arr = [reallyLongArrayOfImageURLs], tmp = ''; $.each(arr, function(count, item) { tmp += '<li><img src="'+item+'"></li>'; }); $('#imgList').append(tmp); All we’ve done here is create a tmp variable that each <li> is added to as it’s created. Once our loop has finished iterating, that tmp variable will contain all of our list items in memory, and can be appended to our <ul> all in one go. Browsers work much faster when working with objects in memory rather than on screen, so this is a much faster, more CPU-cycle-friendly method of building a list. Wrapping up These are far from being the only ways to make your jQuery code run better, but they are among the simplest ones to implement. Though each individual change may only make a few milliseconds of difference, it doesn’t take long for those milliseconds to add up. Studies have shown that the human eye can discern delays of as few as 100ms, so simply making a few changes sprinkled throughout your code can very easily have a noticeable effect on how well your website or app performs. Do you have other jQuery optimization tips to share? Leave them in the comments and help make us all better. Now go forth and make awesome! 2011 Scott Kosman scottkosman 2011-12-13T00:00:00+00:00 https://24ways.org/2011/your-jquery-now-with-less-suck/ code
277 Raising the Bar on Mobile One of the primary challenges of designing for mobile devices is that screen real estate is often in limited supply. Through the advocacy of Luke W and others, we’ve drawn comfort from the idea that this constraint ends up benefiting users and designers alike, from obvious advantages like portability and reach, to influencing our content strategy decisions through focus and restraint. But that doesn’t mean we shouldn’t take advantage of every last pixel of that screen we can snag! As anyone who has designed a website for use on a smartphone can attest, there’s an awful lot of space on mobile screens dedicated to browser functions that would be better off toggled out of view. Unfortunately, the visibility of some of these elements is beyond our control, such as the buttons fixed to the bottom of the viewport in iOS’s Safari and the WebOS browser. However, in many devices, the address bar at the top can be manually hidden, and its absence frees up enough pixel room for a large, impactful heading, a critical piece of navigation, or even just a little more white space to air things out. So, as my humble contribution to this most festive of web publications, today I’ll dig into the approach I used to hide the address bar in a browser-agnostic fashion for sites like BostonGlobe.com, and the jQuery Mobile framework. Surveying the land First, let’s assess the chromes of some popular, current mobile browsers. For example purposes, the following screen-captures feature the homepage of the Boston Globe site, without any address-bar-hiding logic in place. Note: these captures are just mockups – actual experience on these platforms may vary. On the left is iOS5’s Safari (running on iPhone), and on the right is Windows Phone 7 (pre-Mango). BlackBerry 7 (left), and Android 2.3 (right). WebOS (left), Opera Mini (middle), and Opera Mobile (right). Some browsers, such the default browsers on WebOS and BlackBerry 5, hide the bar automatically without any developer intervention, but many of them don’t. Of these, we can only manually hide the address bar on iOS Safari and Android (according to Opera Web Opener, Mike Taylor, some discussion is underway for support in Opera Mini and Mobile as well, which would be great!). This is unfortunate, but iOS and Android are incredibly popular, so let’s direct our focus there. Great API, or greatest API? As it turns out, iOS and Android not only allow you to hide the address bar, they use the same JavaScript method to do so, too (this shouldn’t be surprising, given that they are both WebKit browsers, but nothing expected happens in mobile). However, the method they use is not exactly intuitive. You might set out looking for a JavaScript API dedicated to this purpose, like, say, window.toolbar.hide(), but alas, to hide the address bar you need to use the window.scrollTo method! window.scrollTo(0, 0); The scrollTo method is not new, it’s just this particular use of it that is. For the uninitiated, scrollTo is designed to scroll a document to a particular set of coordinates, assuming the document is large enough to scroll to that spot. The method accepts two arguments: a left coordinate; and a top coordinate. It’s both simple and supported well pretty much everywhere. In iOS and Android, these coordinates are calculated from the top of the browser’s viewport, just below the address bar (interestingly, it seems that some platforms like BlackBerry 6 treat the top of the browser chrome as 0 instead, meaning the page content is closer to 20px from the top). Anyway, by passing the coordinates 0, 0 to the scrollTo method, the browser will jump to the top of the page and pull the address bar out of view! Of course, if a quick call to scrollTo was all we need to do to hide the address bar in iOS and Android, this article would be pretty short, and nothing new. Unfortunately, the first issue we need to deal with is that this method alone will not usually do the trick: it must be called after the page has finished loading. The browser gives us a load event for just that purpose, so we’ll wrap our scrollTo method in it and continue on our merry way! We’ll use the standard, addEventListener method to bind the the load event, passing arguments for event name load, and a callback function to execute when the event is triggered. window.addEventListener("load",function() { window.scrollTo(0, 0); }); For the sake of preventing errors in those using browsers that don’t support addEventListener, such as Internet Explorer 8 and under, let’s make sure that method exists before we use it: if( window.addEventListener ){ window.addEventListener("load",function() { window.scrollTo(0, 0); }); } Now we’re getting somewhere, but we must also call the method after the load event’s default behavior has been applied. For this, we can use the setTimeout method, delaying its execution to after the load event has run its course. if( window.addEventListener ){ window.addEventListener("load",function() { setTimeout(function(){ window.scrollTo(0, 0); }, 0); }); } Sweet sugar of Christmas! Hit this demo in iOS and watch that address bar drift up and away! Not so fast… We’ve got a little problem: the approach above does work in iOS but, in some cases, it works a little too well. In the process of applying this behavior, we’ve broken one of the primary tenets of responsible web development: don’t break the browser’s default behaviour. This usability rule of thumb is often violated by developers with even the best of intentions, from breaking the browser’s back button through unrecorded Ajax page refreshes, to fancy momentum touch scrolling scripts that can wreak havoc in all but the most sophisticated of devices. In this case, we’ve prevented the browser’s native support of deep-linking to sections of a page (a hash identifier in the URL matching a page element’s id attribute, for example, http://example.com#contact) from working properly, because our script always scrolls to the top. To avoid this collision, we’ll need to detect whether a deep link, or hash, is present in the URL before applying our logic. We can do this by ensuring that the location.hash property is falsey: if( !window.location.hash && window.addEventListener ){ window.addEventListener( "load",function() { setTimeout(function(){ window.scrollTo(0, 0); }, 0); }); } Still works great! And a quick test using a hash-based URL confirms that our script will not execute when a deep anchor is in play. Now iOS is looking sharp, and we’ve added our feature defensively to avoid conflicts. Now, on to Android… Wait. You didn’t expect that we could write code for one browser and be finished, right? Of course you didn’t. I mentioned earlier that Android uses the same method for getting rid of the scrollbar, but I left out the fact that the arguments it prefers vary slightly, but significantly, from iOS. Bah! Differering from the earlier logic from iOS, to remove the address bar on Android’s default browser, you need to pass a Y coordinate of 1 instead of 0. Aside from being just plain odd, this is particularly unfortunate because to any other browser on the planet, 1px is a very real, however small, distance from the top of the page! window.scrollTo( 0, 1 ); Looks like we’re going to need a fork… R UA Android? At this point, some developers might decide to simply not support this feature in Android, and more determined devs might decide that a quick check of the User Agent string would be a reliable way to determine the browser and tweak the scroll value accordingly. Neither of those decisions would be tragic, but in the spirit of cross-browser and future-friendly development, I’ll propose an alternative. By this point, it should be clear that neither of the implementations above offer a particularly intuitive way to hide an address bar. As such, one might be skeptical that these approaches will stick around very long in their present state in either browser. Perhaps at some point, Android will decide to use 0 like iOS, making our lives a little easier, or maybe some new browser will decide to model their address bar hiding method after one of these implementations. In any case, detecting the User Agent only allows us to apply logic based on the known present, and in the world of mobile, let’s face it, the present is already the past. Writing a check In this next step of today’s technique, we’ll apply some logic to quickly determine the behavior model of the browser we’re using, then capitalize on that model – without caring which browser it happens to come from – by applying the appropriate scroll distance. To do this, we’ll rely on a fortunate side effect of Android’s implementation, which is when you programatically scroll the page to 1 using scrollTo, Android will report that it’s still at 0 because oddly enough, it is! Of course, any other browser in this situation will report a scroll distance of 1. Thus, by scrolling the page to 1, then asking the browser its scroll distance, we can use this artifact of their wacky implementation to our advantage and scroll to the location that makes sense for the browser in play. Getting the scroll distance To pull off our test, we’ll need to ask the browser for its current scroll distance. The methods for getting scroll distance are not entirely standardized across popular browsers, so we’ll need to use some cross-browser logic. The following scroll distance function is similar to what you’d find in a library like jQuery. It checks the few common ways of getting scroll distance before eventually falling back to 0 for safety’s sake (that said, I’m unaware of any browsers that won’t return a numeric value from one of the first three properties). // scrollTop getter function getScrollTop(){ return scrollTop = window.pageYOffset || document.compatMode === "CSS1Compat" && document.documentElement.scrollTop || document.body.scrollTop || 0; } In order to execute that code above, the body object (referenced here as document.body) will need to be defined already, or we’ll risk an error. To determine that it’s defined, we can run a quick timer to execute code as soon as that object is defined and ready for use. var bodycheck = setInterval(function(){ if( document.body ){ clearInterval( bodycheck ); //more logic can go here!! } }, 15 ); Above, we’ve defined a 15 millisecond interval called bodycheck that checks if document.body is defined and, if so, clears itself of running again. Within that if statement, we can extend our logic further to run other code, such as our check for the scroll distance, defined via the variable scrollTop below: var scrollTop, bodycheck = setInterval(function(){ if( document.body ){ clearInterval( bodycheck ); scrollTop = getScrollTop(); } }, 15 ); With this working, we can immediately scroll to 1, then check the scroll distance when the body is defined. If the distance reports 1, we’re likely in a non-Android browser, so we’ll scroll back to 0 and clean up our mess. window.scrollTo( 0, 1 ); var scrollTop, bodycheck = setInterval(function(){ if( document.body ){ clearInterval( bodycheck ); scrollTop = getScrollTop(); window.scrollTo( 0, scrollTop === 1 ? 0 : 1 ); } }, 15 ); Cashing in All of the pieces are written now, so all we need to do is combine them with our previous logic for scrolling when the window is loaded, and we’ll have a cross-browser solution of which John Resig would be proud. Here’s our combined code snippet, with some formatting updates rolled in as well: (function( win ){ var doc = win.document; // If there’s a hash, or addEventListener is undefined, stop here if( !location.hash && win.addEventListener ){ //scroll to 1 window.scrollTo( 0, 1 ); var scrollTop = 1, getScrollTop = function(){ return win.pageYOffset || doc.compatMode = "CSS1Compat" && doc.documentElement.scrollTop || doc.body.scrollTop || 0; }, //reset to 0 on bodyready, if needed bodycheck = setInterval(function(){ if( doc.body ){ clearInterval( bodycheck ); scrollTop = getScrollTop(); win.scrollTo( 0, scrollTop = 1 ? 0 : 1 ); } }, 15 ); win.addEventListener( “load”, function(){ setTimeout(function(){ //reset to hide addr bar at onload win.scrollTo( 0, scrollTop === 1 ? 0 : 1 ); }, 0); } ); } })( this ); View code example And with that, we’ve got a bunch more room to play with on both iOS and Android. Break out the eggnog …because we’re not done yet! In the spirit of making our script act more defensively, there’s still another use case to consider. It was essential that we used the window’s load event to trigger our scripting, but on pages with a lot of content, its use can come at a cost. Often, a user will begin interacting with a page, scrolling down as they read, before the load event has fired. In those situations, our script will jump the user back to the top of the page, resulting in a jarring experience. To prevent this problem from occurring, we’ll need to ensure that the page has not been scrolled beyond a certain amount. We can add a simple check using our getScrollTop function again, this time ensuring that its value is not greater than 20 pixels or so, accounting for a small tolerance. if( getScrollTop() < 20 ){ //reset to hide addr bar at onload window.scrollTo( 0, scrollTop === 1 ? 0 : 1 ); } And with that, we’re pretty well protected! Here’s a final demo. The completed script can be found on Github (full source: https://gist.github.com/1183357 ). It’s MIT licensed. Feel free to use it anywhere or any way you’d like! Your thoughts? I hope this article provides you with a browser-agnostic approach to hiding the address bar that you can use in your own projects today. Perhaps alternatively, the complications involved in this approach convinced you that doing this well is more trouble than it’s worth and, depending on the use case, that could be a fair decision. But at the very least, I hope this demonstrates that there’s a lot of work involved in pulling off this small task in only two major platforms, and that there’s a real need for standardization in this area. Feel free to leave a comment or criticism and I’ll do my best to answer in a timely fashion. Thanks, everyone! Some parting notes I scream, you scream… At the time of writing, I was not able to test this method on the latest Android 4.0 (Ice Cream Sandwich) build. According to Sencha Touch’s browser scorecard, the browser in 4.0 may have a different way of managing the address bar, so I’ll post in the comments once I get a chance to dig into it further. Short pages get no love Today’s technique only works when the page is as tall, or taller than, the device’s available screen height, so that the address bar may be scrolled out of view. On a short page, you might work around this issue by applying a minimum height to the body element ( body { min-height: 460px; } ), but given the variety of screen sizes out there, not to mention changes in orientation, it’s tough to find a value that makes much sense (unless you manipulate it with JavaScript). 2011 Scott Jehl scottjehl 2011-12-20T00:00:00+00:00 https://24ways.org/2011/raising-the-bar-on-mobile/ design
42 An Overview of SVG Sprite Creation Techniques SVG can be used as an icon system to replace icon fonts. The reasons why SVG makes for a superior icon system are numerous, but we won’t be going over them in this article. If you don’t use SVG icons and are interested in knowing why you may want to use them, I recommend you check out “Inline SVG vs Icon Fonts” by Chris Coyier – it covers the most important aspects of both systems and compares them with each other to help you make a better decision about which system to choose. Once you’ve made the decision to use SVG instead of icon fonts, you’ll need to think of the best way to optimise the delivery of your icons, and ways to make the creation and use of icons faster. Just like bitmaps, we can create image sprites with SVG – they don’t look or work exactly alike, but the basic concept is pretty much the same. There are several ways to create SVG sprites, and this article will give you an overview of three of them. While we’re at it, we’re going to take a look at some of the available tools used to automate sprite creation and fallback for us. Prerequisites The content of this article assumes you are familiar with SVG. If you’ve never worked with SVG before, you may want to look at some of the introductory tutorials covering SVG syntax, structure and embedding techniques. I recommend the following: SVG basics: Using SVG. Structure: Structuring, Grouping, and Referencing in SVG — The <g>, <use>, <defs> and <symbol> Elements. We’ll mention <use> and <symbol> quite a bit in this article. Embedding techniques: Styling and Animating SVGs with CSS. The article covers several topics, but the section linked focuses on embedding techniques. A compendium of SVG resources compiled by Chris Coyier — contains resources to almost every aspect of SVG you might be interested in. And if you’re completely new to the concept of spriting, Chris Coyier’s CSS Sprites explains all about them. Another important SVG feature is the viewBox attribute. For some of the techniques, knowing your way around this attribute is not required, but it’s definitely more useful if you understand – even if just vaguely – how it works. The last technique mentioned in the article requires that you do know the attribute’s syntax and how to use it. To learn all about viewBox, you can refer to my blog post about SVG coordinate systems. With the prerequisites in place, let’s move on to spriting SVGs! Before you sprite… In order to create an SVG sprite with your icons, you’ll of course need to have these icons ready for use. Some spriting tools require that you place your icons in a folder to which a certain spriting process is to be applied. As such, for all of the upcoming sections we’ll work on the assumption that our SVG icons are placed in a folder named SVG. Each icon is an individual .svg file. You’ll need to make sure each icon is well-prepared and optimised for use – make sure you’ve cleaned up the code by running it through one of the optimisation tools or processes available (or doing it manually if it’s not tedious). After prepping the icon files and placing them in a folder, we’re ready to create our SVG sprite. HTML inline SVG sprites Since SVG is XML code, it can be embedded inline in an HTML document as a code island using the <svg> element. Chris Coyier wrote about this technique first on CSS-Tricks. The embedded SVG will serve as a container for our icons and is going to be the actual sprite we’re going to use. So we’ll start by including the SVG in our document. <!DOCTYPE html> <!-- HTML document stuff --> <svg style="display:none;"> <!-- icons here --> </svg> <!-- other document stuff --> </html> Next, we’re going to place the icons inside the <svg>. Each icon will be wrapped in a <symbol> element we can then reference and use elsewhere in the page using the SVG <use> element. The <symbol> element has many benefits, and we’re using it because it allows us to define a symbol (which is a convenient markup for an icon) without rendering that symbol on the screen. The elements defined inside <symbol> will only be rendered when they are referenced – or called – by the <use> element. Moreover, <symbol> can have its own viewBox attribute, which makes it possible to control the positioning of its content inside its container at any time. Before we move on, I’d like to shed some light on the style="display:none;" part of the snippet above. Without setting the display of the SVG to none, and even though its contents are not rendered on the page, the SVG will still take up space in the page, resulting in a big empty area. In order to avoid that, we’re hiding the SVG entirely with CSS. Now, suppose we have a Twitter icon in the icons folder. twitter.svg might look something like this: <!-- twitter.svg --> <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32"> <path d="M32 6.076c-1.177 0.522-2.443 0.875-3.771 1.034 1.355-0.813 2.396-2.099 2.887-3.632-1.269 0.752-2.674 1.299-4.169 1.593-1.198-1.276-2.904-2.073-4.792-2.073-3.626 0-6.565 2.939-6.565 6.565 0 0.515 0.058 1.016 0.17 1.496-5.456-0.274-10.294-2.888-13.532-6.86-0.565 0.97-0.889 2.097-0.889 3.301 0 2.278 1.159 4.287 2.921 5.465-1.076-0.034-2.088-0.329-2.974-0.821-0.001 0.027-0.001 0.055-0.001 0.083 0 3.181 2.263 5.834 5.266 6.437-0.551 0.15-1.131 0.23-1.73 0.23-0.423 0-0.834-0.041-1.235-0.118 0.835 2.608 3.26 4.506 6.133 4.559-2.247 1.761-5.078 2.81-8.154 2.81-0.53 0-1.052-0.031-1.566-0.092 2.905 1.863 6.356 2.95 10.064 2.95 12.076 0 18.679-10.004 18.679-18.68 0-0.285-0.006-0.568-0.019-0.849 1.283-0.926 2.396-2.082 3.276-3.398z" fill="#000000"></path> </svg> We don’t need the root svg element, so we’ll strip the code and only keep the parts that make up the Twitter icon’s shape, which in this example is just the <path> element.Let’s drop that into the sprite container like so: <svg style="display:none;"> <symbol id="twitter-icon" viewBox="0 0 32 32"> <path d="M32 6.076c-1.177 …" fill="#000000"></path> </symbol> <!-- remaining icons here --> <symbol id="instagram-icon" viewBox="0 0 32 32"> <!-- icon contents --> </symbol> <!-- etc. --> </svg> Repeat for the other icons. The value of the <symbol> element’s viewBox attribute depends on the size of the SVG. You don’t need to know how the viewBox works to use it in this case. Its value is made up of four parts: the first two will almost always be “0 0”; the second two will be equal to the size of the icon. For example, our Twitter icon is 32px by 32px (see twitter.svg above), so the viewBox value is “0 0 32 32”. That said, it is certainly useful to understand how the viewBox works – it can help you troubleshoot SVG sometimes and gives you better control over it, allowing you to scale, position and even crop SVGs manually without having to resort to an editor. My blog post explains all about the viewBox attribute and its related attributes. Once you have your SVG sprite ready, you can display the icons anywhere on the page by referencing them using the SVG <use> element: <svg class="twitter-icon"> <use xlink:href="#twitter-icon"></use> <svg> And that’s all there is to it! HTML-inline SVG sprites are simple to create and use, but when you have a lot of icons (and the more icon sets you create) it can easily become daunting if you have to manually transfer the icons into the <svg>. Fortunately, you don’t have to do that. Fabrice Weinberg created a Grunt plugin called grunt-svgstore which takes the icons in your SVG folder and generates the SVG sprites for you; all you have to do is just drop the sprites into your page and use the icons like we did earlier. This technique works in all browsers supporting SVG. There seems to be a bug in Safari on iOS which causes the icons not to show up when the SVG sprite is defined at the bottom of the document after the <use> references to the icons, so it’s safest to include the sprite before you use the icons until this bug is fixed. This technique has one disadvantage: the SVG sprite cannot be cached. We’re saving an extra HTTP request here but the browser cannot cache the image, so we aren’t speeding up any subsequent page loads by inlining the SVG. There must be a better way – and there is. Styling the icons is possible, but getting deep into the styles becomes a bit harder owing to the nature of the contents of the <use> element – these contents are cloned into a shadow DOM, and hence selecting elements in CSS the traditional way is not possible. However, some techniques to work around that do exist, and give us slightly more styling flexibility. Animations work as expected. Referencing an external SVG sprite in HTML Instead of including the SVG inline in the document, you can reference the sprite and the icons inside it externally, taking advantage of fragment identifiers to select individual icons in the sprite. For example, the above reference to the Twitter icon would look something like this instead: <svg class="twitter-icon"> <use xlink:href="path/to/icons.svg#twitter-icon"></use> <svg> icons.svg is the name of the SVG file that contains all of our icons as symbols, and the fragment identifier #twitter-icon is the reference to the <symbol> wrapping the Twitter icon’s contents. Very convenient, isn’t it? The browser will request the sprite and then cache it, speeding up subsequent page loads. Win! This technique also works in all browsers supporting SVG except Internet Explorer – not even IE9+ with SVG support permits this technique. No version of IE supports referencing an external SVG in <use>. Fortunately (again), Jonathan Neil has created a plugin called svg4everybody which fills this gap in IE; you can reference an external sprite in <use> and also provide fallback for browsers that do not support SVG. However, it requires you to have the fallback images (PNG or JPEG, for example) available to do so. For details, refer to the plugin’s Github repository’s readme file. CSS inline SVG sprites Another way to create an SVG sprite is by inlining the SVG icons in a style sheet using data URIs, and providing fallback for non-supporting browsers – also within the CSS. Using this approach, we’re turning the style sheet into the sprite that includes our icons. The style sheet is normally cached by the browser, so we have that concern out of the way. This technique is put into practice in Filament Group’s icon system approach, which uses their Grunticon plugin – or its sister Grumpicon web app – for generating the necessary CSS for the sprite. As such, we’re going to cover this technique by following a workflow that uses one of these tools. Again, we start with our icon SVG files. To focus on the actual spriting method and not on the tooling, I’ll go over the process of sprite creation using the Grumpicon web app, instead of the Grunticon plugin. Both tools generate the same resources that we’re going to use for the icon system. Whether you choose the web app or the Grunt set-up, after processing your SVG folder you’re going to end up with the same set of resources that we’ll be using throughout this section. The first step is to drop your icons into the Grumpicon web app. Grumpicon homepage screenshot. The application will then show you a preview of your icons, and a download button will allow you to download the generated files. These files will contain everything you need for your icon system – all that’s left is for you to drop the generated files and code into your project as recommended and you’ll have your sprite and icons ready to use anywhere you want in your page. Grumpicon generates five files and one folder in the downloaded package: a png folder containing PNG versions of your icons; three style sheets (that we’ll go over briefly); a loader script file; and preview.html which is a live example showing you the other files in action. The script in the loader goes into the <head> of your page. This script handles browser and feature detection, and requests the necessary style sheet depending on browser support for SVG and base64 data URIs. If you view the source code of the preview page, you can see exactly how the script is added. icons.data.svg.css is the style sheet that contains your icons – the sprite. The icons are embedded inline inside the style sheet using data URIs, and applied to elements of your choice as background images, using class names. For example: .twitter-icon{ background-image: url('data:image/svg+xml;…'); /* the ellipsis is where the icon’s data would go */ background-repeat: no-repeat; background-position: 50% 50%; height: 2em; width: 2em; /* etc. */ } Then, you only have to apply the twitter-icon class name to an element in your HTML to apply the icon as a background to it: <span class="twitter-icon"></span> And that’s all you need to do to get an icon on the page. icons.data.svg.css, along with the other two style sheets and the png folder should be added to your CSS folder. icons.data.png.css is the style sheet the script will load in browsers that don’t support SVG, such as IE8. Fallback for the inline SVG is provided as a base64-encoded PNG. For instance, the fallback for the Twitter icon from our example would look like so: .twitter-icon{ background-image: url('data:image/png;base64;…’); /* etc. */ } icons.fallback.css is the style sheet required for browsers that don’t support base64-encoded PNGs – the PNG images are loaded as usual using the image’s URL. The script will load this style sheet for IE6 and IE7, for example. .twitter-icon{ background-image: url(png/twitter-icon.png); /* etc. */ } This technique is very different from the previous one. The sprite in this case is literally the style sheet, not an SVG container, and the icon usage is very similar to that of a CSS sprite – the icons are provided as background images. This technique has advantages and disadvantages. For the sake of brevity, I won’t go into further details, but the main limitations worth mentioning are that SVGs embedded as background images cannot be styled with CSS; and animations are restricted to those defined inside the <svg> for each icon. CSS interactions (such as hover effects) don’t work either. Thus, to apply an effect for an icon that changes its color on hover, for example, you’ll need to export a set of SVGs for each colour in order for Grumpicon to create matching fallback PNG images that can then be used for the animation. For more details about the Grumpicon workflow, I recommend you check out “A Designer’s Guide to Grumpicon” on Filament Group’s website. Using SVG fragment identifiers and views This spriting technique is, again, different from the previous ones, and it is my personal favourite. SVG comes with a standard way of cropping to a specific area in a particular SVG image. If you’ve ever worked with CSS sprites before then this definitely sounds familiar: it’s almost exactly what we do with CSS sprites – the image containing all of the icons is cropped, so to speak, to show only the one icon that we want in the background positioning area of the element, using background size and positioning properties. Instead of using background properties, we’ll be using SVG’s viewBox attribute to crop our SVG to the specific icon we want. What I like about this technique is that it is more visual than the previous ones. Using this technique, the SVG sprite is treated like an actual image containing other images (the icons), instead of treating it as a piece of code containing other code. Again, our SVG icons are placed inside a main SVG container that is going to be our SVG sprite. If you’re working in a graphics editor, position or arrange your icons inside the canvas any way you want them to be, and then export the graphic as is. Of course, the less empty space there is in your SVG, the better. In our example, the sprite contains three icons as shown in the following image. The sprite is open in Sketch. Notice how the SVG is just big enough to fit the icons inside it. It doesn’t have to be like this, but it’s cleaner this way. Screenshot showing the SVG sprite containing our icons. Now, suppose you want to display only the Instagram icon. Using the SVG viewBox attribute, we can crop the SVG to the icon. The Instagram icon is positioned at 64px along the positive x-axis, and zero pixels along the y-axis. It is also 32px by 32px in size. Screenshot showing the position (offset) of the Instagram icon inside the SVG sprite, and its size. Using this information, we can specify the value of the viewBox as: 64 0 32 32. This area of the view box contains only the Instagram icon. 64 0 specifies the top-left corner of the view box area, and 32 32 specify its dimensions. Now, if we were to change the viewBox value on the SVG sprite to this value, only the Instagram icon will be visible inside the SVG viewport. Great. But how do we use this information to display the icon in our page using our sprite? SVG comes with a native way to link to portions or areas of an image using fragment identifiers. Fragment identifiers are used to link into a particular view area of an SVG document. Thus, using a fragment identifier and the boundaries of the area that we want (from the viewBox), we can link to that area and display it. For example, if you want to display the icon from the sprite using an <img> tag, you can reference the icon in the sprite like so: <img src='uiIcons.svg#svgView(viewBox(64, 0, 32, 32))' alt="Settings icon"/> The fragment identifier in the snippet above (#svgView(viewBox(64, 0, 32, 32))) is the important part. This will result in only the Instagram icon’s area of the sprite being displayed. There is also another way to do this, using the SVG <view> element. The <view> element can be used to define a view area and then reference that area somewhere else. For example, to define the view box containing the Instagram icon, we can do the following: <view id='instagram-icon' viewBox='64 0 32 32' /> Then, we can reference this view in our <img> element like this: <img src='sprite.svg#instagram-icon' alt="Instagram icon" /> The best part about this technique – besides the ability to reference an external SVG and hence make use of browser caching – is that it allows us to use practically any SVG embedding technique and does not restrict us to specific tags. It goes without saying that this feature can be used for more than just icon systems, owing to viewBox’s power in controlling an SVG’s viewable area. SVG fragment identifiers have decent browser support, but the technique is buggy in Safari: there is a bug that causes problems when loading a server SVG file and then using fragment identifiers with it. Bear Travis has documented the issue and a workaround. Where to go from here Pick the technique that works best for your project. Each technique has its own pros and cons, relating to convenience and maintainability, performance, and styling and scripting. Each technique also requires its own fallback mechanism. The spriting techniques mentioned here are not the only techniques available. Other methods exist, such as SVG stacks, and others may surface in future, but these are the three main ones today. The third technique using SVG’s built-in viewBox features is my favourite, and with better browser support and fewer (ideally, no) bugs, I believe it is more likely to become the standard way to create and use SVG sprites. Fallback techniques can be created, of course, in one of many possible ways. Do you use SVG for your icon system? If so, which is your favourite technique? Do you know or have worked with other ways for creating SVG sprites? 2014 Sara Soueidan sarasoueidan 2014-12-16T00:00:00+00:00 https://24ways.org/2014/an-overview-of-svg-sprite-creation-techniques/ code
231 Designing for iOS: Life Beyond Media Queries Although not a new phenomenon, media queries seem to be getting a lot attention online recently and for the right reasons too – it’s great to be able to adapt a design with just a few lines of CSS – but many people are relying only on them to create an iPhone-specific version of their website. I was pleased to hear at FOWD NYC a few weeks ago that both myself and Aral Balkan share the same views on why media queries aren’t always going to be the best solution for mobile. Both of us specialise in iPhone design ourselves and we opt for a different approach to media queries. The trouble is, regardless of what you have carefully selected to be display:none; in your CSS, the iPhone still loads everything in the background; all that large imagery for your full scale website also takes up valuable mobile bandwidth and time. You can greatly increase the speed of your website by creating a specific site tailored to mobile users with just a few handy pointers – media queries, in some instances, might be perfectly suitable but, in others, here’s what you can do. Redirect your iPhone/iPod Touch users To detect whether someone is viewing your site on an iPhone or iPod Touch, you can either use JavaScript or PHP. The JavaScript if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))) { if (document.cookie.indexOf("iphone_redirect=false") == -1) window.location = "http://mobile.yoursitehere.com"; } The PHP if(strstr($_SERVER['HTTP_USER_AGENT'],'iPhone') || strstr($_SERVER['HTTP_USER_AGENT'],'iPod')) { header('Location: http://mobile.yoursitehere.com'); exit(); } Both of these methods redirect the user to a site that you have made specifically for the iPhone. At this point, be sure to provide a link to the full version of the website, in case the user wishes to view this and not be thrown into an experience they didn’t want, with no way back. Tailoring your site So, now you’ve got 320 × 480 pixels of screen to play with – and to create a style sheet for, just as you would for any other site you build. There are a few other bits and pieces that you can add to your code to create a site that feels more like a fully immersive iPhone app rather than a website. Retina display When building your website specifically tailored to the iPhone, you might like to go one step further and create a specific style sheet for iPhone 4’s Retina display. Because there are four times as many pixels on the iPhone 4 (640 × 960 pixels), you’ll find specifics such as text shadows and borders will have to be increased. <link rel="stylesheet" media="only screen and (-webkit-min-device-pixel-ratio: 2)" type="text/css" href="../iphone4.css" /> (Credit to Thomas Maier) Prevent user scaling This declaration, added into the <head>, stops the user being able to pinch-zoom in and out of your design, which is perfect if you are designing to the exact pixel measurements of the iPhone screen. <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"> Designing for orientation As iPhones aren’t static devices, you’ll also need to provide a style sheet for horizontal orientation. We can do this by inserting some JavaScript into the <head> as follows: <script type="text/javascript"> function orient() { switch(window.orientation) { case 0: document.getElementById("orient_css").href = "css/iphone_portrait.css"; break; case -90: document.getElementById("orient_css").href = "css/iphone_landscape.css"; break; case 90: document.getElementById("orient_css").href = "css/iphone_landscape.css"; break; } } window.onload = orient(); </script> You can also specify orientation styles using media queries. This is absolutely fine, as by this point you’ll already be working with mobile-specific graphics and have little need to set a lot of things to display:none; <link rel="stylesheet" media="only screen and (max-device-width: 480px)" href="/iphone.css"> <link rel="stylesheet" media="only screen and (orientation: portrait)" href="/portrait.css"> <link rel="stylesheet" media="only screen and (orientation: landscape)” href="/landscape.css"> Remove the address and status bars, top and bottom To give you more room on-screen and to make your site feel more like an immersive web app, you can place the following declaration into the <head> of your document’s code to remove the address and status bars at the top and bottom of the screen. <meta name="apple-mobile-web-app-capable" content="yes" /> Making the most of inbuilt functions Similar to mailto: e-mail links, the iPhone also supports another two handy URI schemes which are great for enhancing contact details. When tapped, the following links will automatically bring up the appropriate call or text interface: <a href="tel:01234567890">Call us</a> <a href="sms:01234567890">Text us</a> iPhone-specific Web Clip icon Although I believe them to be fundamentally flawed, since they rely on the user bookmarking your site, iPhone Web Clip icons are still a nice touch. You need just two declarations, again in the <head> of your document: <link rel="apple-touch-icon" href="icons/regular_icon.png" /> <link rel="apple-touch-icon" sizes="114x114" href="icons/retina_icon.png" /> For iPhone 4 you’ll need to create a 114 × 114 pixels icon; for a non-Retina display, a 57 × 57 pixels icon will do the trick. Precomposed Apple adds its standard gloss ‘moon’ over the top of any icon. If you feel this might be too much for your particular icon and would prefer a matte finish, you can add precomposed to the end of the apple-touch-icon declaration to remove the standard gloss. <link rel="apple-touch-icon-precomposed" href="/images/touch-icon.png" /> Wrapping up Media queries definitely have their uses. They make it easy to build a custom experience for your visitor, regardless of their browser’s size. For more complex sites, however, or where you have lots of imagery and other content that isn’t necessary on the mobile version, you can now use these other methods to help you out. Remember, they are purely for presentation and not optimisation; for busy people on the go, optimisation and faster-running mobile experiences can only be a good thing. Have a wonderful Christmas fellow Webbies! 2010 Sarah Parmenter sarahparmenter 2010-12-17T00:00:00+00:00 https://24ways.org/2010/life-beyond-media-queries/ code
296 Animation in Design Systems Our modern front-end workflow has matured over time to include design systems and component libraries that help us stay organized, improve workflows, and simplify maintenance. These systems, when executed well, ensure proper documentation of the code available and enable our systems to scale with reduced communication conflicts. But while most of these systems take a critical stance on fonts, colors, and general building blocks, their treatment of animation remains disorganized and ad-hoc. Let’s leverage existing structures and workflows to reduce friction when it comes to animation and create cohesive and performant user experiences. Understand the importance of animation Part of the reason we treat animation like a second-class citizen is that we don’t really consider its power. When users are scanning a website (or any environment or photo), they are attempting to build a spatial map of their surroundings. During this process, nothing quite commands attention like something in motion. We are biologically trained to notice motion: evolutionarily speaking, our survival depends on it. For this reason, animation when done well can guide your users. It can aid and reinforce these maps, and give us a sense that we understand the UX more deeply. We retrieve information and put it back where it came from instead of something popping in and out of place. “Where did that menu go? Oh it’s in there.” For a deeper dive into how animation can connect disparate states, I wrote about the Importance of Context-Shifting in UX Patterns for CSS-Tricks. An animation flow on mobile. Animation also aids in perceived performance. Viget conducted a study where they measured user engagement with a standard loading GIF versus a custom animation. Customers were willing to wait almost twice as long for the custom loader, even though it wasn’t anything very fancy or crazy. Just by showing their users that they cared about them, they stuck around, and the bounce rates dropped. 14 second generic loading screen.22 second custom loading screen. This also works for form submission. Giving your personal information over to an online process like a static form can be a bit harrowing. It becomes more harrowing without animation used as a signal that something is happening, and that some process is completing. That same animation can also entertain users and make them feel as though the wait isn’t as long. Eli Fitch gave a talk at CSS Dev Conf called: “Perceived Performance: The Only Kind That Really Matters”, which is one of my favorite talk titles of all time. In it, he discussed how we tend to measure things like timelines and network requests because they are more quantifiable–and therefore easier to measure–but that measuring how a user feels when visiting the site is more important and worth the time and attention. In his talk, he states “Humans over-estimate passive waits by 36%, per Richard Larson of MIT”. This means that if you’re not using animation to speed up how fast the wait time of a form submission loads, users are perceiving it to be much slower than the dev tools timeline is recording. Reign it in Unlike fonts, colors, and so on, we tend to add animation in as a last step, which leads to disorganized implementations that lack overall cohesion. If you asked a designer or developer if they would create a mockup or build a UI without knowing the fonts they were working with, they would dislike the idea. Not knowing the building blocks they’re working with means that the design can fall apart or the development can break with something so fundamental left out at the start. Good animation works the same way. The first step in reigning in your use of animation is to perform an animation audit. Look at all the places you are using animation on your site, or the places you aren’t using animation but probably should. (Hint: perceived performance of a loader on a form submission can dramatically change your bounce rates.) Not sure how to perform a good audit? Val Head has a great chapter on it in her book, Designing Interface Animations, which has of buckets of research and great ideas. Even some beautiful component libraries that have animation in the docs make this mistake. You don’t need every kind of animation, just like you don’t need every kind of font. This bloats our code. Ask yourself questions like: do you really need a flip 180 degree animation? I can’t even conceive of a place on a typical UI where that would be useful, yet most component libraries that I’ve seen have a mixin that does just this. Which leads to… Have an opinion Many people are confused about Material Design. They think that Material Design is Motion Design, mostly because they’ve never seen anyone take a stance on animation before and document these opinions well. But every time you use Material Design as your motion design language, people look at your site and think GOOGLE. Now that’s good branding. By using Google’s motion design language and not your own, you’re losing out on a chance to be memorable on your own website. What does having an opinion on motion look like in practice? It could mean you’ve decided that you never flip things. It could mean that your eases are always going to glide. In that instance, you would put your efforts towards finding an ease that looks “gliding” and pulling out any transform: scaleX(-1) animation you find on your site. Across teams, everyone knows not to spend time mocking up flipping animation (even if they’re working on an entirely different codebase), and to instead work on something that feels like it glides. You save time and don’t have to communicate again and again to make things feel cohesive. Create good developer resources Sometimes people don’t incorporate animation into a design system because they aren’t sure how, beyond the base hover states. All animation properties can be broken into interchangeable pieces. This allows developers and designers alike to mix and match and iterate quickly, while still staying in the correct language. Here are some recommendations (with code and a demo to follow): Create timing units, similar to h1, h2, h3. In a system I worked on recently, I called these t1, t2, t3. T1 would be reserved for longer pieces, down to t5 which is a bit like h5 in that it’s the default (usually around .25 seconds or thereabouts). Keep animation easings for entrance, exit, entrance emphasis and exit emphasis that people can commonly refer to. This, and the animation-fill-mode, are likely to be the only two properties that can be reused for the entrance and exit of the animation. Use the animation-name property to define the keyframes for the animation itself. I would recommend starting with 5 or 6 before making a slew of them, and see if you need more. Writing 30 different animations might seem like a nice resource, but just like your color palette having too many can unnecessarily bulk up your codebase, and keep it from feeling cohesive. Think critically about what you need here. See the Pen Modularized Animation for Component Libraries by Sarah Drasner (@sdras) on CodePen. The example above is pared-down, but you can see how in a robust system, having pieces that are interchangeable cached across the whole system would save time for iterations and prototyping, not to mention make it easy to make adjustments for different feeling movement on the same animation easily. One low hanging fruit might be a loader that leads to a success dialog. On a big site, you might have that pattern many times, so writing up a component that does only that helps you move faster while also allowing you to really zoom in and focus on that pattern. You avoid throwing something together at the last minute, or using a GIF, which are really heavy and mushy on retina. You can make singular pieces that look really refined and are reusable. React and Vue Implementations are great for reusable components, as you can create a building block with a common animation pattern, and once created, it can be a resource for all. Remember to take advantage of things like props to allow for timing and easing adjustments like we have in the previous example! Responsive At the very least we should ensure that interaction also works well on mobile, but if we’d like to create interactions that take advantage of all of the gestures mobile has to offer, we can use libraries like zingtouch or hammer to work with swipe or multiple finger detection. With a bit of work, these can all be created through native detection as well. Responsive web pages can specify initial-scale=1.0 in the meta tag so that the device is not waiting the required 300ms on the secondary tap before calling action. Interaction for touch events must either start from a larger touch-target (40px × 40px or greater) or use @media(pointer:coarse) as support allows. Buy-in Sometimes people don’t create animation resources simply because it gets deprioritized. But design systems were also something we once had to fight for, too. This year at CSS Dev Conf, Rachel Nabors demonstrated how to plot out animation wants vs. needs on a graph (reproduced with her permission) to help prioritize them: This helps people you’re working with figure out the relative necessity and workload of the addition of these animations and think more critically about it. You’re also more likely to get something through if you’re proving that what you’re making is needed and can be reused. Good compromises can be made this way: “we’re not going to go all out and create an animated ‘About Us’ page like you wanted, but I suppose we can let our users know their contact email went through with a small progress and success notification.” Successfully pushing smaller projects through helps build trust with your team, and lets them see what this type of collaboration can look like. This builds up the type of relationship necessary to push through projects that are more involved. It can’t be overstressed that good communication is key. Get started! With these tools and good communication, we can make our codebases more efficient, performant, and feel better for our users. We can enhance the user experience on our sites, and create great resources for our teams to allow them to move more quickly while innovating beautifully. 2016 Sarah Drasner sarahdrasner 2016-12-16T00:00:00+00:00 https://24ways.org/2016/animation-in-design-systems/ code
30 Making Sites More Responsive, Responsibly With digital projects we’re used to shifting our thinking to align with our target audience. We may undertake research, create personas, identify key tasks, or observe usage patterns, with our findings helping to refine our ongoing creations. A product’s overall experience can make or break its success, and when it comes to defining these experiences our development choices play a huge role alongside more traditional user-focused activities. The popularisation of responsive web design is a great example of how we are able to shape the web’s direction through using technology to provide better experiences. If we think back to the move from table-based layouts to CSS, initially our clients often didn’t know or care about the difference in these approaches, but we did. Responsive design was similar in this respect – momentum grew through the web industry choosing to use an approach that we felt would give a better experience, and which was more future-friendly.  We tend to think of responsive design as a means of displaying content appropriately across a range of devices, but the technology and our implementation of it can facilitate much more. A responsive layout not only helps your content work when the newest smartphone comes out, but it also ensures your layout suitably adapts if a visually impaired user drastically changes the size of the text. The 24 ways site at 400% on a Retina MacBook Pro displays a layout more typically used for small screens. When we think more broadly, we realise that our technical choices and approaches to implementation can have knock-on effects for the greater good, and beyond our initial target audiences. We can make our experiences more responsive to people’s needs, enhancing their usability and accessibility along the way. Being responsibly responsive Of course, when we think about being more responsive, there’s a fine line between creating useful functionality and becoming intrusive and overly complex. In the excellent Responsible Responsive Design, Scott Jehl states that: A responsible responsive design equally considers the following throughout a project: Usability: The way a website’s user interface is presented to the user, and how that UI responds to browsing conditions and user interactions. Access: The ability for users of all devices, browsers, and assistive technologies to access and understand a site’s features and content. Sustainability: The ability for the technology driving a site or application to work for devices that exist today and to continue to be usable and accessible to users, devices, and browsers in the future. Performance: The speed at which a site’s features and content are perceived to be delivered to the user and the efficiency with which they operate within the user interface. Scott’s book covers these ideas in a lot more detail than I’ll be able to here (put it on your Christmas list if it’s not there already), but for now let’s think a bit more about our roles as digital creators and the power this gives us. Our choices around technology and the decisions we have to make can be extremely wide-ranging. Solutions will vary hugely depending on the needs of each project, though we can further explore the concept of making our creations more responsive through the use of humble web technologies. The power of the web We all know that under the HTML5 umbrella are some great new capabilities, including a number of JavaScript APIs such as geolocation, web audio, the file API and many more. We often use these to enhance the functionality of our sites and apps, to add in new features, or to facilitate device-specific interactions. You’ll have seen articles with flashy titles such as “Top 5 JavaScript APIs You’ve Never Heard Of!”, which you’ll probably read, think “That’s quite cool”, yet never use in any real work. There is great potential for technologies like these to be misused, but there are also great prospects for them to be used well to enhance experiences. Let’s have a look at a few examples you may not have considered. Offline first When we make websites, many of us follow a process which involves user stories – standardised snippets of context explaining who needs what, and why. “As a student I want to pay online for my course so I don’t have to visit the college in person.” “As a retailer I want to generate unique product codes so I can manage my stock.” We very often focus heavily on what needs doing, but may not consider carefully how it will be done. As in Scott’s list, accessibility is extremely important, not only in terms of providing a great experience to users of assistive technologies, but also to make your creation more accessible in the general sense – including under different conditions. Offline first is yet another ‘first’ methodology (my personal favourite being ‘tea first’), which encourages us to develop so that connectivity itself is an enhancement – letting users continue with tasks even when they’re offline. Despite the rapid growth in public Wi-Fi, if we consider data costs and connectivity in developing countries, our travel habits with planes, underground trains and roaming (or simply if you live in the UK’s signal-barren East Anglian wilderness as I do), then you’ll realise that connectivity isn’t as ubiquitous as our internet-addled brains would make us believe. Take a scenario that I’m sure we’re all familiar with – the digital conference. Your venue may be in a city served by high-speed networks, but after overloading capacity with a full house of hashtag-hungry attendees, each carrying several devices, then everyone’s likely to be offline after all. Wouldn’t it be better if we could do something like this instead? Someone visits our conference website. On this initial run, some assets may be cached for future use: the conference schedule, the site’s CSS, photos of the speakers. When the attendee revisits the site on the day, the page shell loads up from the cache. If we have cached content (our session timetable, speaker photos or anything else), we can load it directly from the cache. We might then try to update this, or get some new content from the internet, but the conference attendee already has a base experience to use. If we don’t have something cached already, then we can try grabbing it online. If for any reason our requests for new content fail (we’re offline), then we can display a pre-cached error message from the initial load, perhaps providing our users with alternative suggestions from what is cached. There are a number of ways we can make something like this, including using the application cache (AppCache) if you’re that way inclined. However, you may want to look into service workers instead. There are also some great resources on Offline First! if you’d like to find out more about this. Building in offline functionality isn’t necessarily about starting offline first, and it’s also perfectly possible to retrofit sites and apps to catch offline scenarios, but this kind of graceful degradation can end up being more complex than if we’d considered it from the start. By treating connectivity as an enhancement, we can improve the experience and provide better performance than we can when waiting to counter failures. Our websites can respond to connectivity and usage scenarios, on top of adapting how we present our content. Thinking in this way can enhance each point in Scott’s criteria. As I mentioned, this isn’t necessarily the kind of development choice that our clients will ask us for, but it’s one we may decide is simply the right way to build based on our project, enhancing the experience we provide to people, and making it more responsive to their situation. Even more accessible We’ve looked at accessibility in terms of broadening when we can interact with a website, but what about how? Our user stories and personas are often of limited use. We refer in very general terms to students, retailers, and sometimes just users. What if we have a student whose needs are very different from another student? Can we make our sites even more usable and accessible through our development choices? Again using JavaScript to illustrate this concept, we can do a lot more with the ways people interact with our websites, and with the feedback we provide, than simply accepting keyboard, mouse and touch inputs and displaying output on a screen. Input Ambient light detection is one of those features that looks great in simple demos, but which we struggle to put to practical use. It’s not new – many satnav systems automatically change the contrast for driving at night or in tunnels, and our laptops may alter the screen brightness or keyboard backlighting to better adapt to our surroundings. Using web technologies we can adapt our presentation to be better suited to ambient light levels. If our device has an appropriate light sensor and runs a browser that supports the API, we can grab the ambient light in units using ambient light events, in JavaScript. We may then change our presentation based on different bandings, perhaps like this: window.addEventListener('devicelight', function(e) { var lux = e.value; if (lux < 50) { //Change things for dim light } if (lux >= 50 && lux <= 10000) { //Change things for normal light } if (lux > 10000) { //Change things for bright light } }); Live demo (requires light sensor and supported browser). Soon we may also be able to do such detection through CSS, with light-level being cited in the Media Queries Level 4 specification. If that becomes the case, it’ll probably look something like this: @media (light-level: dim) { /*Change things for dim light*/ } @media (light-level: normal) { /*Change things for normal light*/ } @media (light-level: washed) { /*Change things for bright light*/ } While we may be quick to dismiss this kind of detection as being a gimmick, it’s important to consider that apps such as Light Detector, listed on Apple’s accessibility page, provide important context around exactly this functionality. “If you are blind, Light Detector helps you to be more independent in many daily activities. At home, point your iPhone towards the ceiling to understand where the light fixtures are and whether they are switched on. In a room, move the device along the wall to check if there is a window and where it is. You can find out whether the shades are drawn by moving the device up and down.” everywaretechnologies.com/apps/lightdetector Input can be about so much more than what we enter through keyboards. Both an ever increasing amount of available sensors and more APIs being supported by the major browsers will allow us to cater for more scenarios and respond to them accordingly. This can be as complex or simple as you need; for instance, while x-webkit-speech has been deprecated, the web speech API is available for a number of browsers, and research into sign language detection is also being performed by organisations such as Microsoft. Output Web technologies give us some great enhancements around input, allowing us to adapt our experiences accordingly. They also provide us with some nice ways to provide feedback to users. When we play video games, many of our modern consoles come with the ability to have rumble effects on our controller pads. These are a great example of an enhancement, as they provide a level of feedback that is entirely optional, but which can give a great deal of extra information to the player in the right circumstances, and broaden the scope of our comprehension beyond what we’re seeing and hearing. Haptic feedback is possible on the web as well. We could use this in any number of responsible applications, such as alerting a user to changes or using different patterns as a communication mechanism. If you find yourself in a pickle, here’s how to print out SOS in Morse code through the vibration API. The following code indicates the length of vibration in milliseconds, interspersed by pauses in milliseconds. navigator.vibrate([100, 300, 100, 300, 100, 300, 600, 300, 600, 300, 600, 300, 100, 300, 100, 300, 100]); Live demo (requires supported browser) With great power… What you’ve no doubt come to realise by now is that these are just more examples of progressive enhancement, whose inclusion will provide a better experience if the capabilities are available, but which we should not rely on. This idea isn’t new, but the most important thing to remember, and what I would like you to take away from this article, is that it is up to us to decide to include these kind of approaches within our projects – if we don’t root for them, they probably won’t happen. This is where our professional responsibility comes in. We won’t necessarily be asked to implement solutions for the scenarios above, but they illustrate how we can help to push the boundaries of experiences. Maybe we’ll have to switch our thinking about how we build, but we can create more usable products for a diverse range of people and usage scenarios through the choices we make around technology. Let’s stop thinking simply in terms of features inside a narrow view of our target users, and work out how we can extend these to cater for a wider set of situations. When you plan your next digital project, consider the power of the web and the enhancements we can use, and try to make your projects even more responsive and responsible. 2014 Sally Jenkinson sallyjenkinson 2014-12-10T00:00:00+00:00 https://24ways.org/2014/making-sites-more-responsive-responsibly/ code
57 Cooking Up Effective Technical Writing Merry Christmas! May your preparations for this festive season of gluttony be shaping up beautifully. By the time you read this I hope you will have ordered your turkey, eaten twice your weight in Roses/Quality Street (let’s not get into that argument), and your Christmas cake has been baked and is now quietly absorbing regular doses of alcohol. Some of you may be reading this and scoffing Of course! I’ve also made three batches of mince pies, a seasonal chutney and enough gingerbread men to feed the whole street! while others may be laughing Bake? Oh no, I can’t cook to save my life. For beginners, recipes are the step-by-step instructions that hand-hold us through the cooking process, but even as a seasoned expert you’re likely to refer to a recipe at some point. Recipes tell us what we need, what to do with it, in what order, and what the outcome will be. It’s the documentation behind our ideas, and allows us to take the blueprint for a tasty morsel and to share it with others so they can recreate it. In fact, this is a little like the open source documentation and tutorials that we put out there, similarly aiming to guide other developers through our creations. The ‘just’ification of documentation Lately it feels like we’re starting to consider the importance of our words, and the impact they can have on others. Brad Frost warned us of the dangers of “Just” when it comes to offering up solutions to queries: “Just use this software/platform/toolkit/methodology…” “Just” makes me feel like an idiot. “Just” presumes I come from a specific background, studied certain courses in university, am fluent in certain technologies, and have read all the right books, articles, and resources. “Just” is a dangerous word. “Just” by Brad Frost I can really empathise with these sentiments. My relationship with code started out as many good web tales do, with good old HTML, CSS and JavaScript. University years involved some time with Perl, PHP, Java and C. In my first job I worked primarily with ColdFusion, a bit of ActionScript, some classic  ASP and pinch of Java. I’d do a bit of PHP outside work every now and again. .NET came in, but we never really got on, and eventually I started learning some Ruby, Python and Node. It was a broad set of learnings, and I enjoyed the similarities and differences that came with new languages. I don’t develop day in, day out any more, and my interests and work have evolved over the years, away from full-time development and more into architecture and strategy. But I still make things, and I still enjoy learning. I have often found myself bemoaning the lack of tutorials or courses that cater for the middle level – someone who may be learning a new language, but who has enough programming experience under their belt to not need to revise the concepts of how loops or objects work, and is perfectly adept at googling the syntax for getting a substring. I don’t want snippets out of context; I want an understanding of architectural principles, of the strengths and weaknesses, of the type of applications that work well with the language. I’m caught in the place between snoozing off when ‘Using the Instagram API with Ruby’ hand-holds me through what REST is, and feeling like I’m stupid and need to go back to dev school when I can’t get my environment and dependencies set up, let alone work out how I’m meant to get any code to run. It’s seems I’m not alone with this – Erin McKean seems to have been here too: “Some tutorials (especially coding tutorials) like to begin things in media res. Great for a sense of dramatic action, bad for getting to “Step 1” without tears. It can be really discouraging to fire up a fresh terminal window only to be confronted by error message after error message because there were obligatory steps 0.1.0 through 0.9.9 that you didn’t even know about.” “Tips for Learning What You Don’t Know You Don’t Know” by Erin McKean I’m sure you’ve been here too. Many tutorials suffer badly from the fabled ‘how to draw an owl’-itis. It’s the kind of feeling you can easily get when sifting through recipes as well as with code. Far from being the simple instructions that let us just follow along, they too can be a minefield. Fall in too low and you may be skipping over an explanation of what simmering is, or set your sights too high and you may get stuck at the point where you’re trying to sous vide a steak using your bathtub and a Ziploc bag. Don’t be a turkey, use your loaf! My mum is a great cook in my eyes (aren’t all mums?). I love her handcrafted collection of gathered recipes from over the years, including the one below, which is a great example of how something may make complete sense to the writer, but could be impermeable to a reader. Depending on your level of baking knowledge, you may ask: What’s SR flour? What’s a tsp? Should I use salted or unsalted butter? Do I use sticks of cinnamon or ground? Why is chopped chocolate better? How do I cream things? How big should the balls be? How well is “well spaced”? How much leeway do I have for “(ish!!)”? Does the “20” on the other cookie note mean I’ll end up with twenty? At any point, making a wrong call could lead to rubbish cookies, and lead to someone heading down the path of an I can’t cook mentality. You may be able to cook (or follow recipes), but you may not understand the local terms for ingredients, may not be able to acquire something and need to know what kind of substitutes you can use, or may need to actually do some prep before you jump into the main bit. However, if we look at good examples of recipes, I think there’s a lot we can apply when it comes to technical writing on the web. I’ve written before about the benefit of breaking documentation into small, reusable parts, and this will help us, but we can also take it a bit further. Here are my five top tips for better technical writing. 1. Structure and standardise your information Think of the structure of a recipe. We very often have some common elements and they usually follow roughly the same format. We have standards and conventions that allow us to understand very quickly what a recipe is and how it should be used.  Great recipes help their chefs know what they need to get ready in advance, both in terms of buying ingredients and putting together their kit. They then talk through the process, using appropriate language, and without making assumptions that the person can fill in any gaps for themselves; they explain why things are done the way they are. The best recipes may also suggest how you can take what you’ve done and put your own spin on it. For instance, a good recipe for the simple act of boiling an egg will explain cooking time in relation to your preference for yolk gooiness. There are also different flavour combinations to try, accompaniments, or presentation suggestions.  By breaking down your technical writing into similar sections, you can help your audience understand the elements they’ll be working with, what they need to do once they have these, and how they can move on from your self-contained illustration. Title Ensure your title is suitably descriptive and representative of the result. Getting Started with Python perhaps isn’t as helpful as Learn Python: General Syntax and Basics. Result Many recipes include a couple of lines as an overview of what you’ll end up with, and many include a photo of the finished dish. With our technical writing we can do the same: In this tutorial we’re going to learn how to set up our development environment, and we’ll then undertake some exercises to explore the general syntax, finishing by building a mini calculator. Ingredients What are the components we’ll be working with, whether in terms of versions, environment, languages or the software packages and libraries you’ll need along the way? Listing these up front gives the reader a great summary of the things they’ll be using, and any gotchas. Being able to provide a small amount of supporting information will also help less experienced users. Ideally, explain briefly what things are and why we’re using it. Prep As we heard from Erin above, not fully understanding the prep needed can be a huge source of frustration. Attempting to run a code snippet without context will often lead to failure when the prerequisites and process aren’t clear. Be sure to include information around any environment set-up, installation or config you’ll need to have done before you start. Stu Robson’s Simple Sass documentation aims to do this before getting into specifics, although ideally this would also include setting up Sass itself. Instructions The body of the tutorial itself is the whole point of our writing. The next four tips will hopefully make your tutorial much more successful. Variations Like our ingredients section, as important as explaining why we’re using something in this context is, it’s also great to explain alternatives that could be used instead, and the impact of doing so. Perhaps go a step further, explaining ways that people can change what you have done in your tutorial/readme for use in different situations, or to provide further reading around next steps. What happens if they want to change your static array of demo data to use JSON, for instance? By giving some thought to follow-up questions, you can better support your readers. While not in a separate section, the source code for GreenSock’s GSAP JS basics explains: We’ll use a window.onload for simplicity, but typically it is best to use either jQuery’s $(document).ready() or $(window).load() or cross-browser event listeners so that you’re not limited to one. Keep in mind to both: Explain what variations are possible. Explain why certain options may be more desirable than others in different situations. 2. Small, reusable components Reusable components are for life, not just for Christmas, and they’re certainly not just for development. If you start to apply the structure above to your writing, you’re probably going to keep coming across the same elements: Do I really have to explain how to install Sass and Node.js again, Sally? The danger with more clarity is that our writing becomes bloated and overly convoluted for advanced readers, those who don’t need to be told how to beat an egg for the hundredth time.  Instead, by making our writing reusable and modular, and by creating smaller, central resources, we can provide context and extra detail where needed without diluting our core message. These could be references we create, or those already created well by others. This recipe for katsudon makes use of this concept. Rather than explaining how to make tonkatsu or dashi stock, these each have their own page. Once familiar, more advanced readers will likely skip over the instructions for the component parts. 3. Provide context to aid accessibility Here I’m talking about accessibility in the broadest sense. Small, isolated snippets can be frustrating to those who don’t fully understand the wider context of how our examples work. Showing an exciting standalone JavaScript function is great, but giving someone the full picture of how and when this is called, and how it should be included in relation to other HTML and CSS is even better. Giving your readers the ability to view a big picture version, and ideally the ability to download a full version of the source, will help to reduce some of the frustrations of trying to get your component to work in their set-up.  4. Be your own tech editor A good editor can be invaluable to your work, and wherever possible I’d recommend that you try to get a neutral party to read over your writing. This may not always be possible, though, and you may need to rely on yourself to cast a critical eye over your work. There are many tips out there around general editing, including printing out your work onto paper, or changing the font size: both will force your eyes to review it in a new light. Beyond this, I’d like to encourage you to think about the following: Explain what things are. For example, instead of referencing Grunt, in the first instance perhaps reference “Grunt (a JavaScript task runner that minimises repetitive activities through automation).” Explain how you get things, even if this is a link to official installers and documentation. Don’t leave your readers having to search. Why are you using this approach/technology over other options? What happens if I use something else? What depends on this? Avoid exclusionary lingo or acronyms. Airbnb’s JavaScript Style Guide includes useful pointers around their reasoning: Use computed property names when creating objects with dynamic property names. Why? They allow you to define all the properties of an object in one place. The language we use often makes assumptions, as we saw with “just”. An article titled “ES6 for Beginners” is hugely ambiguous: is this truly for beginner coders, or actually for people who have a good pre-existing understanding of JavaScript but are new to these features? Review your writing with different types of readers in mind. How might you confuse or mislead them? How can you better answer their questions? This doesn’t necessarily mean supporting everyone – your audience may need to have advanced skills – but even if you’re providing low-level, deep-dive, reference material, trying not to make assumptions or take shortcuts will hopefully lead to better, clearer writing. 5. A picture is worth a thousand words… …or even better: use a thousand pictures, stitched together into a quick video or animated GIF. People learn in different ways. Just as recipes often provide visual references or a video to work along with, providing your technical information with alternative demonstrations can really help get your point across. Your audience will be able to see exactly what you’re doing, what they should expect as interaction responses, and what the process looks like at different points. There are many, many options for recording your screen, including QuickTime Player on Mac OS X (File → New Screen Recording), GifGrabber, or Giffing Tool on Windows. Paul Swain, a UX designer, uses GIFs to provide additional context within his documentation, improving communication: “My colleagues (from across the organisation) love animated GIFs. Any time an interaction is referenced, it’s accompanied by a GIF and a shared understanding of what’s being designed. The humble GIF is worth so much more than a thousand words; and it’s great for cats.” Paul Swain Next time you’re cooking up some instructions for readers, think back to what we can learn from recipes to help make your writing as accessible as possible. Use structure, provide reusable bitesize morsels, give some context, edit wisely, and don’t scrimp on the GIFs. And above all, have a great Christmas! 2015 Sally Jenkinson sallyjenkinson 2015-12-18T00:00:00+00:00 https://24ways.org/2015/cooking-up-effective-technical-writing/ content
20 Make Your Browser Dance It was a crisp winter’s evening when I pulled up alongside the pier. I stepped out of my car and the bitterly cold sea air hit my face. I walked around to the boot, opened it and heaved out a heavy flight case. I slammed the boot shut, locked the car and started walking towards the venue. This was it. My first gig. I thought about all those weeks of preparation: editing video clips, creating 3-D objects, making coloured patterns, then importing them all into software and configuring effects to change as the music did; targeting frequency, beat, velocity, modifying size, colour, starting point; creating playlists of these… and working out ways to mix them as the music played. This was it. This was me VJing. This was all a lifetime (well a decade!) ago. When I started web designing, VJing took a back seat. I was more interested in interactive layouts, semantic accessible HTML, learning all the IE bugs and mastering the quirks that CSS has to offer. More recently, I have been excited by background gradients, 3-D transforms, the @keyframe directive, as well as new APIs such as getUserMedia, indexedDB, the Web Audio API But wait, have I just come full circle? Could it be possible, with these wonderful new things in technologies I am already familiar with, that I could VJ again, right here, in a browser? Well, there’s only one thing to do: let’s try it! Let’s take to the dance floor Over the past couple of years working in The Lab I have learned to take a much more iterative approach to projects than before. One of my new favourite methods of working is to create a proof of concept to make sure my theory is feasible, before going on to create a full-blown product. So let’s take the same approach here. The main VJing functionality I want to recreate is manipulating visuals in relation to sound. So for my POC I need to create a visual, with parameters that can be changed, then get some sound and see if I can analyse that sound to detect some data, which I can then use to manipulate the visual parameters. Easy, right? So, let’s start at the beginning: creating a simple visual. For this I’m going to create a CSS animation. It’s just a funky i element with the opacity being changed to make it flash. See the Pen Creating a light by Rumyra (@Rumyra) on CodePen A note about prefixes: I’ve left them out of the code examples in this post to make them easier to read. Please be aware that you may need them. I find a great resource to find out if you do is caniuse.com. You can also check out all the code for the examples in this article Start the music Well, that’s pretty easy so far. Next up: loading in some sound. For this we’ll use the Web Audio API. The Web Audio API is based around the concept of nodes. You have a source node: the sound you are loading in; a destination node: usually the device’s speakers; and any number of processing nodes in between. All this processing that goes on with the audio is sandboxed within the AudioContext. So, let’s start by initialising our audio context. var contextClass = window.AudioContext; if (contextClass) { //web audio api available. var audioContext = new contextClass(); } else { //web audio api unavailable //warn user to upgrade/change browser } Now let’s load our sound file into the new context we created with an XMLHttpRequest. function loadSound() { //set audio file url var audioFileUrl = '/octave.ogg'; //create new request var request = new XMLHttpRequest(); request.open("GET", audioFileUrl, true); request.responseType = "arraybuffer"; request.onload = function() { //take from http request and decode into buffer context.decodeAudioData(request.response, function(buffer) { audioBuffer = buffer; }); } request.send(); } Phew! Now we’ve loaded in some sound! There are plenty of things we can do with the Web Audio API: increase volume; add filters; spatialisation. If you want to dig deeper, the O’Reilly Web Audio API book by Boris Smus is available to read online free. All we really want to do for this proof of concept, however, is analyse the sound data. To do this we really need to know what data we have. Learning the steps Let’s take a minute to step back and remember our school days and science class. I’m sure if I drew a picture of a sound wave, we would all start nodding our heads. The sound you hear is caused by pressure differences in the particles in the air. Sound pushes these particles together, causing vibrations. Amplitude is basically strength of pressure. A simple example of change of amplitude is when you increase the volume on your stereo and the output wave increases in size. This is great when everything is analogue, but the waveform varies continuously and it’s not suitable for digital processing: there’s an infinite set of values. For digital processing, we need discrete numbers. We have to sample the waveform at set time intervals, and record data such as amplitude and frequency. Luckily for us, just the fact we have a digital sound file means all this hard work is done for us. What we’re doing in the code above is piping that data in the audio context. All we need to do now is access it. We can do this with the Web Audio API’s analysing functionality. Just pop in an analysing node before we connect the source to its destination node. function createAnalyser(source) { //create analyser node analyser = audioContext.createAnalyser(); //connect to source source.connect(analyzer); //pipe to speakers analyser.connect(audioContext.destination); } The data I’m really interested in here is frequency. Later we could look into amplitude or time, but for now I’m going to stick with frequency. The analyser node gives us frequency data via the getFrequencyByteData method. Don’t forget to count! To collect the data from the getFrequencyByteData method, we need to pass in an empty array (a JavaScript typed array is ideal). But how do we know how many items the array will need when we create it? This is really up to us and how high the resolution of frequencies we want to analyse is. Remember we talked about sampling the waveform; this happens at a certain rate (sample rate) which you can find out via the audio context’s sampleRate attribute. This is good to bear in mind when you’re thinking about your resolution of frequencies. var sampleRate = audioContext.sampleRate; Let’s say your file sample rate is 48,000, making the maximum frequency in the file 24,000Hz (thanks to a wonderful theorem from Dr Harry Nyquist, the maximum frequency in the file is always half the sample rate). The analyser array we’re creating will contain frequencies up to this point. This is ideal as the human ear hears the range 0–20,000hz. So, if we create an array which has 2,400 items, each frequency recorded will be 10Hz apart. However, we are going to create an array which is half the size of the FFT (fast Fourier transform), which in this case is 2,048 which is the default. You can set it via the fftSize property. //set our FFT size analyzer.fftSize = 2048; //create an empty array with 1024 items var frequencyData = new Uint8Array(1024); So, with an array of 1,024 items, and a frequency range of 24,000Hz, we know each item is 24,000 ÷ 1,024 = 23.44Hz apart. The thing is, we also want that array to be updated constantly. We could use the setInterval or setTimeout methods for this; however, I prefer the new and shiny requestAnimationFrame. function update() { //constantly getting feedback from data requestAnimationFrame(update); analyzer.getByteFrequencyData(frequencyData); } Putting it all together Sweet sticks! Now we have an array of frequencies from the sound we loaded, updating as the sound plays. Now we want that data to trigger our animation from earlier. We can easily pause and run our CSS animation from JavaScript: element.style.webkitAnimationPlayState = "paused"; element.style.webkitAnimationPlayState = "running"; Unfortunately, this may not be ideal as our animation might be a whole heap longer than just a flashing light. We may want to target specific points within that animation to have it stop and start in a visually pleasing way and perhaps not smack bang in the middle. There is no really easy way to do this at the moment as Zach Saucier explains in this wonderful article. It takes some jiggery pokery with setInterval to try to ascertain how far through the CSS animation you are in percentage terms. This seems a bit much for our proof of concept, so let’s backtrack a little. We know by the animation we’ve created which CSS properties we want to change. This is pretty easy to do directly with JavaScript. element.style.opacity = "1"; element.style.opacity = "0.2"; So let’s start putting it all together. For this example I want to trigger each light as a different frequency plays. For this, I’ll loop through the HTML elements and change the opacity style if the frequency gain goes over a certain threshold. //get light elements var lights = document.getElementsByTagName('i'); var totalLights = lights.length; for (var i=0; i<totalLights; i++) { //get frequencyData key var freqDataKey = i*8; //if gain is over threshold for that frequency animate light if (frequencyData[freqDataKey] > 160){ //start animation on element lights[i].style.opacity = "1"; } else { lights[i].style.opacity = "0.2"; } } See all the code in action here. I suggest viewing in a modern browser :) Awesome! It is true — we can VJ in our browser! Let’s dance! So, let’s start to expand this simple example. First, I feel the need to make lots of lights, rather than just a few. Also, maybe we should try a sound file more suited to gigs or clubs. Check it out! I don’t know about you, but I’m pretty excited — that’s just a bit of HTML, CSS and JavaScript! The other thing to think about, of course, is the sound that you would get at a venue. We don’t want to load sound from a file, but rather pick up on what is playing in real time. The easiest way to do this, I’ve found, is to capture what my laptop’s mic is picking up and piping that back into the audio context. We can do this by using getUserMedia. Let’s include this in this demo. If you make some noise while viewing the demo, the lights will start to flash. And relax :) There you have it. Sit back, play some music and enjoy the Winamp like experience in front of you. So, where do we go from here? I already have a wealth of ideas. We haven’t started with canvas, SVG or the 3-D features of CSS. There are other things we can detect from the audio as well. And yes, OK, it’s questionable whether the browser is the best environment for this. For one, I’m using a whole bunch of nonsensical HTML elements (maybe each animation could be held within a web component in the future). But hey, it’s fun, and it looks cool and sometimes I think it’s OK to just dance. 2013 Ruth John ruthjohn 2013-12-02T00:00:00+00:00 https://24ways.org/2013/make-your-browser-dance/ code
70 Bringing Your Code to the Streets — or How to Be a Street VJ Our amazing world of web code is escaping out of the browser at an alarming rate and appearing in every aspect of the environment around us. Over the past few years we’ve already seen JavaScript used server-side, hardware coded with JavaScript, a rise of native style and desktop apps created with HTML, CSS and JavaScript, and even virtual reality (VR) is getting its fair share of front-end goodness. You can go ahead and play with JavaScript-powered hardware such as the Tessel or the Espruino to name a couple. Just check out the Tessel project page to see JavaScript in the world of coffee roasting or sleep tracking your pet. With the rise of the internet of things, JavaScript can be seen collecting information on flooding among other things. And if that’s not enough ‘outside the browser’ implementations, Node.js servers can even be found in aircraft! I previously mentioned VR and with three.js’s extra StereoEffect.js module it’s relatively simple to get browser 3D goodness to be Google Cardboard-ready, and thus set the stage for all things JavaScript and VR. It’s been pretty popular in the art world too, with interactive works such as Seb Lee-Delisle’s Lunar Trails installation, featuring the old arcade game Lunar Lander, which you can now play in your browser while others watch (it is the web after all). The Science Museum in London held Chrome Web Lab, an interactive exhibition featuring five experiments, showcasing the magic of the web. And it’s not even the connectivity of the web that’s being showcased; we can even take things offline and use web code for amazing things, such as fighting Ebola. One thing is for sure, JavaScript is awesome. Hell, if you believe those telly programs (as we all do), JavaScript can even take down the stock market, purely through the witchcraft of canvas! Go JavaScript! Now it’s our turn So I wanted to create a little project influenced by this theme, and as it’s Christmas, take it to the streets for a little bit of party fun! Something that could take code anywhere. Here’s how I made a portable visual projection pack, a piece of video mixing software and created some web-coded street art. Step one: The equipment You will need: One laptop: with HDMI output and a modern browser installed, such as Google Chrome. One battery-powered mini projector: I’ve used a Texas Instruments DLP; for its 120 lumens it was the best cost-to-lumens ratio I could find. One MIDI controller (optional): mine is an ICON iDJ as it suits mixing visuals. However, there is more affordable hardware on the market such as an Akai LPD8 or a Korg nanoPAD2. As you’ll see in the article, this is optional as it can be emulated within the software. A case to carry it all around in. Step two: The software The projected visuals, I imagined, could be anything you can create within a browser, whether that be simple HTML and CSS, images, videos, SVG or canvas. The only requirement I have is that they move or change with sound and that I can mix any one visual into another. You may remember a couple of years ago I created a demo on this very site, allowing audio-triggered visuals from the ambient sounds your device mic was picking up. That was a great starting point – I used that exact method to pick up the audio and thus the first requirement was complete. If you want to see some more examples of visuals I’ve put together for this, there’s a showcase on CodePen. The second requirement took a little more thought. I needed two screens, which could at any point show any of the visuals I had coded, but could be mixed from one into the other and back again. So let’s start with two divs, both absolutely positioned so they’re on top of each other, but at the start the second screen’s opacity is set to zero. Now all we need is a slider, which when moved from one side to the other slowly sets the second screen’s opacity to 1, thereby fading it in. See the Pen Mixing Screens (Software Version) by Rumyra (@Rumyra) on CodePen. Mixing Screens (CodePen) As you saw above, I have a MIDI controller and although the software method works great, I’d quite like to make use of this nifty piece of kit. That’s easily done with the Web MIDI API. All I need to do is call it, and when I move one of the sliders on the controller (I’ve allocated the big cross fader in the middle for this), pick up on the change of value and use that to control the opacity instead. var midi, data; // start talking to MIDI controller if (navigator.requestMIDIAccess) { navigator.requestMIDIAccess({ sysex: false }).then(onMIDISuccess, onMIDIFailure); } else { alert(“No MIDI support in your browser.”); } // on success function onMIDISuccess(midiData) { // this is all our MIDI data midi = midiData; var allInputs = midi.allInputs.values(); // loop over all available inputs and listen for any MIDI input for (var input = allInputs.next(); input && !input.done; input = allInputs.next()) { // when a MIDI value is received call the onMIDIMessage function input.value.onmidimessage = onMIDIMessage; } } function onMIDIMessage(message) { // data comes in the form [command/channel, note, velocity] data = message.data; // Opacity change for screen. The cross fader values are [176, 8, {0-127}] if ( (data[0] === 176) && (data[1] === 8) ) { // this value will change as the fader is moved var opacity = data[2]/127; screenTwo.style.opacity = opacity; } } The final code was slightly more complicated than this, as I decided to switch the two screens based on the frequencies of the sound that was playing, and use the cross fader to depict the frequency threshold value. This meant they flickered in and out of each other, rather than just faded. There’s a very rough-and-ready first version of the software on GitHub. Phew, Great! Now we need to get all this to the streets! Step three: Portable kit Did you notice how I mentioned a case to carry it all around in? I wanted the case to be morphable, so I could use the equipment from it too, a sort of bag-to-usherette-tray-type affair. Well, I had an unused laptop bag… I strengthened it with some MDF, so when I opened the bag it would hold like a tray where the laptop and MIDI controller would sit. The projector was Velcroed to the external pocket of the bag, so when it was a tray it would project from underneath. I added two durable straps, one for my shoulders and one round my waist, both attached to the bag itself. There was a lot of cutting and trimming. As it was a laptop bag it was pretty thick to start and sewing was tricky. However, I only broke one sewing machine needle; I’ve been known to break more working with leather, so I figured I was doing well. By the way, you can actually buy usherette trays, but I just couldn’t resist hacking my own :) Step four: Take to the streets First, make sure everything is charged – everything – a lot! The laptop has to power both the MIDI controller and the projector, and although I have a mobile phone battery booster pack, that’ll only charge the projector should it run out. I estimated I could get a good hour of visual artistry before I needed to worry, though. I had a couple of ideas about time of day and location. Here in the UK at this time of year, it gets dark around half past four, so I could easily head out in a city around 5pm and it would be dark enough for the projections to be seen pretty well. I chose Bristol, around the waterfront, as there were some interesting locations to try it out in. The best was Millennium Square: busy but not crowded and plenty of surfaces to try projecting on to. My first time out with the portable audio/visual pack (PAVP as it will now be named) was brilliant. I played music and projected visuals, like a one-woman band of A/V! You might be thinking what the point of this was, besides, of course, it being a bit of fun. Well, this project got me to look at canvas and SVG more closely. The Web MIDI API was really interesting; MIDI as a data format has some great practical uses. I think without our side projects we may not have all these wonderful uses for our everyday code. Not only do they remind us coding can, and should, be fun, they also help us learn and grow as makers. My favourite part? When I was projecting into a water feature in Millennium Square. For those who are familiar, you’ll know it’s like a wall of water so it produced a superb effect. I drew quite a crowd and a kid came to stand next to me and all I could hear him say with enthusiasm was, ‘Oh wow! That’s so cool!’ Yes… yes, kid, it was cool. Making things with code is cool. Massive thanks to the lovely Drew McLellan for his incredibly well-directed photography, and also Simon Johnson who took a great hand in perfecting the kit while it was attached. 2015 Ruth John ruthjohn 2015-12-06T00:00:00+00:00 https://24ways.org/2015/bringing-your-code-to-the-streets/ code
248 How to Use Audio on the Web I know what you’re thinking. I never never want to hear sound anywhere near a browser, ever ever, wow! 🙉 You’re having flashbacks, flashbacks to the days of yore, when we had a <bgsound> element and yup did everyone think that was the most rad thing since <blink>. I mean put those two together with a <marquee>, only use CSS colour names, make sure your borders were all set to ridge and you’ve got yourself the neatest website since 1998. The sound played when the website loaded and you could play a MIDI file as well! Everyone could hear that wicked digital track you chose. Oh, surfing was gnarly back then. Yes it is 2018, the end of in fact, soon to be 2019. We are certainly living in the future. Hoverboards self driving cars, holodecks VR headsets, rocket boots drone racing, sound on websites get real, Ruth. We can’t help but be jaded, even though the <bgsound> element is depreciated, and the autoplay policy appeared this year. Although still in it’s infancy, the policy “controls when video and audio is allowed to autoplay”, which should reduce the somewhat obtrusive playing of sound when a website or app loads in the future. But then of course comes the question, having lived in a muted present for so long, where and why would you use audio? ✨ Showcase Time ✨ There are some incredible uses of audio on websites today. This is my personal favourite futurelibrary.no, a site from Norway chronicling books that have been published from a forest of trees planted precisely for the books themselves. The sound effects are lovely, adding to the overall experience. futurelibrary.no Another site that executes this well is pottermore.com. The Hogwarts WebGL simulation uses both sound effects and ambient background music and gives a great experience. The button hovers are particularly good. pottermore.com Eighty-six and a half years is a beautiful narrative site, documenting the musings of an eighty-six and a half year old man. The background music playing on this site is not offensive, it adds to the experience. Eighty-six and a half years Sound can be powerful and in some cases useful. Last year I wrote about using them to help validate forms. Audiochart is a library which “allows the user to explore charts on web pages using sound and the keyboard”. Ben Byford recorded voice descriptions of the pages on his website for playback should you need or want it. There is a whole area of accessibility to be explored here. Then there’s education. Fancy beginning with some piano in the new year? flowkey.com is a website which allows you to play along and learn at the same time. Need to brush up on your music theory? lightnote.co takes you through lessons to do just that, all audio enhanced. Electronic music more your thing? Ableton has your back with learningmusic.ableton.com, a site which takes you through the process of composing electronic music. A website, all made possible through the powers with have with the Web Audio API today. lightnote.co learningmusic.ableton.com Considerations Yes, tis the season, let’s be more thoughtful about our audios. There are some user experience patterns to begin with. 86andahalfyears.com tells the user they are about to ‘enter’ the site and headphones are recommended. This is a good approach because it a) deals with the autoplay policy (audio needs to be instigated by a user gesture) and b) by stating headphones are recommended you are setting the users expectations, they will expect sound, and if in a public setting can enlist the use of a common electronic device to cause less embarrassment. Eighty-six and a half years Allowing mute and/or volume control clearly within the user interface is a good idea. It won’t draw the user out of the experience, it’ll give more control to the user about what audio they want to hear (they may not want to turn down the volume of their entire device), and it’s less thought to reach for a very visible volume than to fumble with device settings. Indicating that sound is playing is also something to consider. Browsers do this by adding icons to tabs, but this isn’t always the first place to look for everyone. To The Future So let’s go! We see amazing demos built with Web Audio, and I’m sure, like me, they make you think, oh wow I wish I could do that / had thought of that / knew the first thing about audio to begin to even conceive that. But audio doesn’t actually need to be all bells and whistles (hey, it’s Christmas). Starting, stopping and adjusting simple panning and volume might be all you need to get started to introduce some good sound design in your web design. Isn’t it great then that there’s a tutorial just for that! Head on over to the MDN Web Audio API docs where the Using the Web Audio API article takes you through playing and pausing sounds, volume control and simple panning (moving the sound from left to right on stereo speakers). This year I believe we have all experienced the web as a shopping mall more than ever. It’s shining store fronts, flashing adverts, fast food, loud noises. Let’s use 2019 to create more forests to explore, oceans to dive and mountains to climb. 2018 Ruth John ruthjohn 2018-12-22T00:00:00+00:00 https://24ways.org/2018/how-to-use-audio-on-the-web/ design
190 Self-Testing Pages with JavaScript Working at an agency I am involved more and more on projects in which client side code is developed internally then sent out to a separate team for implementation. You provide static HTML, CSS and JavaScript which then get placed into the CMS and brought to life as an actual website. As you can imagine this can sometimes lead to frustrations. However many safeguards you include, handing over your code to someone else is always a difficult thing to do effectively. In this article I will show you how you can create a JavaScript implementation checker and that will give you more time for drink based activity as your web site and apps are launched quicker and with less unwanted drama! An all too frequent occurrence You’ve been working on a project for weeks, fixed all your bugs and send it to be implemented. You hear nothing and assume all is going well then a few days before it’s meant to launch you get an email from the implementation team informing you of bugs in your code that you need to urgently fix. The 24ways website with a misspelt ID for the years menu Being paranoid you trawl through the preview URL, check they have the latest files, check your code for errors then notice that a required HTML attribute has been omitted from the build and therefore CSS or JavaScript you’ve hooked onto that particular attribute isn’t being applied and that’s what is causing the “bug”. It takes you seconds drafting an email informing them of this, it takes then seconds putting the required attribute in and low and behold the bug is fixed, everyone is happy but you’ve lost a good few hours of your life – this time could have been better spent in the pub. I’m going to show you a way that these kind of errors can be alerted immediately during implementation of your code and ensure that when you are contacted you know that there actually is a bug to fix. You probably already know the things that could be omitted from a build and look like bugs so you’ll soon be creating tests to look for these and alert when they are not found on the rendered page. The error is reported directly to those who need to know about it and fix it. Less errant bug reports and less frantic emails ahoy! A page with an implementation issue and instant feedback on the problem JavaScript selector engines to the rescue Whether you’re using a library or indeed tapping into the loveliness of the new JavaScript Selector APIs looking for particular HTML elements in JavaScript is fairly trivial now. For instance this is how you look for a div element with the id attribute of year (the missing attribute from top image) using jQuery (the library I’ll be coding my examples in): if ($(‘div#year’).length) { alert(‘win’); } Using this logic you can probably imagine how you can write up a quick method to check for the existence of a particular element and alert when it’s not present — but assuming you have a complex page you’re going to be repeating yourself a fair bit and we don’t want to be doing that. Test scripts If you’ve got a lot of complex HTML patterns that need testing across a number of different pages it makes sense to keep your tests out of production code. Chances are you’ve already got a load of heavy JavaScript assets, and when it comes to file size saving every little helps. I don’t think that tests should contain code inside of them so keep mine externally as JSON. This also means that you can use the one set of tests in multiple places. We already know that it’s a good idea to keep our CSS and JavaScript separate so lets continue along those lines here. The test script for this example looks like this: { "title": "JS tabs implementation test", "description": "Check that the correct HTML patterns has been used", "author": "Ross Bruniges", "created": "20th July 2009", "tests": [ { "name": "JS tabs elements", "description": "Checking that correct HTML elements including class/IDs are used on the page for the JS to progressively enhance", "selector": "div.tabbed_content", "message": "We couldn't find VAR on the page - it's required for our JavaScript to function correctly", "check_for": { "contains": { "elements": [ "div.tab_content", "h2" ], "message": "We've noticed some missing HTML:</p><ul><li>VAR</li></ul><p>please refer to the examples sent for reference" } } } ] } The first four lines are just a little bit of meta data so we remember what this test was all about when we look at it again in the future, or indeed if it ever breaks. The tests are the really cool parts and firstly you’ll notice that it’s an array – we’re only going to show one example test here but there is no reason why you can’t place in as many as you want. I’ll explain what each of the lines in the example test means: name – short test name, I use this in pass/fail messaging later description – meta data for future reference selector – the root HTML element from which your HTML will be searched message – what the app will alert if the initial selector isn’t found check_for – a wrapper to hold inner tests – those run if the initial selector does match contains – the type of check, we’re checking that the selector contains specified elements elements – the HTML elements we are searching for message – a message for when these don’t match (VAR is substituted when it’s appended to the page with the name of any elements that don’t exist) It’s very important to pass the function valid JSON (JSONLint is a great tool for this) otherwise you might get a console showing no tests have even been run. The JavaScript that makes this helpful Again, this code should never hit a production server so I’ve kept it external. This also means that the only thing that’s needed to be done by the implementation team when they are ready to build is that they delete this code. <script src="sleuth.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function() { sleuth.test_page.init(‘js_tabs_test.js'); }); </script> “View the full JavaScript:/examples/self-testing-pages-with-javascript/js/tests/test_suite.js The init function appends the test console to the page and inserts the CSS file required to style it (you don’t need to use pictures of me when tests pass and fail though I see no reason why you shouldn’t), goes and grabs the JSON file referenced and parses it. The methods to pass (tests_pass) and fail (haz_fail) the test I hope are pretty self-explanatory as is the one which creates the test summary once everything has been run (create_summary). The two interesting functions are init_tests and confirm_html. init_tests init_tests:function(i,obj) { var $master_elm = $(obj.selector); sleuth.test_page.$logger.append("<div id='test_" + i + "' class='message'><p><em>" + obj.name + "</em></p></div>"); var $container = $('#test_' + i); if (!$master_elm.length) { var err_sum = obj.message.replace(/VAR/gi, obj.selector); sleuth.test_page.haz_failed(err_sum, $container); return; } if (obj.check_for) { $.each(obj.check_for,function(key, value){ sleuth.test_page.assign_checks($master_elm, $container, key, value); }); } else { sleuth.test_page.tests_passed($container); return; } } The function gets sent the number of the current iteration (used to create a unique id for its test summary) and the current object that contains the data we’re testing against as parameters. We grab a reference to the root element and this is used (pretty much in the example shown right at the start of this article) and its length is checked. If the length is positive we know we can continue to the inner tests (if they exist) but if not we fail the test and don’t go any further. We append the error to the test console for everyone to see. If we pass the initial check we send the reference to the root element, message contains and the inner object to a function that in this example sends us on to confirm_html (if we had a more complex test suite it would do a lot more). confirm_html confirm_html:function(target_selector, error_elm, obj) { var missing_elms = []; $.each(obj.elements, function(i, val) { if (!target_selector.find(val).length) { missing_elms.push(val); } }); if (missing_elms.length) { var file_list = missing_elms.join('</li><li>'); var err_sum = obj.message.replace(/VAR/gi, file_list); sleuth.test_page.haz_failed(err_sum, error_elm); return; } sleuth.test_page.tests_passed(error_elm); return; } We’re again using an array to check for a passed or failed test and checking its length but this time we push in a reference to each missing element we find. If the test does fail we’re providing even more useful feedback by informing what elements have been missed out. All the implementation team need do is look for them in the files we’ve sent and include them as expected. No more silly implementation bugs! Here is an example of a successful implementation. Here are some examples of failed implementations – one which fails at finding the root node and one that has the correct root node but none of the inner HTML tests pass. Is this all we can check for? Certainly not! JavaScript provides pretty easy ways to check for attributes, included files (if the files being checked for are being referenced correctly and not 404ing) and even applied CSS. Want to check that those ARIA attributes are being implemented correctly or that all images contain an alt attribute well this simple test suite can be extended to include tests for this – the sky is pretty much up to your imagination. 2009 Ross Bruniges rossbruniges 2009-12-12T00:00:00+00:00 https://24ways.org/2009/self-testing-pages-with-javascript/ process
63 Be Fluid with Your Design Skills: Build Your Own Sites Just five years ago in 2010, when we were all busy trying to surprise and delight, learning CSS3 and trying to get whole websites onto one page, we had a poster on our studio wall. It was entitled ‘Designers Vs Developers’, an infographic that showed us the differences between the men(!) who created websites. Designers wore skinny jeans and used Macs and developers wore cargo pants and brought their own keyboards to work. We began to learn that designers and developers were not only doing completely different jobs but were completely different people in every way. This opinion was backed up by hundreds of memes, millions of tweets and pages of articles which used words like void and battle and versus. Thankfully, things move quickly in this industry; the wide world of web design has moved on in the last five years. There are new devices, technologies, tools – and even a few women. Designers have been helped along by great apps, software, open source projects, conferences, and a community of people who, to my unending pride, love to share their knowledge and their work. So the world has moved on, and if Miley Cyrus, Ruby Rose and Eliot Sumner are identifying as gender fluid (an identity which refers to a gender which varies over time or is a combination of identities), then I would like to come out as discipline fluid! OK, I will probably never identify as a developer, but I will identify as fluid! How can we be anything else in an industry that moves so quickly? That’s how we should think of our skills, our interests and even our job titles. After all, Steve Jobs told us that “Design is not just what it looks like and feels like. Design is how it works.” Sorry skinny-jean-wearing designers – this means we’re all designing something together. And it’s not just about knowing the right words to use: you have to know how it feels. How it feels when you make something work, when you fix that bug, when you make it work on IE. Like anything in life, things run smoothly when you make the effort to share experiences, empathise and deeply understand the needs of others. How can designers do that if they’ve never built their own site? I’m not talking the big stuff, I’m talking about your portfolio site, your mate’s business website, a website for that great idea you’ve had. I’m talking about doing it yourself to get an unique insight into how it feels. We all know that designers and developers alike love an <ol>, so here it is. Ten reasons designers should be fluid with their skills and build their own sites 1. It’s never been easier Now here’s where the definition of ‘build’ is going to get a bit loose and people are going to get angry, but when I say it’s never been easier I mean because of the existence of apps and software like WordPress, Squarespace, Tumblr, et al. It’s easy to make something and get it out there into the world, and these are all gateway drugs to hard coding! 2. You’ll understand how it feels How it feels to be so proud that something actually works that you momentarily don’t notice if the kerning is off or the padding is inconsistent. How it feels to see your site appear when you’ve redirected a URL. How it feels when you just can’t work out where that one extra space is in a line of PHP that has killed your whole site. 3. It makes you a designer Not a better designer, it makes you a designer when you are designing how things look and how they work. 4. You learn about movement Photoshop and Sketch just don’t cut it yet. Until you see your site in a browser or your app on a phone, it’s hard to imagine how it moves. Building your own sites shows you that it’s not just about how the content looks on the screen, but how it moves, interacts and feels. 5. You make techie friends All the tutorials and forums in the world can’t beat your network of techie friends. Since I started working in web design I have worked with, sat next to, and co-created with some of the greatest developers. Developers who’ve shared their knowledge, encouraged me to build things, patiently explained HTML, CSS, servers, divs, web fonts, iOS development. There has been no void, no versus, very few battles; just people who share an interest and love of making things. 6. You will own domain names When something is paid for, online and searchable then it’s real and you’ve got to put the work in. Buying domains has taught me how to stop procrastinating, but also about DNS, FTP, email, and how servers work. 7. People will ask you to do things
 Learning about code and development opens a whole new world of design. When you put your own personal websites and projects out there people ask you to do more things. OK, so sometimes those things are “Make me a website for free”, but more often it’s cool things like “Come and speak at my conference”, “Write an article for my magazine” and “Collaborate with me.” 8. The young people are coming! They love typography, they love print, they love layout, but they’ve known how to put a website together since they started their first blog aged five and they show me clever apps they’ve knocked together over the weekend! They’re new, they’re fluid, and they’re better than us! 9. Your portfolio is your portfolio OK, it’s an obvious one, but as designers our work is our CV, our legacy! We need to show our skill, our attention to detail and our creativity in the way we showcase our work. Building your portfolio is the best way to start building your own websites. (And please be that designer who’s bothered to work out how to change the Squarespace favicon!) 10. It keeps you fluid! Building your own websites is tough. You’ll never be happy with it, you’ll constantly be updating it to keep up with technology and fashion, and by the time you’ve finished it you’ll want to start all over again. Perfect for forcing you to stay up-to-date with what’s going on in the industry. </ol> 2015 Ros Horner roshorner 2015-12-12T00:00:00+00:00 https://24ways.org/2015/be-fluid-with-your-design-skills-build-your-own-sites/ code
334 Transitional vs. Strict Markup When promoting web standards, standardistas often talk about XHTML as being more strict than HTML. In a sense it is, since it requires that all elements are properly closed and that attribute values are quoted. But there are two flavours of XHTML 1.0 (three if you count the Frameset DOCTYPE, which is outside the scope of this article), defined by the Transitional and Strict DOCTYPEs. And HTML 4.01 also comes in those flavours. The names reveal what they are about: Transitional DOCTYPEs are meant for those making the transition from older markup to modern ways. Strict DOCTYPEs are actually the default – the way HTML 4.01 and XHTML 1.0 were constructed to be used. A Transitional DOCTYPE may be used when you have a lot of legacy markup that cannot easily be converted to comply with a Strict DOCTYPE. But Strict is what you should be aiming for. It encourages, and in some cases enforces, the separation of structure and presentation, moving the presentational aspects from markup to CSS. From the HTML 4 Document Type Definition: This is HTML 4.01 Strict DTD, which excludes the presentation attributes and elements that W3C expects to phase out as support for style sheets matures. Authors should use the Strict DTD when possible, but may use the Transitional DTD when support for presentation attribute and elements is required. An additional benefit of using a Strict DOCTYPE is that doing so will ensure that browsers use their strictest, most standards compliant rendering modes. Tommy Olsson provides a good summary of the benefits of using Strict over Transitional in Ten questions for Tommy Olsson at Web Standards Group: In my opinion, using a Strict DTD, either HTML 4.01 Strict or XHTML 1.0 Strict, is far more important for the quality of the future web than whether or not there is an X in front of the name. The Strict DTD promotes a separation of structure and presentation, which makes a site so much easier to maintain. For those looking to start using web standards and valid, semantic markup, it is important to understand the difference between Transitional and Strict DOCTYPEs. For complete listings of the differences between Transitional and Strict DOCTYPEs, see XHTML: Differences between Strict & Transitional, Comparison of Strict and Transitional XHTML, and XHTML1.0 Element Attributes by DTD. Some of the differences are more likely than others to cause problems for developers moving from a Transitional DOCTYPE to a Strict one, and I’d like to mention a few of those. Elements that are not allowed in Strict DOCTYPEs center font iframe strike u Attributes not allowed in Strict DOCTYPEs align (allowed on elements related to tables: col, colgroup, tbody, td, tfoot, th, thead, and tr) language background bgcolor border (allowed on table) height (allowed on img and object) hspace name (allowed in HTML 4.01 Strict, not allowed on form and img in XHTML 1.0 Strict) noshade nowrap target text, link, vlink, and alink vspace width (allowed on img, object, table, col, and colgroup) Content model differences An element type’s content model describes what may be contained by an instance of the element type. The most important difference in content models between Transitional and Strict is that blockquote, body, and form elements may only contain block level elements. A few examples: text and images are not allowed immediately inside the body element, and need to be contained in a block level element like p or div input elements must not be direct descendants of a form element text in blockquote elements must be wrapped in a block level element like p or div Go Strict and move all presentation to CSS Something that can be helpful when doing the transition from Transitional to Strict DOCTYPEs is to focus on what each element of the page you are working on is instead of how you want it to look. Worry about looks later and get the structure and semantics right first. 2005 Roger Johansson rogerjohansson 2005-12-13T00:00:00+00:00 https://24ways.org/2005/transitional-vs-strict-markup/ code
279 Design the Invisible to Tell Better Stories on the Web For design to be meaningful we need to tell stories. We need to design the invisible, the cues, the messages and the extra detail hidden beneath the aesthetics. It’s all about the story. From verbal exchanges around the campfire to books, the web and everything in between, storytelling allows us to share, organize and process information more efficiently. It helps us understand our surroundings and make emotional connections to people, places and experiences. Web design lends itself perfectly to the conventions of storytelling, a universal process. However, the stories vary because they’re defined by culture, society, politics and religion. All of which need considering if you are to design stories that are relevant to your target audience. The benefits of approaching design with storytelling in mind from the very start of the project is that we are creating considered design that allows users to quickly gather meaning from the website. They do this by reading between the lines and drawing on the wealth of knowledge they have acquired about the associations between colours, typyefaces and signs. With so much recognition and analysis happening subconsciously you have to consider how design communicates on this level. This invisible layer has a significant impact on what you say, how you say it and who you say it to. How can we design something that’s invisible? By researching and making conscious decisions about exactly what you are communicating, you can make the invisible visible. As is often quoted, good design is like air, you only notice it when it’s bad. So by designing the invisible the aim is to design stories that the audience receive subliminally, so that they go somewhat unnoticed, like good air. Storytelling strands To share these stories through design, you can break it down into several strands. Each strand tells a story on its own, but when combined they may start to tell a different story altogether. These strands are colour, typefaces, branding, tone of voice and symbols. All are literal and visible but the invisible element is the meaning behind them – meaning that you can extract and share. In this article I want to focus on colour, typefaces and tone of voice and on how combining story strands can change the meaning. Colour Let’s start with colour. Red represents emotions such as love but can also signify war. Green is commonly used for all things environmental and purple is a colour that connotes wealth and royalty. These associations between colour and emotion or value have been learned over time and are continually reinforced through media and culture. With this knowledge come expectations from your users. For example, they will expect Valentine’s Day sites to be red and kids’ sites to be bright and colourful. This is true in the same way audiences have expectations of certain genres of film or music. These conventions help savvy audiences decode texts and read between the lines or, rather, to draw meaning from the invisible. It’s practically an innate skill. This is why you need to design the invisible: because users will quickly deduce meaning from your site and fill in the story’s gaps, it’s important to give them as much of that story to begin with. A story relevant to their culture. Of all the ways you can tell stories through web design, colour is the most fascinating and important. Not only does it evoke emotions in users but its meaning varies significantly between cultures. In the west, for example, white is a colour associated with weddings, and black is the colour of mourning. This is signified by the traditions of brides wearing white and those in mourning wearing black. In other cultures the meanings are reversed, as black is a colour that represents good luck and white is a colour that signifies mourning. If you assume the same values are true in all cultures then you risk offending the very people you are targeting. When colours combine, the story being told can change. If you design using red, white and blue then it’s going to be difficult to shake off patriotic connotations because this colour combination is so ingrained as being American or British or French thanks largely to their flags. This extends to politics too. Each party has its own representative colour. In the UK, the Conservatives are blue and Labour is red so it would be inappropriate storytelling to design a Labour-related website in blue as there would be a conflict between the content and the design, a conflict that would result in a poor user experience. Conflicts become more of an issue when you start to combine story strands. I once saw a No VAT advert use the symbol on the left: There’s a complete conflict in storytelling here between the sign and its colour. The prohibition sign was used over the word VAT to mean no VAT; that makes sense. But this is a symbol that is used to communicate to people that something is being prohibited or prevented, it mustn’t continue. So to use green contradicts the message of the sign itself; green is used as a colour to say yes, go, proceed, enter. The same would be true if we had a tick in red and a cross in green. Bad design here means the story is flawed and the user experience is compromised. Typefaces Typefaces also tell stories. They are so much more than the words that are written with them because they connote different values. Here are a few: Serif fonts are more formal and are associated with tradition, sophistication and high-end values. Sans serif fonts, on the other hand, are synonymous with modernity, informality and friendliness. These perceptions are again reinforced through more traditional media such as newspaper mastheads, where the serious news-focused broadsheets have serif titles, and the showbiz and gossip-led tabloids have sans serif titles. This translates to the web as well. With these associations already familiar to users, they may see copy and focus on the words, but if the way that copy is displayed jars with the context then we are back to having conflicting stories like the No VAT sign earlier. Let’s take official institutions, for example. The White House, the monarchy, 10 Downing Street and other government departments are formal, traditional and important organisations. If the copy on their websites were written in a typeface like Cooper Black, it would erase any authority and respect that they were due. They need people to take them seriously and trust them, and part of the way to do this is to have a typeface that represents those values. It works both ways though. If Innocent, Threadless or other fun companies used traditional typefaces, they wouldn’t be accurate reflections of their core values, brand and personality. They are better positioned to use friendly, informal and modern typefaces. But still never Comic Sans. Tone of voice Closely tied to this is tone of voice, my absolute bugbear on the web. Tone of voice isn’t what is said but, rather, how it is said. When we interact with others in person we don’t just listen to the words they say, but we also draw meaning from their body language, and pitch and tone of voice. Just because the web removes that face-to-face interaction with your audience it doesn’t mean you can’t have a tone of voice. Innocent pioneered the informal chatty tone of voice that so many others have since emulated, but unless it is representative of your company, then it’s not appropriate. It works for Innocent because the tone of voice is consistent across all the company’s materials, both online and offline. Ben and Jerry’s takes the same approach, as does Threadless, but maybe you need a more formal or corporate tone of voice. It really depends on what your business or service is and who it is for, and that is why I think LoveFilm has it all wrong. LoveFilm offers a film and game rental service, something fun for people in their downtime. While they aren’t particularly stuffy, neither is their tone of voice very friendly or informal, which is what I would expect from a service like theirs. The reason they have it wrong is in the language they use and the way their sentences are constructed. This is the first time we’ve discussed language because, on the whole, designing the invisible isn’t concerned with language at all. But that doesn’t mean that these strands can’t still elicit an emotional response in users. Jon Tan quoted Dr Mazviita Chirimuuta in his New Adventures in Web Design talk in January 2011: Although there is no absolute separation between language and emotion, there will still be countless instances where you have emotional response without verbal input or linguistic cognition. In general language is not necessary for emotion. This is even more pertinent when the emotions evoked are connected to people’s culture, surroundings and way of life. It makes design personal, something that audiences can connect with at more than just face value but, rather, on a subliminal or, indeed, invisible level. It also means that when you are asked the inevitable question of why – why is blue the dominant colour? why have you used that typeface? why don’t we sound like Innocent? – you will have a rationale behind each design decision that can explain what story you are telling, how you discovered the story and how it is targeted at the core audience. Research This is where research plays a vital role in the project cycle. If you don’t know and understand your audience then you don’t know what story to design. Every project lends itself to some level of research, but how in-depth and what methods are most appropriate will be dictated by project requirements and budget restrictions – but do your research. Even if you think you know your audience, it doesn’t hurt to research and reaffirm that because cultures and society do change, albeit slowly, but they can change. So ask questions at the start of the project during the research phase: What do different colours mean for your audience’s culture? Do the typeface and tone of voice appeal to the demographic? Does the brand identity represent the values and personality of your service? Are there any social, political or religious significances associated with your audience that you need to take into consideration so you don’t offend them? Ask questions, understand your audience, design your story based on these insights, and create better user experiences in context that have good, solid storytelling at their heart. Major hat tip to Gareth Strange for the beautiful graphics used within this article. 2011 Robert Mills robertmills 2011-12-14T00:00:00+00:00 https://24ways.org/2011/design-the-invisible/ design
286 Defending the Perimeter Against Web Widgets On July 14, 1789, citizens of Paris stormed the Bastille, igniting a revolution that toppled the French monarchy. On July 14 of this year, there was a less dramatic (though more tweeted) takedown: The Deck network, which delivers advertising to some of the most popular web design and culture destinations, was down for about thirty minutes. During this period, most partner sites running ads from The Deck could not be viewed as result. A few partners were unaffected (aside from not having an ad to display). Fortunately, Dribbble, was one of them. In this article, I’ll discuss outages like this and how to defend against them. But first, a few qualifiers: The Deck has been rock solid – this is the only downtime we’ve witnessed since joining in June. More importantly, the issues in play are applicable to any web widget you might add to your site to display third-party content. Down and out Your defense is only as good as its weakest link. Web pages are filled with links, some of which threaten the ability of your page to load quickly and correctly. If you want your site to work when external resources fail, you need to identify the weak links on your site. In this article, we’ll talk about web widgets as a point of failure and defensive JavaScript techniques for handling them. Widgets 101 Imagine a widget that prints out a Pun of the Day on your site. A simple technique for both widget provider and consumer is for the provider to expose a URL: http://widgetjonesdiary.com/punoftheday.js which returns a JavaScript file like this: document.write("<h2>The Pun of the Day</h2><p>Where do frogs go for beers after work? Hoppy hour!</p>"); The call to document.write() injects the string passed into the document where it is called. So to display the widget on your page, simply add an external script tag where you want it to appear: <div class="punoftheday"> <script src="http://widgetjonesdiary.com/punoftheday.js"></script> <!-- Content appears here as output of script above --> </div> This approach is incredibly easy for both provider and consumer. But there are implications… document.write()… or wrong? As in the example above, scripts may perform a document.write() to inject HTML. Page rendering halts while a script is processed so any output can be inlined into the document. Therefore, page rendering speed depends on how fast the script returns the data. If an external JavaScript widget hangs, so does the page content that follows. It was this scenario that briefly stalled partner sites of The Deck last summer. The elegant solution To make our web widget more robust, calls to document.write() should be avoided. This can be achieved with a technique called JSONP (AKA JSON with padding). In our example, instead of writing inline with document.write(), a JSONP script passes content to a callback function: publishPun("<h2>Pun of the Day</h2><p>Where do frogs go for beers after work? Hoppy hour!</p>"); Then, it’s up to the widget consumer to implement a callback function responsible for displaying the content. Here’s a simple example where our callback uses jQuery to write the content into a target <div>: <!-- Where widget content should appear --> <div class="punoftheday"></div> … <br /> function publishPun(content) { $(&#8216;.punoftheday&#8217;).html(content); // Writes content display location<br /> }<br /> View Example 1 Even if the widget content appears at the top of the page, our script can be included at the bottom so it’s non-blocking: a slow response leaves page rendering unaffected. It simply invokes the callback which, in turn, writes the widget content to its display destination. The hack But what to do if your provider doesn’t support JSONP? This was our case with The Deck. Returning to our example, I’m reminded of computer scientist David Wheeler’s statement, “All problems in computer science can be solved by another level of indirection… Except for the problem of too many layers of indirection.” In our case, the indirection is to move the widget content into position after writing it to the page. This allows us to place the widget <script> tag at the bottom of the page so rendering won’t be blocked, but still display the widget in the target. The strategy: Load widget content into a hidden <div> at the bottom of the page. Move the loaded content from the hidden <div> to its display location. and the code: <!-- Where widget content should appear --> <div class="punoftheday"></div> … <br /> $(&#8216;.punoftheday&#8217;).append($(&#8216;.loading-dock&#8217;).children(&#8216;:gt(0)&#8217;));<br /> View Example 2 After the external punoftheday.js script has processed, the rendered HTML will look as follows: <div class="loading-dock hidden"> <script src="http://widgetjonesdiary.com/punoftheday.js"></script> <h2>Pun of the Day</h2> <p>Where do frogs go for beers after work? Hoppy hour!</p> </div> The ‘loading-dock’ <div> now includes the widget content, albeit hidden from view (if we’ve styled the ‘hidden’ class with display: none). There’s just one more step: move the content to its display destination. This line of jQuery (from above) does the trick: $('.punoftheday').append($('.loading-dock').children(':gt(0)')); This selects all child elements in the ‘loading-doc’ <div> except the first – the widget <script> tag which generated it – and moves it to the display destination. Worth noting is the :gt(0) jQuery selector extension, which allows us to exclude the first (in a 0-based array) child element – the widget <script> tag – from selection. Since all of this happens at the bottom of the page, just before the </body> tag, no rendering has to wait on the external widget script. The only thing that fails if our widget hangs is… the widget itself. Our weakest link has been strengthened and so has our site. DE-FENSE! 2011 Rich Thornett richthornett 2011-12-06T00:00:00+00:00 https://24ways.org/2011/defending-the-perimeter-against-web-widgets/ process
53 Get Expressive with Your Typography In 1955 Beatrice Warde, an American communicator on typography, published a series of essays entitled The Crystal Goblet in which she wrote, “People who love ideas must have a love of words. They will take a vivid interest in the clothes that words wear.” And with that proposition Warde introduced the idea that just as we judge someone based on the clothes they are wearing, so we make judgements about text based on the typefaces in which it is set. Beatrice Warde. ©1970 Monotype Imaging Inc. Choosing the same typeface as everyone else, especially if you’re trying to make a statement, is like turning up to a party in the same dress; to a meeting in the same suit, shirt and tie; or to a craft ale dispensary in the same plaid shirt and turned-up skinny jeans. But there’s more to your choice of typeface than simply making an impression. In 2012 Jon Tan wrote on 24 ways about a scientific study called “The Aesthetics of Reading” which concluded that “good quality typography is responsible for greater engagement during reading and thus induces a good mood.” Furthermore, at this year’s Ampersand conference Sarah Hyndman, an expert in multisensory typography, discussed how typefaces can communicate with our subconscious. Sarah showed that different fonts could have an effect on how food tasted. A rounded font placed near a bowl of jellybeans would make them taste sweeter, and a jagged angular font would make them taste more sour. The quality of your typography can therefore affect the mood of your reader, and your font choice directly affect the senses. This means you can manipulate the way people feel. You can change their emotional state through type alone. Now that’s a real superpower! The effects of your body text design choices are measurable but subtle. If you really want to have an impact you need to think big. Literally. Display text and headings are your attention grabbers. They are your chance to interrupt, introduce and seduce. Display text and headings set the scene and draw people in. Text set large creates an image that visitors see before they read, and that’s your chance to choose a typeface that immediately expresses what the text, and indeed the entire website, stands for. What expectations of the text do you want to set up? Youthful enthusiasm? Businesslike? Cutting-edge? Hipster? Sensible and secure? Fun and informal? Authoritarian? Typography conveys much more than just information. It imparts feeling, emotion and sentiment, and arouses preconceived ideas of trust, tone and content. Think about taking advantage of this by introducing impactful, expressive typography to your designs on the web. You can alter the way your reader feels, so what emotion do you want to provoke? Maybe you want them to feel inspired like this stop smoking campaign: helsenorge.no Perhaps they should be moved and intrigued, as with Makeshift magazine: mkshft.org Or calmly reassured: www.cleopatra-marina.gr Fonts also tap into the complex library of associations that we’ve been accumulating in our brains all of our lives. You build up these associations every time you see a font from the context that you see it in. All of us associate certain letterforms with topics, times and places. Retiro is obviously Spanish: Retiro by Typofonderie Bodoni and Eurostile used in this menu couldn’t be much more Italian: Bodoni and Eurostile, both designed in Italy To me, Clarendon gives a sense of the 1960s and 1970s. I’m not sure if that’s what Costa was going for, but that’s what it means to me: Costa coffee flier And Knockout and Gotham really couldn’t be much more American: Knockout and Gotham by Hoefler & Co When it comes to choosing your display typeface, the type designer Christian Schwartz says there are two kinds. First are the workhorse typefaces that will do whatever you want them to do. Helvetica, Proxima Nova and Futura are good examples. These fonts can be shaped in many different ways, but this also means they are found everywhere and take great skill and practice to work with in a unique and striking manner. The second kind of typeface is one that does most of the work for you. Like finely tailored clothing, it’s the detail in the design that adds interest. Setting headings in Bree rather than Helvetica makes a big difference to the tone of the article Such typefaces carry much more inherent character, but are also less malleable and harder to adapt to different contexts. Good examples are Marr Sans, FS Clerkenwell, Strangelove and Bree. Push the boat out Remember, all type can have an effect on the reader. Take advantage of that and allow your type to have its own vernacular and impact. Be expressive with your type. Don’t be too reverential, dogmatic – or ordinary. Be brave and push a few boundaries. Adapted from Web Typography a book in progress by Richard Rutter. 2015 Richard Rutter richardrutter 2015-12-04T00:00:00+00:00 https://24ways.org/2015/get-expressive-with-your-typography/ design
120 Easier Page States for Wireframes When designing wireframes for web sites and web apps, it is often overlooked that the same ‘page’ can look wildly different depending on its context. A logged-in page will look different from a logged-out page; an administrator’s view may have different buttons than a regular user’s view; a power user’s profile will be more extensive than a new user’s. These different page states need designing at some point, especially if the wireframes are to form a useful communication medium between designer and developer. Documenting the different permutations can be a time consuming exercise involving either multiple pages in one’s preferred box-and-arrow software, or a fully fledged drawing containing all the possible combinations annotated accordingly. Enter interactive wireframes and Polypage Interactive wireframes built in HTML are a great design and communication tool. They provide a clickable prototype, running in the browser as would the final site. As such they give a great feel for how the site will be to use. Once you add in the possibilities of JavaScript and a library such as jQuery, they become even more flexible and powerful. Polypage is a jQuery plugin which makes it really easy to design multiple page states in HTML wireframes. There’s no JavaScript knowledge required (other than cutting and pasting in a few lines). The page views are created by simply writing all the alternatives into your HTML page and adding special class names to apply state and conditional view logic to the various options. When the page is loaded Polypage automatically detects the page states defined by the class names and creates a control bar enabling the user to toggle page states with the click of a mouse or the clack of a keyboard. Using cookies by way of the jQuery cookie plugin, Polypage retains the view state throughout your prototype. This means you could navigate through your wireframes as if you were logged out; as if you were logged in as an administrator; with notes on or off; or with any other view or state you might require. The possibilities are entirely up to you. How does it work? Firstly you need to link to jQuery, the jQuery cookie plugin and to Polypage. Something like this: <script src="javascripts/jquery-1.2.6.min.js" type="text/javascript"></script> <script src="javascripts/cookie.jquery.js" type="text/javascript"></script> <script src="javascripts/polypage.jquery.js" type="text/javascript"></script> Then you need to initialise Polypage on page load using something along these lines: <script type="text/javascript"> $(document).ready(function() { $.polypage.init(); }); </script> Next you need to define the areas of your wireframe which are particular to a given state or view. Do this by applying classes beginning with pp_. Polypage will ignore all other classes in the document. The pp_ prefix should be followed by a state name. This can be any text string you like, bearing in mind it will appear in the control bar. Typical page states might include ‘logged_in’, ‘administrator’ or ‘group_owner’. A complete class name would therefore look something like pp_logged_in. Examples If a user is logged in, you might want to specify an option for him or her to sign out. Using Polypage, this could be put in the wireframe as follows: <a href="logout" class="pp_logged_in"> Sign out </a> Polypage will identify the pp_logged_in class on the link and hide it (as the ‘Sign out’ link should only be shown when the page is in the ‘logged in’ view). Polypage will then automatically write a ‘logged in’ toggle to the control bar, enabling you to show or hide the ‘Sign out’ link by toggling the ‘logged in’ view. The same will apply to all content marked with a pp_logged_in class. States can also be negated by adding a not keyword to the class name. For example you might want to provide a log in link for users who are not signed in. Using Polypage, you would insert the not keyword after the pp prefix as follows: <a href="login" class="pp_not_logged_in"> Login </a> Again Polypage identifies the pp prefix but this time sees that the ‘Login’ link should not be shown when the ‘logged in’ state is selected. States can also be joined together to add some basic logic to pages. The syntax follows natural language and uses the or and and keywords in addition to the afore-mentioned not. Some examples would be pp_logged_in_and_admin, pp_admin_or_group_owner and pp_logged_in_and_not_admin. Finally, you can set default states for a page by passing an array to the polypage.init() function like this: $.polypage.init(['logged_in', 'admin']); You can see a fully fledged example in this fictional social network group page. The example page defaults to a logged in state. You can see the logged out state by toggling ‘logged in’ off in the Polypage control bar. There are also views specified for a group member, a group admin, a new group and notes. Where can I get hold of it? You can download the current version from GitHub. Polypage was originally developed by Clearleft and New Bamboo, with particular contributions from Andy Kent and Natalie Downe. It has been used in numerous real projects, but it is still an early release so there is bound to be room for improvement. We’re pleased to say that Polypage is now an open source project so any feedback, particularly by way of actual improvements, is extremely welcome. 2008 Richard Rutter richardrutter 2008-12-11T00:00:00+00:00 https://24ways.org/2008/easier-page-states-for-wireframes/ process
141 Compose to a Vertical Rhythm “Space in typography is like time in music. It is infinitely divisible, but a few proportional intervals can be much more useful than a limitless choice of arbitrary quantities.” So says the typographer Robert Bringhurst, and just as regular use of time provides rhythm in music, so regular use of space provides rhythm in typography, and without rhythm the listener, or the reader, becomes disorientated and lost. On the Web, vertical rhythm – the spacing and arrangement of text as the reader descends the page – is contributed to by three factors: font size, line height and margin or padding. All of these factors must calculated with care in order that the rhythm is maintained. The basic unit of vertical space is line height. Establishing a suitable line height that can be applied to all text on the page, be it heading, body copy or sidenote, is the key to a solid dependable vertical rhythm, which will engage and guide the reader down the page. To see this in action, I’ve created an example with headings, footnotes and sidenotes. Establishing a suitable line height The easiest place to begin determining a basic line height unit is with the font size of the body copy. For the example I’ve chosen 12px. To ensure readability the body text will almost certainly need some leading, that is to say spacing between the lines. A line-height of 1.5em would give 6px spacing between the lines of body copy. This will create a total line height of 18px, which becomes our basic unit. Here’s the CSS to get us to this point: body { font-size: 75%; } html>body { font-size: 12px; } p { line-height 1.5em; } There are many ways to size text in CSS and the above approach provides and accessible method of achieving the pixel-precision solid typography requires. By way of explanation, the first font-size reduces the body text from the 16px default (common to most browsers and OS set-ups) down to the 12px we require. This rule is primarily there for Internet Explorer 6 and below on Windows: the percentage value means that the text will scale predictably should a user bump the text size up or down. The second font-size sets the text size specifically and is ignored by IE6, but used by Firefox, Safari, IE7, Opera and other modern browsers which allow users to resize text sized in pixels. Spacing between paragraphs With our rhythmic unit set at 18px we need to ensure that it is maintained throughout the body copy. A common place to lose the rhythm is the gaps set between margins. The default treatment by web browsers of paragraphs is to insert a top- and bottom-margin of 1em. In our case this would give a spacing between the paragraphs of 12px and hence throw the text out of rhythm. If the rhythm of the page is to be maintained, the spacing of paragraphs should be related to the basic line height unit. This is achieved simply by setting top- and bottom-margins equal to the line height. In order that typographic integrity is maintained when text is resized by the user we must use ems for all our vertical measurements, including line-height, padding and margins. p { font-size:1em; margin-top: 1.5em; margin-bottom: 1.5em; } Browsers set margins on all block-level elements (such as headings, lists and blockquotes) so a way of ensuring that typographic attention is paid to all such elements is to reset the margins at the beginning of your style sheet. You could use a rule such as: body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,p,blockquote,th,td { margin:0; padding:0; } Alternatively you could look into using the Yahoo! UI Reset style sheet which removes most default styling, so providing a solid foundation upon which you can explicitly declare your design intentions. Variations in text size When there is a change in text size, perhaps with a heading or sidenotes, the differing text should also take up a multiple of the basic leading. This means that, in our example, every diversion from the basic text size should take up multiples of 18px. This can be accomplished by adjusting the line-height and margin accordingly, as described following. Headings Subheadings in the example page are set to 14px. In order that the height of each line is 18px, the line-height should be set to 18 ÷ 14 = 1.286. Similarly the margins above and below the heading must be adjusted to fit. The temptation is to set heading margins to a simple 1em, but in order to maintain the rhythm, the top and bottom margins should be set at 1.286em so that the spacing is equal to the full 18px unit. h2 { font-size:1.1667em; line-height: 1.286em; margin-top: 1.286em; margin-bottom: 1.286em; } One can also set asymmetrical margins for headings, provided the margins combine to be multiples of the basic line height. In our example, a top margin of 1½ lines is combined with a bottom margin of half a line as follows: h2 { font-size:1.1667em; line-height: 1.286em; margin-top: 1.929em; margin-bottom: 0.643em; } Also in our example, the main heading is given a text size of 18px, therefore the line-height has been set to 1em, as has the margin: h1 { font-size:1.5em; line-height: 1em; margin-top: 0; margin-bottom: 1em; } Sidenotes Sidenotes (and other supplementary material) are often set at a smaller size to the basic text. To keep the rhythm, this smaller text should still line up with body copy, so a calculation similar to that for headings is required. In our example, the sidenotes are set at 10px and so their line-height must be increased to 18 ÷ 10 = 1.8. .sidenote { font-size:0.8333em; line-height:1.8em; } Borders One additional point where vertical rhythm is often lost is with the introduction of horizontal borders. These effectively act as shims pushing the subsequent text downwards, so a two pixel horizontal border will throw out the vertical rhythm by two pixels. A way around this is to specify horizontal lines using background images or, as in our example, specify the width of the border in ems and adjust the padding to take up the slack. The design of the footnote in our example requires a 1px horizontal border. The footnote contains 12px text, so 1px in ems is 1 ÷ 12 = 0.0833. I have added a margin of 1½ lines above the border (1.5 × 18 ÷ 12 = 2.5ems), so to maintain the rhythm the border + padding must equal a ½ (9px). We know the border is set to 1px, so the padding must be set to 8px. To specify this in ems we use the familiar calculation: 8 ÷ 12 = 0.667. Hit me with your rhythm stick Composing to a vertical rhythm helps engage and guide the reader down the page, but it takes typographic discipline to do so. It may seem like a lot of fiddly maths is involved (a few divisions and multiplications never hurt anyone) but good type setting is all about numbers, and it is this attention to detail which is the key to success. 2006 Richard Rutter richardrutter 2006-12-12T00:00:00+00:00 https://24ways.org/2006/compose-to-a-vertical-rhythm/ design
146 Increase Your Font Stacks With Font Matrix Web pages built in plain old HTML and CSS are displayed using only the fonts installed on users’ computers (@font-face implementations excepted). To enable this, CSS provides the font-family property for specifying fonts in order of preference (often known as a font stack). For example: h1 {font-family: 'Egyptienne F', Cambria, Georgia, serif} So in the above rule, headings will be displayed in Egyptienne F. If Egyptienne F is not available then Cambria will be used, failing that Georgia or the final fallback default serif font. This everyday bit of CSS will be common knowledge among all 24 ways readers. It is also a commonly held belief that the only fonts we can rely on being installed on users’ computers are the core web fonts of Arial, Times New Roman, Verdana, Georgia and friends. But is that really true? If you look in the fonts folder of your computer, or even your Mum’s computer, then you are likely to find a whole load of fonts besides the core ones. This is because many software packages automatically install extra typefaces. For example, Office 2003 installs over 100 additional fonts. Admittedly not all of these fonts are particularly refined, and not all are suitable for the Web. However they still do increase your options. The Matrix I have put together a matrix of (western) fonts showing which are installed with Mac and Windows operating systems, which are installed with various versions of Microsoft Office, and which are installed with Adobe Creative Suite. The matrix is available for download as an Excel file and as a CSV. There are no readily available statistics regarding the penetration of Office or Creative Suite, but you can probably take an educated guess based on your knowledge of your readers. The idea of the matrix is that use can use it to help construct your font stack. First of all pick the font you’d really like for your text – this doesn’t have to be in the matrix. Then pick the generic family (serif, sans-serif, cursive, fantasy or monospace) and a font from each of the operating systems. Then pick any suitable fonts from the Office and Creative Suite lists. For example, you may decide your headings should be in the increasingly ubiquitous Clarendon. This is a serif type face. At OS-level the most similar is arguably Georgia. Adobe CS2 comes with Century Old Style which has a similar feel. Century Schoolbook is similar too, and is installed with all versions of Office. Based on this your font stack becomes: font-family: 'Clarendon Std', 'Century Old Style Std', 'Century Schoolbook', Georgia, serif Note the ‘Std’ suffix indicating a ‘standard’ OpenType file, which will normally be your best bet for more esoteric fonts. I’m not suggesting the process of choosing suitable fonts is an easy one. Firstly there are nearly two hundred fonts in the matrix, so learning what each font looks like is tricky and potentially time consuming (if you haven’t got all the fonts installed on a machine to hand you’ll be doing a lot of Googling for previews). And it’s not just as simple as choosing fonts that look similar or have related typographic backgrounds, they need to have similar metrics as well, This is especially true in terms of x-height which gives an indication of how big or small a font looks. Over to You The main point of all this is that there are potentially more fonts to consider than is generally accepted, so branch out a little (carefully and tastefully) and bring a little variety to sites out there. If you come up with any novel font stacks based on this approach, please do blog them (tagged as per the footer) and at some point they could all be combined in one place for everyone to consider. Appendix What about Linux? The only operating systems in the matrix are those from Microsoft and Apple. For completeness, Linux operating systems should be included too, although these are many and varied and very much in a minority, so I omitted them for time being. For the record, some Linux distributions come packaged with Microsoft’s core fonts. Others use the Vera family, and others use the Liberation family which comprises fonts metrically identical to Times New Roman and Arial. Sources The sources of font information for the matrix are as follows: Windows XP SP2 Windows Vista Office 2003 Office 2007 Mac OSX Tiger Mac OSX Leopard (scroll down two thirds) Office 2004 (Mac) by inspecting my Microsoft Office 2004/Office/Fonts folder Office 2008 (Mac) is expected to be as Office 2004 with the addition of the Vista ClearType fonts Creative Suite 2 (see pdf link in first comment) Creative Suite 3 2007 Richard Rutter richardrutter 2007-12-17T00:00:00+00:00 https://24ways.org/2007/increase-your-font-stacks-with-font-matrix/ design
239 Using the WebFont Loader to Make Browsers Behave the Same Web fonts give us designers a whole new typographic palette with which to work. However, browsers handle the loading of web fonts in different ways, and this can lead to inconsistent user experiences. Safari, Chrome and Internet Explorer leave a blank space in place of the styled text while the web font is loading. Opera and Firefox show text with the default font which switches over when the web font has loaded, resulting in the so-called Flash of Unstyled Text (aka FOUT). Some people prefer Safari’s approach as it eliminates FOUT, others think the Firefox way is more appropriate as content can be read whilst fonts download. Whatever your preference, the WebFont Loader can make all browsers behave the same way. The WebFont Loader is a JavaScript library that gives you extra control over font loading. It was co-developed by Google and Typekit, and released as open source. The WebFont Loader works with most web font services as well as with self-hosted fonts. The WebFont Loader tells you when the following events happen as a browser downloads web fonts (or loads them from cache): when fonts start to download (‘loading’) when fonts finish loading (‘active’) if fonts fail to load (‘inactive’) If your web page requires more than one font, the WebFont Loader will trigger events for individual fonts, and for all the fonts as a whole. This means you can find out when any single font has loaded, and when all the fonts have loaded (or failed to do so). The WebFont Loader notifies you of these events in two ways: by applying special CSS classes when each event happens; and by firing JavaScript events. For our purposes, we’ll be using just the CSS classes. Implementing the WebFont Loader As stated above, the WebFont Loader works with most web font services as well as with self-hosted fonts. Self-hosted fonts To use the WebFont Loader when you are hosting the font files on your own server, paste the following code into your web page: <script type="text/javascript"> WebFontConfig = { custom: { families: ['Font Family Name', 'Another Font Family'], urls: [ 'http://yourwebsite.com/styles.css' ] } }; (function() { var wf = document.createElement('script'); wf.src = ('https:' == document.location.protocol ? 'https' : 'http') + '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js'; wf.type = 'text/javascript'; wf.async = 'true'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(wf, s); })(); </script> Replace Font Family Name and Another Font Family with a comma-separated list of the font families you want to check against, and replace http://yourwebsite.com/styles.css with the URL of the style sheet where your @font-face rules reside. Fontdeck Assuming you have added some fonts to a website project in Fontdeck, use the afore-mentioned code for self-hosted solutions and replace http://yourwebsite.com/styles.css with the URL of the <link> tag in your Fontdeck website settings page. It will look something like http://f.fontdeck.com/s/css/xxxx/domain/nnnn.css. Typekit Typekit’s JavaScript-based implementation incorporates the WebFont Loader events by default, so you won’t need to include any WebFont Loader code. Making all browsers behave like Safari To make Firefox and Opera work in the same way as WebKit browsers (Safari, Chrome, etc.) and Internet Explorer, and thus minimise FOUT, you need to hide the text while the fonts are loading. While fonts are loading, the WebFont Loader adds a class of wf-loading to the <html> element. Once the fonts have loaded, the wf-loading class is removed and replaced with a class of wf-active (or wf-inactive if all of the fonts failed to load). This means you can style elements on the page while the fonts are loading and then style them differently when the fonts have finished loading. So, let’s say the text you need to hide while fonts are loading is contained in all paragraphs and top-level headings. By writing the following style rule into your CSS, you can hide the text while the fonts are loading: .wf-loading h1, .wf-loading p { visibility:hidden; } Because the wf-loading class is removed once the the fonts have loaded, the visibility:hidden rule will stop being applied, and the text revealed. You can see this in action on this simple example page. That works nicely across the board, but the situation is slightly more complicated. WebKit doesn’t wait for all fonts to load before displaying text: it displays text elements as soon as the relevant font is loaded. To emulate WebKit more accurately, we need to know when individual fonts have loaded, and apply styles accordingly. Fortunately, as mentioned earlier, the WebFont Loader has events for individual fonts too. When a specific font is loading, a class of the form wf-fontfamilyname-n4-loading is applied. Assuming headings and paragraphs are styled in different fonts, we can make our CSS more specific as follows: .wf-fontfamilyname-n4-loading h1, .wf-anotherfontfamily-n4-loading p { visibility:hidden; } Note that the font family name is transformed to lower case, with all spaces removed. The n4 is a shorthand for the weight and style of the font family. In most circumstances you’ll use n4 but refer to the WebFont Loader documentation for exceptions. You can see it in action on this Safari example page (you’ll probably need to disable your cache to see any change occur). Making all browsers behave like Firefox To make WebKit browsers and Internet Explorer work like Firefox and Opera, you need to explicitly show text while the fonts are loading. In order to make this happen, you need to specify a font family which is not a web font while the fonts load, like this: .wf-fontfamilyname-n4-loading h1 { font-family: 'arial narrow', sans-serif; } .wf-anotherfontfamily-n4-loading p { font-family: arial, sans-serif; } You can see this in action on the Firefox example page (again you’ll probably need to disable your cache to see any change occur). And there’s more That’s just the start of what can be done with the WebFont Loader. More areas to explore would be tweaking font sizes to reduce the impact of reflowing text and to better cater for very narrow fonts. By using the JavaScript events much more can be achieved too, such as fading in text as the fonts load. 2010 Richard Rutter richardrutter 2010-12-02T00:00:00+00:00 https://24ways.org/2010/using-the-webfont-loader-to-make-browsers-behave-the-same/ code
307 Get the Balance Right: Responsive Display Text Last year in 24 ways I urged you to Get Expressive with Your Typography. I made the case for grabbing your readers’ attention by setting text at display sizes, that is to say big. You should consider very large text in the same way you might a hero image: a picture that creates an atmosphere and anchors your layout. When setting text to be read, it is best practice to choose body and subheading sizes from a pre-defined scale appropriate to the viewport dimensions. We set those sizes using rems, locking the text sizes together so they all scale according to the page default and your reader’s preferences. You can take the same approach with display text by choosing larger sizes from the same scale. However, display text, as defined by its purpose and relative size, is text to be seen first, and read second. In other words a picture of text. When it comes to pictures, you are likely to scale all scene-setting imagery - cover photos, hero images, and so on - relative to the viewport. Take the same approach with display text: lock the size and shape of the text to the screen or browser window. Introducing viewport units With CSS3 came a new set of units which are locked to the viewport. You can use these viewport units wherever you might otherwise use any other unit of length such as pixels, ems or percentage. There are four viewport units, and in each case a value of 1 is equal to 1% of either the viewport width or height as reported in reference1 pixels: vw - viewport width, vh - viewport height, vmin - viewport height or width, whichever is smaller vmax - viewport height or width, whichever is larger In one fell swoop you can set the size of a display heading to be proportional to the screen or browser width, rather than choosing from a scale in a series of media queries. The following makes the heading font size 13% of the viewport width: h1 { font-size: 13 vw; } So for a selection of widths, the rendered font size would be: Rendered font size (px) Viewport width 13 vw 320 42 768 100 1024 133 1280 166 1920 250 A problem with using vw in this manner is the difference in text block proportions between portrait and landscape devices. Because the font size is based on the viewport width, the text on a landscape display is far bigger than when rendered on the same device held in a portrait orientation. Landscape text is much bigger than portrait text when using vw units. The proportions of the display text relative to the screen are so dissimilar that each orientation has its own different character, losing the inconsistency and considered design you would want when designing to make an impression. However if the text was the same size in both orientations, the visual effect would be much more consistent. This where vmin comes into its own. Set the font size using vmin and the size is now set as a proportion of the smallest side of the viewport, giving you a far more consistent rendering. h1 { font-size: 13vmin; } Landscape text is consistent with portrait text when using vmin units. Comparing vw and vmin renderings for various common screen dimensions, you can see how using vmin keeps the text size down to a usable magnitude: Rendered font size (px) Viewport 13 vw 13 vmin 320 × 480 42 42 414 × 736 54 54 768 × 1024 100 100 1024 × 768 133 100 1280 × 720 166 94 1366 × 768 178 100 1440 × 900 187 117 1680 × 1050 218 137 1920 × 1080 250 140 2560 × 1440 333 187 Hybrid font sizing Using vertical media queries to set text in direct proportion to screen dimensions works well when sizing display text. In can be less desirable when sizing supporting text such as sub-headings, which you may not want to scale upwards at the same rate as the display text. For example, we can size a subheading using vmin so that it starts at 16 px on smaller screens and scales up in the same way as the main heading: h1 { font-size: 13vmin; } h2 { font-size: 5vmin; } Using vmin alone for supporting text can scale it too quickly The balance of display text to supporting text on the phone works well, but the subheading text on the tablet, even though it has been increased in line with the main heading, is starting to feel disproportionately large and a little clumsy. This problem becomes magnified on even bigger screens. A solution to this is use a hybrid method of sizing text2. We can use the CSS calc() function to calculate a font size simultaneously based on both rems and viewport units. For example: h2 { font-size: calc(0.5rem + 2.5vmin); } For a 320 px wide screen, the font size will be 16 px, calculated as follows: (0.5 × 16) + (320 × 0.025) = 8 + 8 = 16px For a 768 px wide screen, the font size will be 27 px: (0.5 × 16) + (768 × 0.025) = 8 + 19 = 27px This results in a more balanced subheading that doesn’t take emphasis away from the main heading: To give you an idea of the effect of using a hybrid approach, here’s a side-by-side comparison of hybrid and viewport text sizing: table.ex--scale{width:100%;overflow: hidden;} table.ex--scale td{vertical-align:baseline;text-align:center;padding:0} tr.ex--scale-key{color:#666} tr.ex--scale-key td{font-size:.875rem;padding:0 0.125em} .ex--scale-2 tr.ex--scale-size{color:#ccc} tr.ex--scale-size td{font-size:1em;line-height:.34em;padding-bottom:.5rem} td.ex--scale-step{color:#000} td.ex--scale-hilite{color:red} .ex--scale-3 tr.ex--scale-size td{line-height:.9em} top: calc() hybrid method; bottom: vmin only 16 20 27 32 35 40 44 16 24 38 48 54 64 72 320 480 768 960 1080 1280 1440 Over this festive period, try experiment with the proportion of rem and vmin in your hybrid calculation to see what feels best for your particular setting. A reference pixel is based on the logical resolution of a device which takes into account double density screens such as Retina displays. ↩︎ For even more sophisticated uses of hybrid text sizing see the work of Mike Riethmuller. ↩︎ 2016 Richard Rutter richardrutter 2016-12-09T00:00:00+00:00 https://24ways.org/2016/responsive-display-text/ code
330 An Explanation of Ems Ems are so-called because they are thought to approximate the size of an uppercase letter M (and so are pronounced emm), although 1em is actually significantly larger than this. The typographer Robert Bringhurst describes the em thus: The em is a sliding measure. One em is a distance equal to the type size. In 6 point type, an em is 6 points; in 12 point type an em is 12 points and in 60 point type an em is 60 points. Thus a one em space is proportionately the same in any size. To illustrate this principle in terms of CSS, consider these styles: #box1 { font-size: 12px; width: 1em; height: 1em; border:1px solid black; } #box2 { font-size: 60px; width: 1em; height: 1em; border: 1px solid black; } These styles will render like: M and M Note that both boxes have a height and width of 1em but because they have different font sizes, one box is bigger than the other. Box 1 has a font-size of 12px so its width and height is also 12px; similarly the text of box 2 is set to 60px and so its width and height are also 60px. 2005 Richard Rutter richardrutter 2005-12-02T00:00:00+00:00 https://24ways.org/2005/an-explanation-of-ems/ design
55 How Tabs Should Work Tabs in browsers (not browser tabs) are one of the oldest custom UI elements in a browser that I can think of. They’ve been done to death. But, sadly, most of the time I come across them, the tabs have been badly, or rather partially, implemented. So this post is my definition of how a tabbing system should work, and one approach of implementing that. But… tabs are easy, right? I’ve been writing code for tabbing systems in JavaScript for coming up on a decade, and at one point I was pretty proud of how small I could make the JavaScript for the tabbing system: var tabs = $('.tab').click(function () { tabs.hide().filter(this.hash).show(); }).map(function () { return $(this.hash)[0]; }); $('.tab:first').click(); Simple, right? Nearly fits in a tweet (ignoring the whole jQuery library…). Still, it’s riddled with problems that make it a far from perfect solution. Requirements: what makes the perfect tab? All content is navigable and available without JavaScript (crawler-compatible and low JS-compatible). ARIA roles. The tabs are anchor links that: are clickable have block layout have their href pointing to the id of the panel element use the correct cursor (i.e. cursor: pointer). Since tabs are clickable, the user can open in a new tab/window and the page correctly loads with the correct tab open. Right-clicking (and Shift-clicking) doesn’t cause the tab to be selected. Native browser Back/Forward button correctly changes the state of the selected tab (think about it working exactly as if there were no JavaScript in place). The first three points are all to do with the semantics of the markup and how the markup has been styled. I think it’s easy to do a good job by thinking of tabs as links, and not as some part of an application. Links are navigable, and they should work the same way other links on the page work. The last three points are JavaScript problems. Let’s investigate that. The shitmus test Like a litmus test, here’s a couple of quick ways you can tell if a tabbing system is poorly implemented: Change tab, then use the Back button (or keyboard shortcut) and it breaks The tab isn’t a link, so you can’t open it in a new tab These two basic things are, to me, the bare minimum that a tabbing system should have. Why is this important? The people who push their so-called native apps on users can’t have more reasons why the web sucks. If something as basic as a tab doesn’t work, obviously there’s more ammo to push a closed native app or platform on your users. If you’re going to be a web developer, one of your responsibilities is to maintain established interactivity paradigms. This doesn’t mean don’t innovate. But it does mean: stop fucking up my scrolling experience with your poorly executed scroll effects. </rant> :breath: URI fragment, absolute URL or query string? A URI fragment (AKA the # hash bit) would be using mysite.com/config#content to show the content panel. A fully addressable URL would be mysite.com/config/content. Using a query string (by way of filtering the page): mysite.com/config?tab=content. This decision really depends on the context of your tabbing system. For something like GitHub’s tabs to view a pull request, it makes sense that the full URL changes. For our problem though, I want to solve the issue when the page doesn’t do a full URL update; that is, your regular run-of-the-mill tabbing system. I used to be from the school of using the hash to show the correct tab, but I’ve recently been exploring whether the query string can be used. The biggest reason is that multiple hashes don’t work, and comma-separated hash fragments don’t make any sense to control multiple tabs (since it doesn’t actually link to anything). For this article, I’ll keep focused on using a single tabbing system and a hash on the URL to control the tabs. Markup I’m going to assume subcontent, so my markup would look like this (yes, this is a cat demo…): <ul class="tabs"> <li><a class="tab" href="#dizzy">Dizzy</a></li> <li><a class="tab" href="#ninja">Ninja</a></li> <li><a class="tab" href="#missy">Missy</a></li> </ul> <div id="dizzy"> <!-- panel content --> </div> <div id="ninja"> <!-- panel content --> </div> <div id="missy"> <!-- panel content --> </div> It’s important to note that in the markup the link used for an individual tab references its panel content using the hash, pointing to the id on the panel. This will allow our content to connect up without JavaScript and give us a bunch of features for free, which we’ll see once we’re on to writing the code. URL-driven tabbing systems Instead of making the code responsive to the user’s input, we’re going to exclusively use the browser URL and the hashchange event on the window to drive this tabbing system. This way we get Back button support for free. With that in mind, let’s start building up our code. I’ll assume we have the jQuery library, but I’ve also provided the full code working without a library (vanilla, if you will), but it depends on relatively new (polyfillable) tech like classList and dataset (which generally have IE10 and all other browser support). Note that I’ll start with the simplest solution, and I’ll refactor the code as I go along, like in places where I keep calling jQuery selectors. function show(id) { // remove the selected class from the tabs, // and add it back to the one the user selected $('.tab').removeClass('selected').filter(function () { return (this.hash === id); }).addClass('selected'); // now hide all the panels, then filter to // the one we're interested in, and show it $('.panel').hide().filter(id).show(); } $(window).on('hashchange', function () { show(location.hash); }); // initialise by showing the first panel show('#dizzy'); This works pretty well for such little code. Notice that we don’t have any click handlers for the user and the Back button works right out of the box. However, there’s a number of problems we need to fix: The initialised tab is hard-coded to the first panel, rather than what’s on the URL. If there’s no hash on the URL, all the panels are hidden (and thus broken). If you scroll to the bottom of the example, you’ll find a “top” link; clicking that will break our tabbing system. I’ve purposely made the page long, so that when you click on a tab, you’ll see the page scrolls to the top of the tab. Not a huge deal, but a bit annoying. From our criteria at the start of this post, we’ve already solved items 4 and 5. Not a terrible start. Let’s solve items 1 through 3 next. Using the URL to initialise correctly and protect from breakage Instead of arbitrarily picking the first panel from our collection, the code should read the current location.hash and use that if it’s available. The problem is: what if the hash on the URL isn’t actually for a tab? The solution here is that we need to cache a list of known panel IDs. In fact, well-written DOM scripting won’t continuously search the DOM for nodes. That is, when the show function kept calling $('.tab').each(...) it was wasteful. The result of $('.tab') should be cached. So now the code will collect all the tabs, then find the related panels from those tabs, and we’ll use that list to double the values we give the show function (during initialisation, for instance). // collect all the tabs var tabs = $('.tab'); // get an array of the panel ids (from the anchor hash) var targets = tabs.map(function () { return this.hash; }).get(); // use those ids to get a jQuery collection of panels var panels = $(targets.join(',')); function show(id) { // if no value was given, let's take the first panel if (!id) { id = targets[0]; } // remove the selected class from the tabs, // and add it back to the one the user selected tabs.removeClass('selected').filter(function () { return (this.hash === id); }).addClass('selected'); // now hide all the panels, then filter to // the one we're interested in, and show it panels.hide().filter(id).show(); } $(window).on('hashchange', function () { var hash = location.hash; if (targets.indexOf(hash) !== -1) { show(hash); } }); // initialise show(targets.indexOf(location.hash) !== -1 ? location.hash : ''); The core of working out which tab to initialise with is solved in that last line: is there a location.hash? Is it in our list of valid targets (panels)? If so, select that tab. The second breakage we saw in the original demo was that clicking the “top” link would break our tabs. This was due to the hashchange event firing and the code didn’t validate the hash that was passed. Now this happens, the panels don’t break. So far we’ve got a tabbing system that: Works without JavaScript. Supports right-click and Shift-click (and doesn’t select in these cases). Loads the correct panel if you start with a hash. Supports native browser navigation. Supports the keyboard. The only annoying problem we have now is that the page jumps when a tab is selected. That’s due to the browser following the default behaviour of an internal link on the page. To solve this, things are going to get a little hairy, but it’s all for a good cause. Removing the jump to tab You’d be forgiven for thinking you just need to hook a click handler and return false. It’s what I started with. Only that’s not the solution. If we add the click handler, it breaks all the right-click and Shift-click support. There may be another way to solve this, but what follows is the way I found – and it works. It’s just a bit… hairy, as I said. We’re going to strip the id attribute off the target panel when the user tries to navigate to it, and then put it back on once the show code starts to run. This change will mean the browser has nowhere to navigate to for that moment, and won’t jump the page. The change involves the following: Add a click handle that removes the id from the target panel, and cache this in a target variable that we’ll use later in hashchange (see point 4). In the same click handler, set the location.hash to the current link’s hash. This is important because it forces a hashchange event regardless of whether the URL actually changed, which prevents the tabs breaking (try it yourself by removing this line). For each panel, put a backup copy of the id attribute in a data property (I’ve called it old-id). When the hashchange event fires, if we have a target value, let’s put the id back on the panel. These changes result in this final code: /*global $*/ // a temp value to cache *what* we're about to show var target = null; // collect all the tabs var tabs = $('.tab').on('click', function () { target = $(this.hash).removeAttr('id'); // if the URL isn't going to change, then hashchange // event doesn't fire, so we trigger the update manually if (location.hash === this.hash) { // but this has to happen after the DOM update has // completed, so we wrap it in a setTimeout 0 setTimeout(update, 0); } }); // get an array of the panel ids (from the anchor hash) var targets = tabs.map(function () { return this.hash; }).get(); // use those ids to get a jQuery collection of panels var panels = $(targets.join(',')).each(function () { // keep a copy of what the original el.id was $(this).data('old-id', this.id); }); function update() { if (target) { target.attr('id', target.data('old-id')); target = null; } var hash = window.location.hash; if (targets.indexOf(hash) !== -1) { show(hash); } } function show(id) { // if no value was given, let's take the first panel if (!id) { id = targets[0]; } // remove the selected class from the tabs, // and add it back to the one the user selected tabs.removeClass('selected').filter(function () { return (this.hash === id); }).addClass('selected'); // now hide all the panels, then filter to // the one we're interested in, and show it panels.hide().filter(id).show(); } $(window).on('hashchange', update); // initialise if (targets.indexOf(window.location.hash) !== -1) { update(); } else { show(); } This version now meets all the criteria I mentioned in my original list, except for the ARIA roles and accessibility. Getting this support is actually very cheap to add. ARIA roles This article on ARIA tabs made it very easy to get the tabbing system working as I wanted. The tasks were simple: Add aria-role set to tab for the tabs, and tabpanel for the panels. Set aria-controls on the tabs to point to their related panel (by id). I use JavaScript to add tabindex=0 to all the tab elements. When I add the selected class to the tab, I also set aria-selected to true and, inversely, when I remove the selected class I set aria-selected to false. When I hide the panels I add aria-hidden=true, and when I show the specific panel I set aria-hidden=false. And that’s it. Very small changes to get full sign-off that the tabbing system is bulletproof and accessible. Check out the final version (and the non-jQuery version as promised). In conclusion There’s a lot of tab implementations out there, but there’s an equal amount that break the browsing paradigm and the simple linkability of content. Clearly there’s a special hell for those tab systems that don’t even use links, but I think it’s clear that even in something that’s relatively simple, it’s the small details that make or break the user experience. Obviously there are corners I’ve not explored, like when there’s more than one set of tabs on a page, and equally whether you should deliver the initial markup with the correct tab selected. I think the answer lies in using query strings in combination with hashes on the URL, but maybe that’s for another year! 2015 Remy Sharp remysharp 2015-12-22T00:00:00+00:00 https://24ways.org/2015/how-tabs-should-work/ code
182 Breaking Out The Edges of The Browser HTML5 contains more than just the new entities for a more meaningful document, it also contains an arsenal of JavaScript APIs. So many in fact, that some APIs have outgrown the HTML5 spec’s backyard and have been sent away to grow up all on their own and been given the prestigious honour of being specs in their own right. So when I refer to (bendy finger quote) “HTML5”, I mean the HTML5 specification and a handful of other specifications that help us authors build web applications. Examples of those specs I would include in the umbrella term would be: geolocation, web storage, web databases, web sockets and web workers, to name a few. For all you guys and gals, on this special 2009 series of 24 ways, I’m just going to focus on data storage and offline applications: boldly taking your browser where no browser has gone before! Web Storage The Web Storage API is basically cookies on steroids, a unhealthy dosage of steroids. Cookies are always a pain to work with. First of all you have the problem of setting, changing and deleting them. Typically solved by Googling and blindly relying on PPK’s solution. If that wasn’t enough, there’s the 4Kb limit that some of you have hit when you really don’t want to. The Web Storage API gets around all of the hoops you have to jump through with cookies. Storage supports around 5Mb of data per domain (the spec’s recommendation, but it’s open to the browsers to implement anything they like) and splits in to two types of storage objects: sessionStorage – available to all pages on that domain while the window remains open localStorage – available on the domain until manually removed Support Ignoring beta browsers for our support list, below is a list of the major browsers and their support for the Web Storage API: Latest: Internet Explorer, Firefox, Safari (desktop & mobile/iPhone) Partial: Google Chrome (only supports localStorage) Not supported: Opera (as of 10.10) Usage Both sessionStorage and localStorage support the same interface for accessing their contents, so for these examples I’ll use localStorage. The storage interface includes the following methods: setItem(key, value) getItem(key) key(index) removeItem(key) clear() In the simple example below, we’ll use setItem and getItem to store and retrieve data: localStorage.setItem('name', 'Remy'); alert( localStorage.getItem('name') ); Using alert boxes can be a pretty lame way of debugging. Conveniently Safari (and Chrome) include database tab in their debugging tools (cmd+alt+i), so you can get a visual handle on the state of your data: Viewing localStorage As far as I know only Safari has this view on stored data natively in the browser. There may be a Firefox plugin (but I’ve not found it yet!) and IE… well that’s just IE. Even though we’ve used setItem and getItem, there’s also a few other ways you can set and access the data. In the example below, we’re accessing the stored value directly using an expando and equally, you can also set values this way: localStorage.name = "Remy"; alert( localStorage.name ); // shows "Remy" The Web Storage API also has a key method, which is zero based, and returns the key in which data has been stored. This should also be in the same order that you set the keys, for example: alert( localStorage.getItem(localStorage.key(0)) ); // shows "Remy" I mention the key() method because it’s not an unlikely name for a stored value. This can cause serious problems though. When selecting the names for your keys, you need to be sure you don’t take one of the method names that are already on the storage object, like key, clear, etc. As there are no warnings when you try to overwrite the methods, it means when you come to access the key() method, the call breaks as key is a string value and not a function. You can try this yourself by creating a new stored value using localStorage.key = "foo" and you’ll see that the Safari debugger breaks because it relies on the key() method to enumerate each of the stored values. Usage Notes Currently all browsers only support storing strings. This also means if you store a numeric, it will get converted to a string: localStorage.setItem('count', 31); alert(typeof localStorage.getItem('count')); // shows "string" This also means you can’t store more complicated objects natively with the storage objects. To get around this, you can use Douglas Crockford’s JSON parser (though Firefox 3.5 has JSON parsing support baked in to the browser – yay!) json2.js to convert the object to a stringified JSON object: var person = { name: 'Remy', height: 'short', location: 'Brighton, UK' }; localStorage.setItem('person', JSON.stringify(person)); alert( JSON.parse(localStorage.getItem('person')).name ); // shows "Remy" Alternatives There are a few solutions out there that provide storage solutions that detect the Web Storage API, and if it’s not available, fall back to different technologies (for instance, using a flash object to store data). One comprehensive version of this is Dojo’s storage library. I’m personally more of a fan of libraries that plug missing functionality under the same namespace, just as Crockford’s JSON parser does (above). For those interested it what that might look like, I’ve mocked together a simple implementation of sessionStorage. Note that it’s incomplete (because it’s missing the key method), and it could be refactored to not using the JSON stringify (but you would need to ensure that the values were properly and safely encoded): // requires json2.js for all browsers other than Firefox 3.5 if (!window.sessionStorage && JSON) { window.sessionStorage = (function () { // window.top.name ensures top level, and supports around 2Mb var data = window.top.name ? JSON.parse(window.top.name) : {}; return { setItem: function (key, value) { data[key] = value+""; // force to string window.top.name = JSON.stringify(data); }, removeItem: function (key) { delete data[key]; window.top.name = JSON.stringify(data); }, getItem: function (key) { return data[key] || null; }, clear: function () { data = {}; window.top.name = ''; } }; })(); } Now that we’ve cracked the cookie jar with our oversized Web Storage API, let’s have a look at how we take our applications offline entirely. Offline Applications Offline applications is (still) part of the HTML5 specification. It allows developers to build a web app and have it still function without an internet connection. The app is access via the same URL as it would be if the user were online, but the contents (or what the developer specifies) is served up to the browser from a local cache. From there it’s just an everyday stroll through open web technologies, i.e. you still have access to the Web Storage API and anything else you can do without a web connection. For this section, I’ll refer you to a prototype demo I wrote recently of a contrived Rubik’s cube (contrived because it doesn’t work and it only works in Safari because I’m using 3D transforms). Offline Rubik’s cube Support Support for offline applications is still fairly limited, but the possibilities of offline applications is pretty exciting, particularly as we’re seeing mobile support and support in applications such as Fluid (and I would expect other render engine wrapping apps). Support currently, is as follows: Latest: Safari (desktop & mobile/iPhone) Sort of: Firefox‡ Not supported: Internet Explorer, Opera, Google Chrome ‡ Firefox 3.5 was released to include offline support, but in fact has bugs where it doesn’t work properly (certainly on the Mac), Minefield (Firefox beta) has resolved the bug. Usage The status of the application’s cache can be tested from the window.applicationCache object. However, we’ll first look at how to enable your app for offline access. You need to create a manifest file, which will tell the browser what to cache, and then we point our web page to that cache: <!DOCTYPE html> <html manifest="remy.manifest"> <!-- continues ... --> For the manifest to be properly read by the browser, your server needs to serve the .manifest files as text/manifest by adding the following to your mime.types: text/cache-manifest manifest Next we need to populate our manifest file so the browser can read it: CACHE MANIFEST /demo/rubiks/index.html /demo/rubiks/style.css /demo/rubiks/jquery.min.js /demo/rubiks/rubiks.js # version 15 The first line of the manifest must read CACHE MANIFEST. Then subsequent lines tell the browser what to cache. The HTML5 spec recommends that you include the calling web page (in my case index.html), but it’s not required. If I didn’t include index.html, the browser would cache it as part of the offline resources. These resources are implicitly under the CACHE namespace (which you can specify any number of times if you want to). In addition, there are two further namespaces: NETWORK and FALLBACK. NETWORK is a whitelist namespace that tells the browser not to cache this resource and always try to request it through the network. FALLBACK tells the browser that whilst in offline mode, if the resource isn’t available, it should return the fallback resource. Finally, in my example I’ve included a comment with a version number. This is because once you include a manifest, the only way you can tell the browser to reload the resources is if the manifest contents changes. So I’ve included a version number in the manifest which I can change forcing the browser to reload all of the assets. How it works If you’re building an app that makes use of the offline cache, I would strongly recommend that you add the manifest last. The browser implementations are very new, so can sometimes get a bit tricky to debug since once the resources are cached, they really stick in the browser. These are the steps that happen during a request for an app with a manifest: Browser: sends request for your app.html Server: serves all associated resources with app.html – as normal Browser: notices that app.html has a manifest, it re-request the assets in the manifest Server: serves the requested manifest assets (again) Browser: window.applicationCache has a status of UPDATEREADY Browser: reloads Browser: only request manifest file (which doesn’t show on the net requests panel) Server: responds with 304 Not Modified on the manifest file Browser: serves all the cached resources locally What might also add confusion to this process, is that the way the browsers work (currently) is if there is a cache already in place, it will use this first over updated resources. So if your manifest has changed, the browser will have already loaded the offline cache, so the user will only see the updated on the next reload. This may seem a bit convoluted, but you can also trigger some of this manually through the applicationCache methods which can ease some of this pain. If you bind to the online event you can manually try to update the offline cache. If the cache has then updated, swap the updated resources in to the cache and the next time the app loads it will be up to date. You could also prompt your user to reload the app (which is just a refresh) if there’s an update available. For example (though this is just pseudo code): addEvent(applicationCache, 'updateready', function () { applicationCache.swapCache(); tellUserToRefresh(); }); addEvent(window, 'online', function () { applicationCache.update(); }); Breaking out of the Browser So that’s two different technologies that you can use to break out of the traditional browser/web page model and get your apps working in a more application-ny way. There’s loads more in the HTML5 and non-HTML5 APIs to play with, so take your Christmas break to check them out! 2009 Remy Sharp remysharp 2009-12-02T00:00:00+00:00 https://24ways.org/2009/breaking-out-the-edges-of-the-browser/ code
172 The Construction of Instruction If the world were made to my specifications, all your clients would be happy to pay for a web writer to craft every sentence into something as elegant as it was functional, and the client would have planned the content so that you had it just when you asked, but we both know that won’t happen every time. Sometimes you just know they are going to write the About page, two company blog pages and a Facebook fan page before resigning their position as chief content writer and you are going to end up filling in all the details that will otherwise just be Lorem Ipsum. Welcome to the big world of microcopy: A man walks into a bar. The bartender nods a greeting and watches as the man scans the bottles behind the bar. “Er, you have a lot of gin here. Is there one you would recommend?” “Yes sir.” Long pause. “… Never mind, I’ll have the one in the green bottle.” “Certainly, sir. But you can’t buy it from this part of the bar. You need to go through the double doors there.” “But they look like they lead into the kitchen.” “Really, sir? Well, no, that’s where we allow customers to purchase gin.” The man walks through the doors. On the other side he is greeted by the same bartender. “Y-you!” he stammers but the reticent bartender is now all but silent. Unnerved, the man points to a green bottle, “Er, I’d like to buy a shot of that please. With ice and tonic water.” The bartender mixes the drink and puts it on the bar just out of the reach of the man and looks up. “Um, do you take cards?” the man asks, ready to present his credit card. The bartender goes to take the card to put it through the machine. “Wait! How much was it – with sales tax and everything? Do you take a gratuity?” The bartender simply shrugs. The man eyes him for a moment and decides to try his luck at the bar next door. In the Choose Your Own Adventure version of this story there are plenty of ways to stop the man giving up. You could let him buy the gin right where he was; you could make the price more obvious; you could signpost the place to buy gin. The mistakes made by the bar and bartender are painfully obvious. And yet, there are websites losing users everyday due to the same lack of clear instruction. A smidgen of well written copy goes a long way to reassure the nervous prospect. Just imagine if our man walked into the bar and the bartender explained that although the bar was here, sales were conducted in the next room because people were not then able to overhear the man’s card details. Instead, he is left to fend for himself. Online, we kick customers through the anonymous double doors with a merry ‘Paypal will handle your transaction!’. Recently I worked on a site where the default error message, to account for anything happening that the developers hadn’t accounted for, was ‘SOMETHING HAS GONE WRONG!’. It might have been technically accurate but this is not how to inspire confidence in your customers that they can make a successful purchase through you. As everyone knows they can shop just fine, thank you very much, it is your site they will blame. Card declined? It’s the site. Didn’t know my email address has changed? It’s the site. Can’t log in? It’s the site. Yes, yes. I know. None of these things are related to your site, or you the developer, but drop outs will be high and you’ll get imploring emails from your client asking you to wade knee deep into the site analytics to find a solution by testing 41 shades of blue because if it worked for Google…? Before you try a visual fix involving the Dulux paint chart breeding with a Pantone swatch, take an objective look at the information you are giving customers. How much are you assuming they know? How much are you relying on age-old labels and prompts without clarification? Here’s a fun example for non-North Americans: ask your Granny to write out her billing address. If she looks at you blankly, tell her it is the address where the bank sends her statements. Imagine how many fewer instances of the wrong address there would be if we routinely added that information when people purchased from the UK? Instead, we rely on a language convention that hasn’t much common usage without explanation because, well, because we always have since the banks told us how we could take payments online. So. Your client is busying themselves with writing the ultimate Facebook fan page about themselves and here you are left with creating a cohesive signup process or basket or purchase instructions. Here are five simple rules for bending puny humans to your will creating instructive instructions and constructive error messages that ultimately mean less hassle for you. Plan what you want to say and plan it out as early as possible This goes for all content. Walk a virtual mile in the shoes of your users. What specific help can you offer customers to actively encourage continuation and ensure a minimal amount of dropouts? Make space for that information. One of the most common web content mistakes is jamming too much into a space that has been defined by physical boundaries rather than planned out. If you manage it, the best you can hope for is that no-one notices it was a last-minute job. Mostly it reads like a bad game of Tetris with content sticking out all over the place. Use your words Microcopy often says a lot in a few words but without those words you could leave room for doubt. When doubt creeps in a customer wants reassurance just like Alice: This time (Alice) found a little bottle… with the words ‘DRINK ME’ beautifully printed on it in large letters. It was all very well to say ‘Drink me,’ but the wise little Alice was not going to do that in a hurry. ‘No, I’ll look first,’ she said, ‘and see whether it’s marked “poison” or not’ Alice in Wonderland, Lewis Carroll. Value clarity over brevity. Or a little more prosaically, “If in doubt, spell it out.” Thanks, Jeremy! Be prepared to help ‘Login failed: email/password combination is incorrect.’ Oh. ‘Login failed: email/password combination is incorrect. Are you typing in all capitals? Caps Lock may be on. Have you changed your email address recently and not updated your account with us? Try your old email address first. Can’t remember your password? We can help you reset it.’ Ah! Be direct and be informative There is rarely a site that doesn’t suffer from some degree of jargon. Squash it early by setting a few guidelines about what language and tone of voice you will use to converse with your users. Be consistent. Equally, try to be as specific as possible when giving error messages or instructions and allay fears upfront. Card payments are handled by paypal but you do not need a paypal account to pay. We will not display your email address but we might need it to contact you. Sign up for our free trial (no credit card required). Combine copy and visual cues, learn from others and test new combinations While visual design and copy can work independently, they work best together. New phrases and designs are being tested all the time so take a peek at abtests.com for more ideas, then test some new ideas and add your own results. Have a look at the microcopy pool on Flickr for some wonderful examples of little words and pictures working together. And yes, you absolutely should join the group and post more examples. A man walks into a bar. The bartender greets him in a friendly manner and asks him what he would like to drink. “Gin and Tonic, please.” “Yes sir, we have our house gin on offer but we also have a particularly good import here too.” “The import, please.” “How would you like it? With a slice of lemon? Over ice?” “Both” “That’s £3.80. We accept cash, cards or you could open a tab.” “Card please.” “Certainly sir. Move just over here so that you can’t be observed. Now, please enter your pin number.” “Thank you.” “And here is your drink. Do let me know if there is a problem with it. I shall just be here at the bar. Enjoy.” Cheers! 2009 Relly Annett-Baker rellyannettbaker 2009-12-08T00:00:00+00:00 https://24ways.org/2009/the-construction-of-instruction/ content
227 A Contentmas Epiphany The twelve days of Christmas fall between 25 December, Christmas Day, and 6 January, the Epiphany of the Kings. Traditionally, these have been holidays and a lot of us still take a good proportion of these days off. Equally, a lot of us have a got a personal site kicking around somewhere that we sigh over and think, “One day I’ll sort you out!” Why not take this downtime to give it a big ol’ refresh? I know, good idea, huh? HEY WAIT! WOAH! NO-ONE’S TOUCHING PHOTOSHOP OR DOING ANY CSS FANCYWORK UNTIL I’M DONE WITH YOU! Be honest, did you immediately think of a sketch or mockup you have tucked away? Or some clever little piece of code you want to fiddle with? Now ask yourself, why would you start designing the container if you haven’t worked out what you need to put inside? Anyway, forget the content strategy lecture; I haven’t given you your gifts yet. I present The Twelve Days of Contentmas! This is a simple little plan to make sure that your personal site, blog or portfolio is not just looking good at the end of these twelve days, but is also a really useful repository of really useful content. WARNING KLAXON: There are twelve parts, one for each day of Christmas, so this is a lengthy article. I’m not expecting anyone to absorb this in one go. Add to Instapaper. There is no TL;DR for this because it’s a multipart process, m’kay? Even so, this plan of mine cuts corners on a proper applied strategy for content. You might find some aspects take longer than the arbitrary day I’ve assigned. And if you apply this to your company-wide intranet, I won’t be held responsible for the mess. That said, I encourage you to play along and sample some of the practical aspects of organising existing content and planning new content because it is, honestly, an inspiring and liberating process. For one thing, you get to review all the stuff you have put out for the world to look at and see what you could do next. This always leaves me full of ideas on how to plug the gaps I’ve found, so I hope you are similarly motivated come day twelve. Let’s get to it then, shall we? On the first day of Contentmas, Relly gave to me: 1. A (partial) content inventory I’m afraid being a site owner isn’t without its chores. With great power comes great responsibility and all that. There are the domain renewing, hosting helpline calls and, of course, keeping on top of all the content that you have published. If you just frowned a little and thought, “Well, there’s articles and images and… stuff”, then I’d like to introduce you to the idea of a content inventory. A content inventory is a list of all your content, in a simple spreadsheet, that allows you to see at a glance what is currently on your site: articles; about me page; contact form, and so on. You add the full URL so that you can click directly to any page listed. You add a brief description of what it is and what tags it has. In fact, I’ll show you. I’ve made a Google Docs template for you. Sorry, it isn’t wrapped. Does it seem like a mammoth task? Don’t feel you have to do this all in one day. But do do it. For one thing, looking back at all the stuff you’ve pushed out into the world gives you a warm fuzzy feeling which keeps the heating bill down. Grab a glass of mulled cider and try going month-by-month through your blog archives, or project-by-project through your portfolio. Do a little bit each day for the next twelve days and you’ll have done something awesome. The best bit is that this exploration of your current content helps you with the next day’s task. Bonus gift: for more on content auditing and inventory, check out Jeff Veen’s article on just this topic, which is also suitable for bigger business sites too. On the second day of Contentmas, Relly gave to me: 2. Website loves Remember when you were a kid, you’d write to Santa with a wish list that would make your parents squirm, because your biggest hope for your stocking would be either impossible or impossibly expensive. Do you ever get the same thing now as a grown-up where you think, “Wouldn’t it be great if I could make a video blog every week”, or “I could podcast once a month about this”, and then you push it to the back of your mind, assuming that you won’t have time or you wouldn’t know what to talk about anyway? True fact: content doesn’t just have to be produced when we are so incensed that we absolutely must blog about a topic. Neither does it have to be a drain to a demanding schedule. You can plan for it. In fact, you’re about to. So, today, get a pen and a notebook. Move away from your computer. My gift to you is to grab a quiet ten minutes between turkey sandwiches and relatives visiting and give your site some of the attention it deserves for 2011. What would you do with your site if you could? I don’t mean what would you do purely visually – although by all means note those things down too – but to your site as a whole. Here are some jumping off points: Would you like to individually illustrate and design some of your articles? What about a monthly exploration of your favourite topic through video or audio? Who would you like to collaborate with? What do you want your site to be like for a user? What tone of voice would you like to use? How could you use imagery and typography to support your content? What would you like to create content about in the new year? It’s okay if you can’t do these things yet. It’s okay to scrub out anything where you think, “Nah, never gonna happen.” But do give some thought to what you might want to do next. The best inspiration for this comes from what you’ve already done, so keep on with that inventory. Bonus gift: a Think Vitamin article on podcasting using Skype, so you can rope in a few friends to join in, too. On the third day of Contentmas, Relly gave to me: 3. Red pens Shock news, just in: the web is not print! One of the hardest things as a writer is to reach the point where you say, “Yeah, okay, that’s it. I’m done” and send off your beloved manuscript or article to print. I’m convinced that if deadlines didn’t exist, nothing would get finished. Why? Well, at the point you hand it over to the publishing presses, you can make no more changes. At best, you can print an erratum or produce an updated second edition at a later date. And writers love to – no, they live to – tweak their creations, so handing them over is quite a struggle. Just one more comma and… Online, we have no such constraints. We can edit, correct, test, tweak, twiddle until we’re blooming sick of it. Our red pens never run out of ink. It is time for you to run a more critical eye over your content, especially the stuff already published. Relish in the opportunity to change stuff on the fly. I am not so concerned by blog articles and such (although feel free to apply this concept to those, too), but mainly by your more concrete content: about pages; contact pages; home page navigation; portfolio pages; 404 pages. Now, don’t go running amok with the cut function yet. First, put all these evergreen pages into your inventory. In the notes section, write a quick analysis of how useful this copy is. Example questions: Is your contact page up-to-date? Does your about page link to the right places? Is your portfolio current? Does your 404 page give people a way to find what they were looking for? We’ll come back to this in a few days once we have a clearer idea of how to improve our content. Bonus gift: the audio and slides of a talk I gave on microcopy and 404 pages at @media WebDirections last year. On the fourth day of Contentmas, Relly gave to me: 4. Stalling nerds Actually, I guess more accurately this is something I get given a lot. Designers and developers particularly can find a million ways to extract themselves from the content of a site but, as the site owner, and this being your personal playground and all, you mustn’t. You actually can’t, sorry. But I do understand that at this point, ‘sorting out your site’ suddenly seems a lot less exciting, especially if you are a visually-minded person and words and lists aren’t really your thing. So far, there has been a lot of not-very-exciting exercises in planning, and there’s probably a nice pile of DVDs and video games that you got from Santa worth investigating. Stay strong my friend. By now, you have probably hit upon an idea of some sort you are itching to start on, so for every half-hour you spend doing inventory, gift yourself another thirty minutes to play with that idea. Bonus gift: the Pomodoro Technique. Take one kitchen timer and a to-do list and see how far you can go. On the fifth day of Contentmas, Relly gave to me: 5. Golden rules Here are some guidelines for writing online: Make headlines for tutorials and similar content useful and descriptive; use a subheading for any terrible pun you want to work in. Create a broad opening paragraph that addresses what your article is about. Part of the creative skill in writing is to do this in a way that both informs the reader and captures their attention. If you struggle with this, consider a boxout giving a summary of the article. Use headings to break up chunks of text and allow people to scan. Most people will have a scoot about an article before starting at the beginning to give it a proper read. These headings should be equal parts informative and enticing. Try them out as questions that might be posed by the reader too. Finish articles by asking your reader to take an affirmative action: subscribe to your RSS feed; leave a comment (if comments are your thing – more on that later); follow you on Twitter; link you to somewhere they have used your tutorial or code. The web is about getting excited, making things and sharing with others, so give your readers the chance to do that. For portfolio sites, this call to action is extra important as you want to pick up new business. Encourage people to e-mail you or call you – don’t just rely on a number in the footer or an e-mail link at the top. Think up some consistent calls-to-action you can use and test them out. So, my gift to you today is a simplified page table for planning out your content to make it as useful as possible. Feel free to write a new article or tutorial, or work on that great idea from yesterday and try out these guidelines for yourself. It’s a simple framework – good headline; broad opening; headings to break up volume; strong call to action – but it will help you recognise if what you’ve written is in good shape to face the world. It doesn’t tell you anything about how to create it – that’s your endeavour – but it does give you a start. No more staring at a blank page. Bonus gift: okay, you have to buy yourself this one, but it is the gift that keeps on giving: Ginny Reddish’s Letting Go of the Words – the hands down best guide to web writing there is, with a ton of illustrative examples. On the sixth day of Contentmas, Relly gave to me: 6. Foundation-a-laying Yesterday, we played with a page table for articles. Today, we are going to set the foundations for your new, spangly, spruced up, relaunched site (for when you’re ready, of course). We’ve checked out what we’ve got, we’ve thought about what we’d like, we have a wish list for the future. Now is the time for a small reality check. Be realistic with yourself. Can you really give your site some attention every day? Record a short snippet of audio once a week? A photo diary post once a month? Look back at the wish list you made. What can you do? What can you aim for? What just isn’t possible right now? As much as we’d all love to be producing a slick video podcast and screencast three times a week, it’s better to set realistic expectations and work your way up. Where does your site sit in your online world? Do you want it to be the hub of all your social interactions, a lifestream, a considered place of publication or a free for all? Do you want to have comments (do you have the personal resource to monitor comments?) or would you prefer conversation to happen via Twitter, Facebook or not at all? Does this apply to all pages, posts and content types or just some? Get these things straight in your head and it’s easier to know what sort of environment you want to create and what content you’ll need to sustain it. Get your notebook again and think about specific topics you’d like to cover, or aspects of a project you want to go into more, and how you can go ahead and do just that. A good motivator is to think what you’ll get out of doing it, even if that is “And I’ll finally show the poxy $whatever_community that my $chosen_format is better than their $other_format.” What topics have you really wanted to get off your chest? Look through your inventory again. What gaps are there in your content just begging to be filled? Today, you’re going to give everyone the gift of your opinion. Find one of those things where someone on the internet is wrong and create a short but snappy piece to set them straight. Doesn’t that feel good? Soon you’ll be able to do this in a timely manner every time someone is wrong on the internet! Bonus gift: we’re halfway through, so I think something fun is in order. How about a man sledding naked down a hill in Brighton on a tea tray? Sometimes, even with a whole ton of content planning, it’s the spontaneous stuff that is still the most fun to share. On the seventh day of Contentmas, Relly gave to me: 7. Styles-a-guiding Not colour style guides or brand style guides or code style guides. Content style guides. You could go completely to town and write yourself a full document defining every aspect of your site’s voice and personality, plus declaring your view on contracted phrases and the Oxford comma, but this does seem a tad excessive. Unless you’re writing an entire site as a fictional character, you probably know your own voice and vocabulary better than anyone. It’s in your head, after all. Instead, equip yourself with a good global style guide (I like the Chicago Manual of Style because I can access it fully online, but the Associated Press (AP) Stylebook has a nifty iPhone app and, if I’m entirely honest, I’ve found a copy of Eats, Shoots and Leaves has set me right on all but the most technical aspects of punctuation). Next, pick a good dictionary and bookmark thesaurus.com. Then have a go at Kristina Halvorson’s ‘Voice and Tone’ exercise from her book Content Strategy for the Web, to nail down what you’d like your future content to be like: To introduce the voice and tone qualities you’re [looking to create], a good approach is to offer contrasting values. For example: Professional, not academic. Confident, not arrogant. Clever, not cutesy. Savvy, not hipster. Expert, not preachy. Take a look around some of your favourite sites and examine the writing and stylistic handling of content. What do you like? What do you want to emulate? What matches your values list? Today’s gift to you is an idea. Create a ‘swipe file’ through Evernote or Delicious and save all the stuff you come across that, regardless of topic, makes you think, “That’s really cool.” This isn’t the same as an Instapaper list you’d like to read. This is stuff you have read or have seen that is worth looking at in closer detail. Why is it so good? What is the language and style like? What impact does the typography have? How does the imagery work to enhance the message? This isn’t about creating a personal brand or any such piffle. It’s about learning to recognise how good content works and how to create something awesome yourself. Obviously, your ideas are brilliant, so take the time to understand how best to spring them on the unsuspecting public for easier world domination. Bonus gift: a nifty style guide is a must when you do have to share content creation duties with others. Here is Leeds University’s publicly available PDF version for you to take a gander at. I especially like the Rationale sections for chopping off dissenters at the knees. On the eighth day of Contentmas, Relly gave to me: 8. Times-a-making You have an actual, real plan for what you’d like to do with your site and how it is going to sound (and probably some ideas on how it’s going to look, too). I hope you are full of enthusiasm and Getting Excited To Make Things. Just before we get going and do exactly that, we are going to make sure we have made time for this creative outpouring. Have you tried to blog once a week before and found yourself losing traction after a month or two? Are there a couple of podcasts lurking neglected in your archives? Whereas half of the act of running is showing up for training, half of creating is making time rather than waiting for it to become urgent. It’s okay to write something and set a date to come back to it (which isn’t the same as leaving it to decompose in your drafts folder). Putting a date in your calendar to do something for your site means that you have a forewarning to think of a topic to write about, and space in your schedule to actually do it. Crucially, you’ve actually made some time for this content lark. To do this, you need to think about how long it takes to get something out of the door/shipped/published/whatever you want to call it. It might take you just thirty minutes to record a podcast, but also a further hour to research the topic beforehand and another hour to edit and upload the clips. Suddenly, doing a thirty minute podcast every day seems a bit unlikely. But, on the flipside, it is easy to see how you could schedule that in three chunks weekly. Put it in your calendar. Do it, publish it, book yourself in for the next week. Keep turning up. Today my gift to you is the gift of time. Set up your own small content calendar, using your favourite calendar system, and schedule time to play with new ways of creating content, time to get it finished and time to get it on your site. Don’t let good stuff go to your drafts folder to die of neglect. Bonus gift: lots of writers swear by the concept of ‘daily pages’. That is, churning out whatever is in your head to see if there is anything worth building upon, or just to lose the grocery list getting in the way. 750words.com is a site built around this concept. Go have a play. On the ninth day of Contentmas, Relly gave to me: 9. Copy enhancing An incredibly radical idea for day number nine. We are going to look at that list of permanent pages you made back on day three and rewrite the words first, before even looking at a colour palette or picking a font! Crazy as it sounds, doing it this way round could influence your design. It could shape the imagery you use. It could affect your choice of typography. IMAGINE THE POSSIBILITIES! Look at the page table from day five. Print out one for each of your homepage, about page, contact page, portfolio, archive, 404 page or whatever else you have. Use these as a place to brainstorm your ideas and what you’d like each page to do for your site. Doodle in the margin, choose words you think sound fun to say, daydream about pictures you’d like to use and colours you think would work, but absolutely, completely and utterly fill in those page tables to understand how much (or how little) content you’re playing with and what you need to do to get to ‘launch’. Then, use them for guidance as you start to write. Don’t skimp. Don’t think that a fancy icon of an envelope encourages people to e-mail you. Use your words. People get antsy at this bit. Writing can be hard work and it’s easy for me to say, “Go on and write it then!” I know this. I mean, you should see the faces I pull when I have to do anything related to coding. The closest equivalent would be when scientists have to stick their hands in big gloves attached to a glass box to do dangerous experiments. Here’s today’s gift, a little something about writing that I hope brings you comfort: To write something fantastic you almost always have to write a rubbish draft first. Now, you might get lucky and write a ‘good enough’ draft first time and that’s fab – you’ve cut some time getting to ‘fantastic’. If, however, you’ve always looked at your first attempt to write more than the bare minimum and sighed in despair, and resigned yourself to adding just a title, date and a screenshot, be cheered because you have taken the first step to being able to communicate with clarity, wit and panache. Keep going. Look at writing you admire and emulate it. Think about how you will lovingly design those words when they are done. Know that you can go back and change them. Check back with your page table to keep you on track. Do that first draft. Bonus gift: becoming a better writer helps you to explain design concepts to clients. On the tenth day of Contentmas, Relly gave to me: 10. Ideas for keeping Hurrah! You have something down on paper, ready to start evolving your site around it. Here’s where the words and visuals and interaction start to come together. Because you have a plan, you can think ahead and do things you wouldn’t be able to pull together otherwise. How about finding a fresh-faced stellar illustrator on Dribbble to create you something perfect to pep up your contact page or visualize your witty statement on statements of work. A List Apart has been doing it for years and it hasn’t worked out too badly for them, has it? What about spending this month creating a series of introductory tutorials on a topic, complete with screencasts and audio and give them a special home on your site? How about putting in some hours creating a glorious about me page, with a biography, nice picture, and where you spend your time online? You could even do the web equivalent of getting up in the attic and sorting out your site’s search to make it easier to find things in your archives. Maybe even do some manual recommendations for relevant content and add them as calls to action. How about writing a few awesome case studies with individual screenshots of your favourite work, and creating a portfolio that plays to your strengths? Don’t just rely on the pretty pictures; use your words. Otherwise no-one understands why things are the way they are on that screenshot and BAM! you’ll be judged on someone else’s tastes. (Elliot has a head start on you for this, so get to it!) Do you have a serious archive of content? What’s it like being a first-time visitor to your site? Could you write them a guide to introduce yourself and some of the most popular stuff on your site? Ali Edwards is a massively popular crafter and every day she gets new visitors who have found her multiple papercraft projects on Flickr, Vimeo and elsewhere, so she created a welcome guide just for them. What about your microcopy? Can you improve on your blogging platform’s defaults for search, comment submission and labels? I’ll bet you can. Maybe you could plan a collaboration with other like-minded souls. A week of posts about the more advanced wonders of HTML5 video. A month-long baton-passing exercise in extolling the virtues of IE (shut up, it could happen!). Just spare me any more online advent calendars. Watch David McCandless’s TED talk on his jawdropping infographic work and make something as awesome as the Billion Dollar O Gram. I dare you. Bonus gift: Grab a copy of Brian Suda’s Designing with Data, in print or PDF if Santa didn’t put one in your stocking, and make that awesome something with some expert guidance. On the eleventh day of Contentmas, Relly gave to me: 11. Pixels pushing Oh, go on then. Make a gorgeous bespoke velvet-lined container for all that lovely content. It’s proper informed design now, not just decoration. Mr. Zeldman says so. Bonus gift: I made you a movie! If books were designed like websites. On the twelfth day of Contentmas, Relly gave to me: 12. Delighters delighting The Epiphany is upon us; your site is now well on its way to being a beautiful, sustainable hub of content and you have a date in your calendar to help you keep that resolution of blogging more. What now? Keep on top of your inventory. One day it will save your butt, I promise. Keep making a little bit of time regularly to create something new: an article; an opinion piece; a small curation of related links; a photo diary; a new case study. That’s easier than an annual content bootcamp for sure. And today’s gift: look for ways to play with that content and make something a bit special. Stretch yourself a little. It’ll be worth it. Bonus gift: Paul Annett’s presentation on Ooh, that’s clever: Delighters in design from SxSW 09. All my favourite designers and developers have their own unique styles and touches. It’s what sets them apart. My very, very favourites have an eloquence and expression that they bring to their sites and to their projects. I absolutely love to explore a well-crafted, well-written site – don’t we all? I know the time it takes. I appreciate the time it takes. But the end results are delicious. Do please share your spangly, refreshed sites with me in the comments. Catch me on Twitter, I’m @RellyAB, and I’ve been your host for these Twelve Days of Contentmas. 2010 Relly Annett-Baker rellyannettbaker 2010-12-21T00:00:00+00:00 https://24ways.org/2010/a-contentmas-epiphany/ content
287 Extracting the Content As we throw away our canvas in approaches and yearn for a content-out process, there remains a pain point: the Content. It is spoken of in the hushed tones usually reserved for Lord Voldemort. The-thing-that-someone-else-is-responsible-for-that-must-not-be-named. Designers and developers have been burned before by not knowing what the Content is, how long it is, what style it is and when the hell it’s actually going to be delivered, in internet eons past. Warily, they ask clients for it. But clients don’t know what to make, or what is good, because no one taught them this in business school. Designers struggle to describe what they need and when, so the conversation gets put off until it’s almost too late, and then everyone is relieved that they can take the cop-out of putting up a blog and maybe some product descriptions from the brochure. The Content in content out. I’m guessing, as a smart, sophisticated, and, may I say, nicely-scented reader of the honourable and venerable tradition of 24 ways, that you sense something better is out there. Bunches of boxes to fill in just don’t cut it any more in a responsive web design world. The first question is, how are you going to design something to ensure users have the easiest access to the best Content, if you haven’t defined at the beginning what that Content is? Of course, it’s more than possible that your clients have done lots of user research before approaching you to start this project, and have a plethora of finely tuned Content for you to design with. Have you finished laughing yet? Alright then. Let’s just assume that, for whatever reason of gross oversight, this hasn’t happened. What next? Bringing up Content for the first time with a client is like discussing contraception when you’re in a new relationship. It might be awkward and either party would probably rather be doing something else, but it needs to be broached before any action happens (that, and it’s disastrous to assume the other party has the matter in hand). If we can’t talk about it, how can we expect people to be doing it right and not making stupid mistakes? That being the case, how do we talk about Content? Let’s start by finding a way to talk about it without blushing and scuffing our shoes. And there’s a reason I’ve been treating Content as a Proper Noun. The first step, and I mean really-first-step-way-back-at-the-beginning-of-the-project-while-you-are-still-scoping-out-what-the-hell-you-might-do-for-each-other-and-it’s-still-all-a-bit-awkward-like-a-first-date, is for you to explain to the client how important it is that you, together, work out what is important to your users as part of the user experience design, so that your users get the best user experience. The trouble is that, in most cases, this would lead to blank stares, possibly followed by a light cough and a query about using Comic Sans because it seems friendly. Let’s start by ensuring your clients understand the task ahead. You see, all the time we talk about the Content we do our clients a big disservice. Content is poorly defined. It looms over a project completion point like an unscalable (in the sense of a dozen stacked Kilimanjaros), seething, massive, singular entity. The Content. Defining the problem. We should really be thinking of the Content as ‘contents’; as many parts that come together to form a mighty experience, like hit 90s kids’ TV show Mighty Morphin Power Rangers*. *For those of you who might have missed the Power Rangers, they were five teenagers with attitude, each given crazy mad individual skillz and a coloured lycra suit from an alien overlord. In return, they had to fight a new monster of the week using their abilities and weaponry in sync (even if the audio was not) and then, finally, in thrilling combination as a Humongous Mechanoid Machine of Awesome. They literally joined their individual selves, accessories and vehicles into a big robot. It was a toy manufacturer’s wet dream. So, why do I say Content is like the Power Rangers? Because Content is not just a humongous mecha. It is a combination of well-crafted pieces of contents that come together to form a well-crafted humongous mecha. Of Content. The Red Power Ranger was always the leader. You can imagine your text contents, found on about pages, product descriptions, blog articles, and so on, as being your Red Power Ranger. Maybe your pictures are your Yellow Power Ranger; video is Blue (not used as much as the others, but really impressive when given a good storyline); maybe Pink is your infographics (it’s wrong to find it sexier than the other equally important Rangers, but you kind of do anyway). And so on. These bits of content – Red Text Ranger, Yellow Picture Ranger and others – often join together on a page, like they are teaming up to fight the bad guy in an action scene, and when they all come together (your standard workaday huge mecha) in a launched site, that’s when Content becomes an entity. While you might have a vision for the whole site, Content rarely works that way. Of course, you keep your eye on the bigger prize, the completion of your mega robot, but to get there you need to assemble your working parts, the cogs and springs of contents that will mesh together to finally create your Humongous Mecha of Content. You create parts and join them to form a whole. (It’s rarely seamless; often we need to adjust as we go, but we can create our Mecha’s blueprint by making sure we have all the requisite parts.) The point here is the order these parts were created. No alien overlord plans a Humongous Mechanoid and then thinks, “Gee, how can I split this into smaller fighting units powered by teenagers in snazzy shiny suits?” No toy manufacturer goes into production of a mega robot, made up of model mecha vehicles with detachable arsenal, without thinking how they will easily fit back together to form the ‘Buy all five now to create the mega robot’ set. No good contents are created as a singular entity and chunked up to be slotted in to place any which way, into the body of a site. Think contents, not the Content. Think of contents as smaller units, or as a plural. The Content is what you have at the end. The contents are what you are creating and they are easy to break down. You are no longer scaling the unscalable. You can draw the map and plot the path, page by page, section by section. The page table is your friend To do this, I use a page table. A page table is a simple table template you can create in the word processor of your choice, that you use to tell you everything about the contents of a page – everything except the contents itself. Here’s a page table I created for an employee’s guide to redundancy in the alpha.gov.uk website: Guide to redundancy for employees Page objective: Provide specific information for employees who are facing redundancy about the process, their options and next steps. Source content: directgov page on Redundancy. Scope: In scope Page title An employee’s guide to redundancy Priority content Message: You have rights as an employee facing redundancy Method: A guide written in plain English, with links to appropriate additional content. A video guide (out of scope). Covers the stages of redundancy and rights for those in trade unions and not in trade unions. Glossary of unfamiliar terms. Call to action: Read full guide, act to explore redundancy actions, benefits or new employment. Assets: link to redundancy calculator. Secondary Related items, or popular additional links. Additional tools, such as search and suggestions. location set v not set states microcopy encouraging location set where location may make a difference to the content – ie, Scotland/Northern Ireland. Tertiary Footer and standard links. Content creation: Content exists but was created within the constraints of the previous CMS. Review, correct and edit where necessary. Maintenance: should be flagged for review upon advice from Department of Work and Pensions, and annually. Technology/Publishing/Policy implications: Should be reviewed once the glossary styles have been decided. No video guide in scope at this time, so languages should be simple and screen reader friendly. Reliance on third parties: None, all content and source exists in house. Outstanding questions: None. Download a copy of this page table This particular page table template owes a lot to Brain Traffic’s version found in Kristina Halvorson’s book Content Strategy for the Web. With smaller clients than, say, the government, I might use something a bit more casual. With clients who like timescales and deadlines, I might turn it into a covering sheet, with signatures and agreements from two departments who have to work together to get the piece done on time. I use page tables, and the process of working through them, to reassure clients that I understand the task they face and that I can help them break it down section by section, page stack to page, down to product descriptions and interaction copy. About 80% of my clients break into relieved smiles. Most clients want to work with you to produce something good, they just don’t understand how, and they want you to show them the mountain path on the map. With page tables, clients can understand that with baby steps they can break down their content requirements and commission content they need in time for the designers to work with it (as opposed to around it). If I was Santa, these clients would be on my nice list for sure. My own special brand of Voldemort-content-evilness comes in how I wield my page tables for the other 20%. Page tables are not always thrilling, I’ll admit. Sometimes they get ignored in favour of other things, yet they are crucial to the continual growth and maintenance of a truly content-led site. For these naughty list clients who, even when given the gift of the page table, continually say “Ooh, yes. Content. Right”, I have a special gift. I have a stack of recycled paper under my desk and a cheap black and white laser printer. And I print a blank page table for every conceivable page I can find on the planned redesign. If I’m feeling extra nice, I hole punch them and put them in a fat binder. There is nothing like saying, “This is all the contents you need to have in hand for launch”, and the satisfying thud the binder makes as it hits the table top, to galvanize even the naughtiest clients to start working with you to create the content you need to really create in a content-out way. 2011 Relly Annett-Baker rellyannettbaker 2011-12-15T00:00:00+00:00 https://24ways.org/2011/extracting-the-content/ content
50 Make a Comic For something slightly different over Christmas, why not step away from your computer and make a comic? Definitely not the author working on a comic in the studio, with the desk displaying some of the things you need to make a comic on paper. Why make a comic? First of all, it’s truly fun and it’s not that difficult. If you’re a designer, you can use skills you already have, so why not take some time to indulge your aesthetic whims and make something for yourself, rather than for a client or your company. And you can use a computer – or not. If you’re an interaction designer, it’s likely you’ve already made a storyboard or flow, or designed some characters for personas. This is a wee jump away from that, to the realm of storytelling and navigating human emotions through characters who may or may not be human. Similar medium and skills, different content. It’s not a client deliverable but something that stands by itself, and you’ve nobody’s criteria to meet except those that exist in your imagination! Thanks to your brain and the alchemy of comics, you can put nearly anything in a sequence and your brain will find a way to make sense of it. Scott McCloud wrote about the non sequitur in comics: “There is a kind of alchemy at work in the space between panels which can help us find meaning or resonance in even the most jarring of combinations.” Here’s an example of a non sequitur from Scott McCloud’s Understanding Comics – the images bear no relation to one another, but since they’re in a sequence our brains do their best to understand it: Once you know this it takes the pressure off somewhat. It’s a fun thing to keep in mind and experiment with in your comics! Materials needed A4 copy/printing paper HB pencil for light drawing Dip pen and waterproof Indian ink Bristol board (or any good quality card with a smooth, durable surface) Step 1: Get ideas You’d be surprised where you can take a small grain of an idea and develop it into an interesting comic. Think about a funny conversation you had, or any irrational fears, habits, dreams or anything else. Just start writing and drawing. Having ideas is hard, I know, but you will get some ideas when you start working. One way to keep track of ideas is to keep a sketch diary, capturing funny conversations and other events you could use in comics later. You might want to just sketch out the whole comic very roughly if that helps. I tend to sketch the story first, but it usually changes drastically during step 2. Step 2: Edit your story using thumbnails How thumbnailing works. Why use thumbnails? You can move them around or get rid of them! Drawings are harder and much slower to edit than words, so you need to draw something very quick and very rough. You don’t have to care about drawing quality at this point. You might already have a drafted comic from the previous step; now you can split each panel up into a thumbnail like the image above. Get an A4 sheet of printing paper and tear it up into squares. A thumbnail equals a comic panel. Start drawing one panel per thumbnail. This way you can move scenes and parts of the story around as you work on the pacing. It’s an extremely useful tip if you want to expand a moment in time or draw out a dialogue, or if you want to just completely cut scenes. Step 3: Plan a layout So you’ve got the story more or less down: you now need to know how they’ll look on the page. Sketch a layout and arrange the thumbnails into the layout. The simplest way to do this is to divide an A4 page into equal panels — say, nine. But if you want, you can be more creative than that. The Gigantic Beard That Was Evil by Stephen Collins is an excellent example of the scope for using page layout creatively. You can really push the form: play with layout, scale, story and what you think of as a comic. Step 4: Draw the comic I recommend drawing on A4 Bristol board paper since it has a smooth surface, can tolerate a lot of rubbing out and holds ink well. You can get it from any art shop. Using your thumbnails for reference, draw the comic lightly using an HB pencil. Don’t make the line so heavy that it can’t be erased (since you’ll ink over the lines later). Step 5: Ink the comic Image before colour was added. You’ve drawn your story. Well done! Now for the fun part. I recommend using a dip pen and some waterproof ink. Why waterproof? If you want, you can add an ink wash later, or even paint it. If you don’t have a dip pen, you could also use any quality pen. Carefully go over your pencilled lines with the pen, working from top left to right and down, to avoid smudging it. It’s unfortunately easy to smudge the ink from the dip pen, so I recommend practising first. You’ve made a comic! Step 6: Adding colour Comics traditionally had a limited colour palette before computers (here’s an in-depth explanation if you’re curious). You can actually do a huge amount with a restricted colour palette. Ellice Weaver’s comics show how very nicely how you can paint your work using a restricted palette. So for the next step, resist the temptation to add ALL THE COLOURS and consider using a limited palette. Once the ink is completely dry, erase the pencilled lines and you’ll be left with a beautiful inked black and white drawing. You could use a computer for this part. You could also photocopy it and paint straight on the copy. If you’re feeling really brave, you could paint straight on the original. But I’d suggest not doing this if it’s your first try at painting! What follows is an extremely basic guide for painting using Photoshop, but there are hundreds of brilliant articles out there and different techniques for digital painting. How to paint your comic using Photoshop Scan the drawing and open it in Photoshop. You can adjust the levels (Image → Adjustments → Levels) to make the lines darker and crisper, and the paper invisible. At this stage, you can erase any smudges or mistakes. With a Wacom tablet, you could even completely redraw parts! Computers are just amazing. Keep the line art as its own layer. Add a new layer on top of the lines, and set the layer state from normal to multiply. This means you can paint your comic without obscuring your lines. Rename the layer something else, so you can keep track. Start blocking in colour. And once you’re happy with that, experiment with adding tone and texture. Christmas comic challenge! Why not challenge yourself to make a short comic over Christmas? If you make one, share it in the comments. Or show me on Twitter — I’d love to see it. Credit: Many of these techniques were learned on the Royal Drawing School’s brilliant ‘Drawing the Graphic Novel’ course. 2015 Rebecca Cottrell rebeccacottrell 2015-12-20T00:00:00+00:00 https://24ways.org/2015/make-a-comic/ design
78 Fluent Design through Early Prototyping There’s a small problem with wireframes. They’re not good for showing the kind of interactions we now take for granted – transitions and animations on the web, in Android, iOS, and other platforms. There’s a belief that early prototyping requires a large amount of time and effort, and isn’t worth an early investment. But it’s not true! It’s still normal to spend a significant proportion of time working in wireframes. Given that wireframes are high-level and don’t show much detail, it’s tempting to give up control and responsibility for things like transitions and other things sidelined as visual considerations. These things aren’t expressed well, and perhaps not expressed at all, in wireframes, yet they critically influence the quality of a product. Rapid prototyping early helps to bring sidelined but significant design considerations into focus. Speaking fluent design Fluency in a language means being able to speak it confidently and accurately. The Latin root means flow. By design fluency, I mean using a set of skills in order to express or communicate an idea. Prototyping is a kind of fluency. It takes designers beyond the domain of grey and white boxes to consider all the elements that make up really good product design. Designers shouldn’t be afraid of speaking fluent design. They should think thoroughly about product decisions beyond their immediate role — not for the sake of becoming some kind of power-hungry design demigod, but because it will lead to better, more carefully considered product design. Wireframes are incomplete sentences Wireframes, once they’ve served their purpose, are a kind of self-imposed restriction. Mostly made out of grey and white boxes, they deliberately express the minimum. Important details — visuals, nuanced transitions, sounds — are missing. Their appearance bears little resemblance to the final thing. Responsibility for things that traditionally didn’t matter (or exist) is relinquished. Animations and transitions in particular are increasingly relevant to the mobile designer’s methods. And rather than being fanciful and superfluous visual additions to a product, they help to clarify designs and provide information about context. Wireframes are useful in the early stages. As a designer trying to persuade stakeholders, clients, or peers, sometimes it will be in your interests to only tell half the story. They’re ideal for gauging whether a design is taking the right direction, and they’re the right medium for deciding core things, such as the overall structure and information architecture. But spending a long time in wireframes means delaying details to a later stage in the project, or to the end, when the priority is shifted to getting designs out of the door. This leaves little time to test, finesse and perfect things which initially seemed to be less important. I think designers should move away from using wireframes as primary documentation once the design has reached a certain level of maturity. A prototype is multiple complete sentences Paragraphs, even. Unlike a wireframe, a prototype is a persuasive storyteller. It can reveal the depth and range of design decisions, not just the layout, but also motion: animations and transitions. If it’s a super-high-fidelity prototype, it’s a perfect vessel for showing the visual design as well. It’s all of these things that contribute to the impression that a product is good… and useful, and engaging, and something you’d like to use. A prototype is impressive. A good prototype can help to convince stakeholders and persuade clients. With a compelling demo, people can more easily imagine that this thing could actually exist. “Hey”, they’re thinking. “This might actually be pretty good!” How to make a prototype in no time and with no effort Now, it does take time and effort to make a prototype. However, good news! It used to require a lot more effort. There are tools that make prototyping much quicker and easier. If you’re making a mobile prototype (this seems quite likely), you will want to test and show this on the actual device. This sounds like it could be a pain, but there are a few ways to do this that are quite easy. Keynote, Apple’s presentation software, is an unlikely candidate for a prototyping tool, but surprisingly great and easy for creating prototypes with transitions that can be shown on different devices. Keynote enables you to do a few useful, excellent things. You can make each screen in your design a slide, which can be linked together to allow you to click through the prototype. You can add customisable transitions between screens. If you want to show a panel that can slide open or closed on your iPad mockup, for example, transitions can also be added to individual elements on the screen. The design can be shown on tablet and mobile devices, and interacted with like it’s a real app. Another cool feature is that you can export the prototype as a video, which works as another effective format for demoing a design. Overall, Keynote offers a very quick, lightweight way to prototype a design. Once you’ve learned the basics, it shouldn’t take longer than a few hours – at most – to put together a respectable clickable prototype with transitions. Download the interactive MOV example Holly icon by Megan Sheehan from The Noun Project This is a Quicktime movie exported from Keynote. This version is animated for demonstration purposes, but download the interactive original and you can click the screen to move through the prototype. It demonstrates the basic interactivity of an iPhone app. This anonymised example was used on a project at Fjord to create a master example of an app’s transitions. Prototyping drawbacks, and perceived drawbacks If prototyping is so great, then why do we leave it to the end, or not bother with it at all? There are multiple misconceptions about prototyping: they’re too difficult to make; they take too much time; or they’re inaccurate (and dangerous) documentation. A prototype is a preliminary model. There should always be a disclaimer that it’s not the real thing to avoid setting up false expectations. A prototype doesn’t have to be the main deliverable. It can be a key one that’s supported by visual and interaction specifications. And a prototype is a lightweight means of managing and reflecting changes and requirements in a project. An actual drawback of prototyping is that to make one too early could mean being gung-ho with what you thought a client or stakeholder wanted, and delivering something inappropriate. To avoid this, communicate, iterate, and keep things simple until you’re confident that the client or other stakeholders are happy with your chosen direction. The key throughout any design project is iteration. Designers build iterative models, starting simple and becoming increasingly sophisticated. It’s a process of iterative craft and evolution. There’s no perfect methodology, no magic recipe to follow. What to do next Make a prototype! It’s the perfect way to impress your friends. It can help to advance a brilliant idea with a fraction of the effort of complete development. Sketches and wireframes are perfect early on in a project, but once they’ve served their purpose, prototypes enable the design to advance, and push thinking towards clarifying other important details including transitions. For Keynote tutorials, Keynotopia is a great resource. Axure is standard and popular prototyping software many UX designers will already be familiar with; it’s possible to create transitions in Axure. POP is an iPhone app that allows you to design apps on paper, take photos with your phone, and turn them into interactive prototypes. Ratchet is an elegant iPhone prototyping tool aimed at web developers. There are perhaps hundreds of different prototyping tools and methods. My final advice is not to get bogged down in (or limited by) any particular tool, but to remember you’re making quick and iterative models. Experiment and play! Prototyping will push you and your designs to a scary place without limitations. No more grey and white boxes, just possibilities! 2012 Rebecca Cottrell rebeccacottrell 2012-12-10T00:00:00+00:00 https://24ways.org/2012/fluent-design-through-early-prototyping/ ux
33 Five Ways to Animate Responsibly It’s been two years since I wrote about “Flashless Animation” on this very site. Since then, animation has steadily begun popping up on websites, from sleek app-like user interfaces to interactive magazine-like spreads. It’s an exciting time for web animation wonks, interaction developers, UXers, UI designers and a host of other acronyms! But in our rush to experiment with animation it seems that we’re having fewer conversations about whether or not we should use it, and more discussions about what we can do with it. We spend more time fretting over how to animate all the things at 60fps than we do devising ways to avoid incapacitating users with vestibular disorders. I love web animation. I live it. And I make adorably silly things with it that have no place on a self-respecting production website. I know it can be abused. We’ve all made fun of Flash-turbation. But how quickly we forget the lessons we learned from that period of web design. Parallax scrolling effects may be the skip intro of this generation. Surely we have learned better in the sobering up period between Flash and the web animation API. So here are five bits of advice we can use to pull back from the edge of animation abuse. With these thoughts in mind, we can make 2015 the year web animation came into its own. Animate deliberately Sadly, animation is considered decorative by the bulk of the web development community. UI designers and interaction developers know better, of course. But when I’m teaching a workshop on animation for interaction, I know that my students face an uphill battle against decision makers who consider it nice to have, and tack it on at the end of a project, if at all. This stigma is hard to shake. But it starts with us using animation deliberately or not at all. Poorly considered, tacked-on animation will often cause more harm than good. Users may complain that it’s too slow or too fast, or that they have no idea what just happened. When I was at Chrome Dev Summit this year, I had the privilege to speak with Roma Sha, the UX lead behind Polymer’s material design (with the wonderful animation documentation). I asked her what advice she’d give to people using animation and transitions in their own designs. She responded simply: animate deliberately. If you cannot afford to slow down to think about animation and make well-informed and well-articulated decisions on behalf of the user, it is better that you not attempt it at all. Animation takes energy to perform, and a bad animation is worse than none at all. It takes more than twelve principles We always try to draw correlations between disparate things that spark our interest. Recently it feels like more and more people are putting the The Illusion of Life on their reading shelf next to Understanding Comics. These books give us so many useful insights from other industries. However, we should never mistake a website for a comic book or an animated feature film. Some of these concepts, while they help us see our work in a new light, can be more or less relevant to producing said work. The illusion of life from cento lodigiani on Vimeo. I am specifically thinking of the twelve principles of animation put forth by Disney studio veterans in that great tome The Illusion of Life. These principles are very useful for making engaging, lifelike animation, like a ball bouncing or a squirrel scampering, or the physics behind how a lightbox should feel transitioning off a page. But they provide no direction at all for when or how something should be animated as part of a greater interactive experience, like how long a drop-down should take to fully extend or if a group of manipulable objects should be animated sequentially or as a whole. The twelve principles are a great place to start, but we have so much more to learn. I’ve documented at least six more functions of interactive animation that apply to web and app design. When thinking about animation, we should consider why and how, not just what, the physics. Beautiful physics mean nothing if the animation is superfluous or confusing. Useful and necessary, then beautiful There is a Shaker saying: “Don’t make something unless it is both necessary and useful; but if it is both necessary and useful, don’t hesitate to make it beautiful.” When it comes to animation and the web, currently there is very little documentation about what makes it useful or necessary. We tend to focus more on the beautiful, the delightful, the aesthetic. And while aesthetics are important, they take a back seat to the user’s overall experience. The first time I saw the load screen for Pokemon Yellow on my Game Boy, I was enthralled. By the sixth time, I was mashing the start button as soon as Game Freak’s logo hit the screen. What’s delightful and meaningful to us while working on a project is not always so for our users. And even when a purely delightful animation is favorably received, as with Pokemon Yellow’s adorable opening screen, too many repetitions of the cutest but ultimately useless animation, and users start to resent it as a hindrance. If an animation doesn’t help the user in some way, by showing them where they are or how two elements on a page relate to each other, then it’s using up battery juice and processing cycles solely for the purpose of delight. Hardly the best use of resources. Rather than animating solely for the sake of delight, we should first be able to articulate two things the animation does for the user. As an example, take this menu icon from Finethought.com (found via Use Your Interface). The menu icon does two things when clicked: It gives the user feedback by animating, letting the user know its been clicked. It demonstrates its changed relationship to the page’s content by morphing into a close button. Assuming we have two good reasons to animate something, there is no reason our third cannot be to delight the user. Go four times faster There is a rule of thumb in the world of traditional animation which is applicable to web animation: however long you think your animation should last, take that time and halve it. Then halve it again! When we work on an animation for hours, our sense of time dilates. What seems fast to us is actually unbearably slow for most users. In fact, the most recent criticism from users of animated interfaces on websites seems to be, “It’s so slow!” A good animation is unobtrusive, and that often means running fast. When getting your animations ready for prime time, reduce those durations to 25% of their original speed: a four-second fade out should be over in one. Install a kill switch No matter how thoughtful and necessary an animation, there will be people who become physically sick from seeing it. For these people, we must add a way to turn off animations on the website. Fortunately, web designers are already thinking of ways to empower users to make their own decisions about how they experience the web. As an example, this site for the animated film Little from the Fish Shop allows users to turn off most of the parallax effects. While it doesn’t remove the animation entirely, this website does reduce the most nauseating of the animations. Animation is a powerful tool in our web design arsenal. But we must take care: if we abuse animation it might get a bad reputation; if we underestimate it, it won’t be prioritized. But if we wield it thoughtfully, use it where it is both necessary and useful, and empower users to turn it off, animation is a tool that will help us build things that are easier to use and more delightful for years to come. Let’s make 2015 the year web animation went to work for users. 2014 Rachel Nabors rachelnabors 2014-12-14T00:00:00+00:00 https://24ways.org/2014/five-ways-to-animate-responsibly/ ux
86 Flashless Animation Animation in a Flashless world When I splashed down in web design four years ago, the first thing I wanted to do was animate a cartoon in the browser. I’d been drawing comics for years, and I’ve wanted to see them come to life for nearly as long. Flash animation was still riding high, but I didn’t want to learn Flash. I wanted to learn JavaScript! Sadly, animating with JavaScript was limiting and resource-intensive. My initial foray into an infinitely looping background did more to burn a hole in my CPU than amaze my friends (although it still looks pretty cool). And there was still no simple way to incorporate audio. The browser technology just wasn’t there. Things are different now. CSS3 transitions and animations can do most of the heavy lifting and HTML5 audio can serve up the music and audio clips. You can do a lot without leaning on JavaScript at all, and when you lean on JavaScript, you can do so much more! In this project, I’m going to show you how to animate a simple walk cycle with looping audio. I hope this will inspire you to do something really cool and impress your friends. I’d love to see what you come up with, so please send your creations my way at rachelnabors.com! Note: Because every browser wants to use its own prefixes with CSS3 animations, and I have neither the time nor the space to write all of them out, I will use the W3C standard syntaxes; that is, going prefix-less. You can implement them out of the box with something like Prefixfree, or you can add prefixes on your own. If you take the latter route, I recommend using Sass and Compass so you can focus on your animations, not copying and pasting. The walk cycle Walk cycles are the “Hello world” of animation. One of the first projects of animation students is to spend hours drawing dozens of frames to complete a simple loopable animation of a character walking. Most animators don’t have to draw every frame themselves, though. They draw a few key frames and send those on to production animators to work on the between frames (or tween frames). This is meticulous, grueling work requiring an eye for detail and natural movement. This is also why so much production animation gets shipped overseas where labor is cheaper. Luckily, we don’t have to worry about our frame count because we can set our own frames-per-second rate on the fly in CSS3. Since we’re trying to impress friends, not animation directors, the inconsistency shouldn’t be a problem. (Unless your friend is an animation director.) This is a simple walk cycle I made of my comic character Tuna for my CSS animation talk at CSS Dev Conference this year: The magic lies here: animation: walk-cycle 1s steps(12) infinite; Breaking those properties down: animation: <name> <duration> <timing-function> <iteration-count>; walk-cycle is a simple @keyframes block that moves the background sprite on .tuna around: @keyframes walk-cycle { 0% {background-position: 0 0; } 100% {background-position: 0 -2391px;} } The background sprite has exactly twelve images of Tuna that complete a full walk cycle. We’re setting it to cycle through the entire sprite every second, infinitely. So why isn’t the background image scrolling down the .tuna container? It’s all down to the timing function steps(). Using steps() let us tell the CSS to make jumps instead of the smooth transitions you’d get from something like linear. Chris Mills at dev.opera wrote in his excellent intro to CSS3 animation : Instead of giving a smooth animation throughout, [steps()] causes the animation to jump between a set number of steps placed equally along the duration. For example, steps(10) would make the animation jump along in ten equal steps. There’s also an optional second parameter that takes a value of start or end. steps(10, start) would specify that the change in property value should happen at the start of each step, while steps(10, end) means the change would come at the end. (Seriously, go read his full article. I’m not going to touch on half the stuff he does because I cannot improve on the basics any more than he already has.) The background A cat walking in a void is hardly an impressive animation and certainly your buddy one cube over could do it if he chopped up some of those cat GIFs he keeps using in group chat. So let’s add a parallax background! Yes, yes, all web designers signed a peace treaty to not abuse parallax anymore, but this is its true calling—treaty be damned. And to think we used to need JavaScript to do this! It’s still pretty CPU intensive but much less complicated. We start by splitting up the page into different layers, .foreground, .midground, and .background. We put .tuna in the .midground. .background has multiple background images, all set to repeat horizontally: background-image: url(background_mountain5.png), url(background_mountain4.png), url(background_mountain3.png), url(background_mountain2.png), url(background_mountain1.png); background-repeat: repeat-x; With parallax, things in the foreground move faster than those in the background. Next time you’re driving, notice how the things closer to you move out of your field of vision faster than something in the distance, like a mountain or a large building. We can imitate that here by making the background images on top (in the foreground, closer to us) wider than those on the bottom of the stack (in the distance). The different lengths let us use one animation to move all the background images at different rates in the same interval of time: animation: parallax_bg linear 40s infinite; The shorter images have less distance to cover in the same amount of time as the longer images, so they move slower. Let’s have a look at the background’s animation: @keyframes parallax_bg { 0% { background-position: -2400px 100%, -2000px 100%, -1800px 100%, -1600px 100%, -1200px 100%; } 100% { background-position: 0 100%, 0 100%, 0 100%, 0 100%, 0 100%; } } At 0%, all the background images are positioned at the negative value of their own widths. Then they start moving toward background-position: 0 100%. If we wanted to move them in the reverse direction, we’d remove the negative values at 0% (so they would start at 2400px 100%, 2000px 100%, etc.). Try changing the values in the codepen above or changing background-repeat to none to see how the images play together. .foreground and .midground operate on the same principles, only they use single background images. The music After finishing the first draft of my original walk cycle, I made a GIF with it and posted it on YTMND with some music from the movie Paprika, specifically the track “The Girl in Byakkoya.” After showing it to some colleagues in my community, it became clear that this was a winning combination sure to drive away dresscode blues. So let’s use HTML5 to get a clip of that music looping in there! Warning, there is sound. Please adjust your volume or apply headphones as needed. We’re using HTML5 audio’s loop and autoplay abilities to automatically play and loop a sound file on page load: <audio loop autoplay> <source src="http://music.com/clip.mp3" /> </audio> Unfortunately, you may notice there is a small pause between loops. HTML5 audio, thou art half-baked still. Let’s hope one day the Web Audio API will be able to help us out, but until things improve, we’ll have to hack our way around these shortcomings. Turns out there’s a handy little script called seamlessLoop.js which we can use to patch this. Mind you, if we were really getting crazy with the Cheese Whiz, we’d want to get out big guns like sound.js. But that’d be overkill for a mere loop (and explaining the Web Audio API might bore, rather than impress your friends)! Installing seamlessLoop.js will get rid of the pause, and now our walk cycle is complete. (I’ve done some very rough sniffing to see if the browser can play MP3 files. If not, we fall back to using .ogg formatted clips (Opera and Firefox users, you’re welcome).) Really impress your friends by adding a run cycle So we have music, we have a walk cycle, we have parallax. It will be a snap to bring them all together and have a simple, endless animation. But let’s go one step further and knock the socks off our viewers by adding a run cycle. The run cycle Tacking a run cycle on to our walk cycle will require a third animation sequence: a transitional animation of Tuna switching from walking to running. I have added all these to the sprite: Let’s work on getting that transition down. We’re going to use multiple animations on the same .tuna div, but we’re going to kick them off at different intervals using animation-delay—no JavaScript required! Isn’t that magical? It requires a wee bit of math (not much, it doesn’t hurt) to line them up. We want to: Loop the walk animation twice Play the transitional cycle once (it has a finite beginning and end perfectly drawn to pick up between the last frame of the walk cycle and the first frame of the run cycle—no looping this baby) RUN FOREVER. Using the pattern animation: <name> <duration> <timing-function> <delay> <iteration-count>, here’s what that looks like: animation: walk-cycle 1s steps(12) 2, walk-to-run .75s steps(12) 2s 1, run-cycle .75s steps(13) 2.75s infinite; I played with the times to get make the movement more realistic. You may notice that the running animation looks smoother than the walking animation. That’s because it has 13 keyframes running over .75 second instead of 12 running in one second. Remember, professional animation studios use super-high frame counts. This little animation isn’t even up to PBS’s standards! The music: extended play with HTML5 audio sprites My favorite part in the The Girl in Byakkoya is when the calm opening builds and transitions into a bouncy motif. I want to start with Tuna walking during the opening, and then loop the running and bounciness together for infinity. The intro lasts for 24 seconds, so we set our 1 second walk cycle to run for 24 repetitions: walk-cycle 1s steps(12) 24 We delay walk-to-run by 24 seconds so it runs for .75 seconds before… We play run-cycle at 24.75 seconds and loop it infinitely For the music, we need to think of it as two parts: the intro and the bouncy loop. We can do this quite nicely with audio sprites: using one HTML5 audio element and using JavaScript to change the play head location, like skipping tracks with a CD player. Although this technique will result in a small gap in music shifts, I think it’s worth using here to give you some ideas. // Get the audio element var byakkoya = document.querySelector('audio'); // create function to play and loop audio function song(a){ //start playing at 0 a.currentTime = 0; a.play(); //when we hit 64 seconds... setTimeout(function(){ // skip back to 24.5 seconds and keep playing... a.currentTime = 24.55; // then loop back when we hit 64 again, or every 59.5 seconds. setInterval(function(){ a.currentTime = 24.55; },39450); },64000); } The load screen I’ve put it off as long as I can, but now that the music and the CSS are both running on their own separate clocks, it’s imperative that both images and music be fully downloaded and ready to run when we kick this thing off. So we need a load screen (also, it’s nice to give people a heads-up that you’re about to blast them with music, no matter how wonderful that music may be). Since the two timers are so closely linked, we’d best not run the animations until we run the music: * { animation-play-state: paused; } animation-play-state can be set to paused or running, and it’s the most useful thing you will learn today. First we use an event listener to see when the browser thinks we can play through from the beginning to end of the music without pause for buffering: byakkoya.addEventListener("canplaythrough", function () { }); (More on HTML5 audio’s media events at HTML5doctor.com) Inside our event listener, I use a bit of jQuery to add class of .playable to the body when we’re ready to enable the play button: $("body").addClass("playable"); $("#play-me").html("Play me.").click(function(){ song(byakkoya); $("body").addClass("playing"); }); That .playing class is special because it turns on the animations at the same time we start playing the song: .playing * { animation-play-state: running; } The background We’re almost done here! When we add the background, it needs to speed up at the same time that Tuna starts running. The music picks up speed around 24.75 seconds in, and so we’re going to use animation-delay on those backgrounds, too. This will require some math. If you try to simply shorten the animation’s duration at the 24.75s mark, the backgrounds will, mid-scroll, jump back to their initial background positions to start the new animation! Argh! So let’s make a new @keyframe and calculate where the background position would be just before we speed up the animation. Here’s the formula: new 0% value = delay ÷ old duration × length of image new 100% value = new 0% value + length of image Here’s the formula put to work on a smaller scale: Voilà! The finished animation! I’ve always wanted to bring my illustrations to life. Then I woke up one morning and realized that I had all the tools to do so in my browser and in my head. Now I have fallen in love with Flashless animation. I’m sure there will be detractors who say HTML wasn’t meant for this and it’s a gross abuse of the DOM! But I say that these explorations help us expand what we expect from devices and software and challenge us in good ways as artists and programmers. The browser might not be the most appropriate place for animation, but is certainly a fun place to start. There is so much you can do with the spec implemented today, and so much of the territory is still unexplored. I have not yet begun to show you everything. In eight months I expect this demo will represent the norm, not the bleeding edge. I look forward to seeing the wonderful things you create. (Also, someone, please, do something about that gappy HTML5 audio looping. It’s a crying shame!) 2012 Rachel Nabors rachelnabors 2012-12-06T00:00:00+00:00 https://24ways.org/2012/flashless-animation/ code
47 Developing Robust Deployment Procedures Once you have developed your site, how do you make it live on your web hosting? For many years the answer was to log on to your server and upload the files via FTP. Over time most hosts and FTP clients began to support SFTP, ensuring your files were transmitted over a secure connection. The process of deploying a site however remained the same. There are issues with deploying a site in this way. You are essentially transferring files one by one to the server without any real management of that transfer. If the transfer fails for some reason, you may end up with a site that is only half updated. It can then be really difficult to work out what hasn’t been replaced or added, especially where you are updating an existing site. If you are updating some third-party software your update may include files that should be removed, but that may not be obvious to you and you risk leaving outdated files littering your file system. Updating using (S)FTP is a fragile process that leaves you open to problems caused by both connectivity and human error. Is there a better way to do this? You’ll be glad to know that there is. A modern professional deployment workflow should have you moving away from fragile manual file transfers to deployments linked to code committed into source control. The benefits of good practice You may never have experienced any major issues while uploading files over FTP, and good FTP clients can help. However, there are other benefits to moving to modern deployment practices. No surprises when you launch If you are deploying in the way I suggest in this article you should have no surprises when you launch because the code you committed from your local environment should be the same code you deploy – and to staging if you have a staging server. A missing vital file won’t cause things to start throwing errors on updating the live site. Being able to work collaboratively Source control and good deployment practice makes working with your clients and other developers easy. Deploying first to a staging server means you can show your client updates and then push them live. If you subcontract some part of the work, you can give your subcontractor the ability to deploy to staging, leaving you with the final push to launch, once you know you are happy with the work. Having a proper backup of site files with access to them from anywhere The process I will outline requires the use of hosted, external source control. This gives you a backup of your latest commit and the ability to clone those files and start working on them from any machine, wherever you are. Being able to jump back into a site quickly when the client wants a few changes When doing client work it is common for some work to be handed over, then several months might go by without you needing to update the site. If you don’t have a good process in place, just getting back to work on it may take several hours for what could be only a few hours of work in itself. A solid method for getting your local copy up to date and deploying your changes live can cut that set-up time down to a few minutes. The tool chain In the rest of this article I assume that your current practice is to deploy your files over (S)FTP, using an FTP client. You would like to move to a more robust method of deployment, but without blowing apart your workflow and spending all Christmas trying to put it back together again. Therefore I’m selecting the most straightforward tools to get you from A to B. Source control Perhaps you already use some kind of source control for your sites. Today that is likely to be Git but you might also use Subversion or Mercurial. If you are not using any source control at all then I would suggest you choose Git, and that is what I will be working with in this article. When you work with Git, you always have a local repository. This is where your changes are committed. You also have the option to push those changes to a remote repository; for example, GitHub. You may well have come across GitHub as somewhere you can go to download open source code. However, you can also set up private repositories for sites whose code you don’t want to make publicly accessible. A hosted Git repository gives you somewhere to push your commits to and deploy from, so it’s a crucial part of our tool chain. A deployment service Once you have your files pushed to a remote repository, you then need a way to deploy them to your staging environment and live server. This is the job of a deployment service. This service will connect securely to your hosting, and either automatically (or on the click of a button) transfer files from your Git commit to the hosting server. If files need removing, the service should also do this too, so you can be absolutely sure that your various environments are the same. Tools to choose from What follows are not exhaustive lists, but any of these should allow you to deploy your sites without FTP. Hosted Git repositories GitHub Beanstalk Bitbucket Standalone deployment tools Deploy dploy.io FTPloy I’ve listed Beanstalk as a hosted Git repository, though it also includes a bundled deployment tool. Dploy.io is a standalone version of that tool just for deployment. In this tutorial I have chosen two separate services to show how everything fits together, and because you may already be using source control. If you are setting up all of this for the first time then using Beanstalk saves having two accounts – and I can personally recommend them. Putting it all together The steps we are going to work through are: Getting your local site into a local Git repository Pushing the files to a hosted repository Connecting a deployment tool to your web hosting Setting up a deployment Get your local site into a local Git repository Download and install Git for your operating system. Open up a Terminal window and tell Git your name using the following command (use the name you will set up on your hosted repository). > git config --global user.name "YOUR NAME" Use the next command to give Git your email address. This should be the address that you will use to sign up for your remote repository. > git config --global user.email "YOUR EMAIL ADDRESS" Staying in the command line, change to the directory where you keep your site files. If your files are in /Users/rachel/Sites/mynicewebite you would type: > cd /Users/rachel/Sites/mynicewebsite The next command tells Git that we want to create a new Git repository here. > git init We then add our files: > git add . Then commit the files: > git commit -m “Adding initial files” The bit in quotes after -m is a message describing what you are doing with this commit. It’s important to add something useful here to remind yourself later why you made the changes included in the commit. Your local files are now in a Git repository! However, everything should be just the same as before in terms of working on the files or viewing them in a local web server. The only difference is that you can add and commit changes to this local repository. Want to know more about Git? There are some excellent resources in a range of formats here. Setting up a hosted Git repository I’m going to use Atlassian Bitbucket for my first example as they offer a free hosted and private repository. Create an account on Bitbucket. Then create a new empty repository and give it a name that will identify the repository easily. Click Getting Started and under Command Line select “I have an existing project”. This will give you a set of instructions to run on the command line. The first instruction is just to change into your working directory as we did before. We then add a remote repository, and run two commands to push everything up to Bitbucket. cd /path/to/my/repo git remote add origin https://myuser@bitbucket.org/myname/24ways-tutorial.git git push -u origin --all git push -u origin --tags When you run the push command you will be asked for the password that you set for Bitbucket. Having entered that, you should be able to view the files of your site on Bitbucket by selecting the navigation option Source in the sidebar. You will also be able to see commits. When we initially committed our files locally we added the message “Adding initial files”. If you select Commits from the sidebar you’ll see we have one commit, with the message we set locally. You can imagine how useful this becomes when you can look back and see why you made certain changes to a project that perhaps you haven’t worked on for six months. Before working on your site locally you should run: > git pull in your working directory to make sure you have all of the most up-to-date files. This is especially important if someone else might work on them, or you just use multiple machines. You then make your changes and add any changed or modified files, for example: > git add index.php Commit the change locally: > git commit -m “updated the homepage” Then push it to Bitbucket: > git push origin master If you want to work on your files on a different computer you clone them using the following command: > git clone https://myuser@bitbucket.org/myname/24ways-tutorial.git You then have a copy of your files that is already a Git repository with the Bitbucket repository set up as a remote, so you are all ready to start work. Connecting a deployment tool to your repository and web hosting The next step is deploying files. I have chosen to use a deployment tool called Deploy as it has support for Bitbucket. It does have a monthly charge – but offers a free account for open source projects. Sign up for your account then log in and create your first project. Select Create an empty project. Under Configure Repository Details choose Bitbucket and enter your username and password. If Deploy can connect, it will show you your list of projects. Select the one you want. The next screen is Add New Server and here you need to configure the server that you want to deploy to. You might set up more than one server per project. In an ideal world you would deploy to a staging server for your client preview changes and then deploy once everything is signed off. For now I’ll assume you just want to set up your live site. Give the server a name; I usually use Production for the live web server. Then choose the protocol to connect with. Unless your host really does not support SFTP (which is pretty rare) I would choose that instead of FTP. You now add the same details your host gave you to log in with your SFTP client, including the username and password. The Path on server should be where your files are on the server. When you log in with an SFTP client and you get put in the directory above public_html then you should just be able to add public_html here. Once your server is configured you can deploy. Click Deploy now and choose the server you just set up. Then choose the last commit (which will probably be selected for you) and click Preview deployment. You will then get a preview of which files will change if you run the deployment: the files that will be added and any that will be removed. At the very top of that screen you should see the commit message you entered right back when you initially committed your files locally. If all looks good, run the deployment. You have taken the first steps to a more consistent and robust way of deploying your websites. It might seem like quite a few steps at first, but you will very soon come to realise how much easier deploying a live site is through this process. Your new procedure step by step Edit your files locally as before, testing them through a web server on your own computer. Commit your changes to your local Git repository. Push changes to the remote repository. Log into the deployment service. Hit the Deploy now button. Preview the changes. Run the deployment and then check your live site. Taking it further I have tried to keep things simple in this article because so often, once you start to improve processes, it is easy to get bogged down in all the possible complexities. If you move from deploying with an FTP client to working in the way I have outlined above, you’ve taken a great step forward in creating more robust processes. You can continue to improve your procedures from this point. Staging servers for client preview When we added our server we could have added an additional server to use as a staging server for clients to preview their site on. This is a great use of a cheap VPS server, for example. You can set each client up with a subdomain – clientname.yourcompany.com – and this becomes the place where they can view changes before you deploy them. In that case you might deploy to the staging server, let the client check it out and then go back and deploy the same commit to the live server. Using Git branches As you become more familiar with using Git, and especially if you start working with other people, you might need to start developing using branches. You can then have a staging branch that deploys to staging and a production branch that is always a snapshot of what has been pushed to production. This guide from Beanstalk explains how this works. Automatic deployment to staging I wouldn’t suggest doing automatic deployment to the live site. It’s worth having someone on hand hitting the button and checking that everything worked nicely. If you have configured a staging server, however, you can set it up to deploy the changes each time a commit is pushed to it. If you use Bitbucket and Deploy you would create a deployment hook on Bitbucket to post to a URL on Deploy when a push happens to deploy the code. This can save you a few steps when you are just testing out changes. Even if you have made lots of changes to the staging deployment, the commit that you push live will include them all, so you can do that manually once you are happy with how things look in staging. Further Reading The tutorials from Git Client Tower, already mentioned in this article, are a great place to start if you are new to Git. A presentation from Liam Dempsey showing how to use the GitHub App to connect to Bitbucket Try Git from Code School The Git Workbook a self study guide to Git from Lorna Mitchell Get set up for the new year I love to start the New Year with a clean slate and improved processes. If you are still wrangling files with FTP then this is one thing you could tick off your list to save you time and energy in 2015. Post to the comments if you have suggestions of tools or ideas for ways to enhance this type of set-up for those who have already taken the first steps. 2014 Rachel Andrew rachelandrew 2014-12-04T00:00:00+00:00 https://24ways.org/2014/developing-robust-deployment-procedures/ process
68 Grid, Flexbox, Box Alignment: Our New System for Layout Three years ago for 24 ways 2012, I wrote an article about a new CSS layout method I was excited about. A specification had emerged, developed by people from the Internet Explorer team, bringing us a proper grid system for the web. In 2015, that Internet Explorer implementation is still the only public implementation of CSS grid layout. However, in 2016 we should be seeing it in a new improved form ready for our use in browsers. Grid layout has developed hidden behind a flag in Blink, and in nightly builds of WebKit and, latterly, Firefox. By being developed in this way, breaking changes could be safely made to the specification as no one was relying on the experimental implementations in production work. Another new layout method has emerged over the past few years in a more public and perhaps more painful way. Shipped prefixed in browsers, The flexible box layout module (flexbox) was far too tempting for developers not to use on production sites. Therefore, as changes were made to the specification, we found ourselves with three different flexboxes, and browser implementations that did not match one another in completeness or in the version of specified features they supported. Owing to the different ways these modules have come into being, when I present on grid layout it is often the very first time someone has heard of the specification. A question I keep being asked is whether CSS grid layout and flexbox are competing layout systems, as though it might be possible to back the loser in a CSS layout competition. The reality, however, is that these two methods will sit together as one system for doing layout on the web, each method playing to certain strengths and serving particular layout tasks. If there is to be a loser in the battle of the layouts, my hope is that it will be the layout frameworks that tie our design to our markup. They have been a necessary placeholder while we waited for a true web layout system, but I believe that in a few years time we’ll be easily able to date a website to circa 2015 by seeing <div class="row"> or <div class="col-md-3"> in the markup. In this article, I’m going to take a look at the common features of our new layout systems, along with a couple of examples which serve to highlight the differences between them. To see the grid layout examples you will need to enable grid in your browser. The easiest thing to do is to enable the experimental web platform features flag in Chrome. Details of current browser support can be found here. Relationship Items only become flex or grid items if they are a direct child of the element that has display:flex, display:grid or display:inline-grid applied. Those direct children then understand themselves in the context of the complete layout. This makes many things possible. It’s the lack of relationship between elements that makes our existing layout methods difficult to use. If we float two columns, left and right, we have no way to tell the shorter column to extend to the height of the taller one. We have expended a lot of effort trying to figure out the best way to make full-height columns work, using techniques that were never really designed for page layout. At a very simple level, the relationship between elements means that we can easily achieve full-height columns. In flexbox: See the Pen Flexbox equal height columns by rachelandrew (@rachelandrew) on CodePen. And in grid layout (requires a CSS grid-supporting browser): See the Pen Grid equal height columns by rachelandrew (@rachelandrew) on CodePen. Alignment Full-height columns rely on our flex and grid items understanding themselves as part of an overall layout. They also draw on a third new specification: the box alignment module. If vertical centring is a gift you’d like to have under your tree this Christmas, then this is the box you’ll want to unwrap first. The box alignment module takes the alignment and space distribution properties from flexbox and applies them to other layout methods. That includes grid layout, but also other layout methods. Once implemented in browsers, this specification will give us true vertical centring of all the things. Our examples above achieved full-height columns because the default value of align-items is stretch. The value ensured our columns stretched to the height of the tallest. If we want to use our new vertical centring abilities on all items, we would set align-items:center on the container. To align one flex or grid item, apply the align-self property. The examples below demonstrate these alignment properties in both grid layout and flexbox. The portrait image of Widget the cat is aligned with the default stretch. The other three images are aligned using different values of align-self. Take a look at an example in flexbox: See the Pen Flexbox alignment by rachelandrew (@rachelandrew) on CodePen. And also in grid layout (requires a CSS grid-supporting browser): See the Pen Grid alignment by rachelandrew (@rachelandrew) on CodePen. The alignment properties used with CSS grid layout. Fluid grids A cornerstone of responsive design is the concept of fluid grids. “[…]every aspect of the grid—and the elements laid upon it—can be expressed as a proportion relative to its container.” —Ethan Marcotte, “Fluid Grids” The method outlined by Marcotte is to divide the target width by the context, then use that value as a percentage value for the width property on our element. h1 { margin-left: 14.575%; /* 144px / 988px = 0.14575 */ width: 70.85%; /* 700px / 988px = 0.7085 */ } In more recent years, we’ve been able to use calc() to simplify this (at least, for those of us able to drop support for Internet Explorer 8). However, flexbox and grid layout make fluid grids simple. The most basic of flexbox demos shows this fluidity in action. The justify-content property – another property defined in the box alignment module – can be used to create an equal amount of space between or around items. As the available width increases, more space is assigned in proportion. In this demo, the list items are flex items due to display:flex being added to the ul. I have given them a maximum width of 250 pixels. Any remaining space is distributed equally between the items as the justify-content property has a value of space-between. See the Pen Flexbox: justify-content by rachelandrew (@rachelandrew) on CodePen. For true fluid grid-like behaviour, your new flexible friends are flex-grow and flex-shrink. These properties give us the ability to assign space in proportion. The flexbox flex property is a shorthand for: flex-grow flex-shrink flex-basis The flex-basis property sets the default width for an item. If flex-grow is set to 0, then the item will not grow larger than the flex-basis value; if flex-shrink is 0, the item will not shrink smaller than the flex-basis value. flex: 1 1 200px: a flexible box that can grow and shrink from a 200px basis. flex: 0 0 200px: a box that will be 200px and cannot grow or shrink. flex: 1 0 200px: a box that can grow bigger than 200px, but not shrink smaller. In this example, I have a set of boxes that can all grow and shrink equally from a 100 pixel basis. See the Pen Flexbox: flex-grow by rachelandrew (@rachelandrew) on CodePen. What I would like to happen is for the first element, containing a portrait image, to take up less width than the landscape images, thus keeping it more in proportion. I can do this by changing the flex-grow value. By giving all the items a value of 1, they all gain an equal amount of the available space after the 100 pixel basis has been worked out. If I give them all a value of 3 and the first box a value of 1, the other boxes will be assigned three parts of the available space while box 1 is assigned only one part. You can see what happens in this demo: See the Pen Flexbox: flex-grow by rachelandrew (@rachelandrew) on CodePen. Once you understand flex-grow, you should easily be able to grasp how the new fraction unit (fr, defined in the CSS grid layout specification) works. Like flex-grow, this unit allows us to assign available space in proportion. In this case, we assign the space when defining our track sizes. In this demo (which requires a CSS grid-supporting browser), I create a four-column grid using the fraction unit to define my track sizes. The first track is 1fr in width, and the others 2fr. grid-template-columns: 1fr 2fr 2fr 2fr; See the Pen Grid fraction units by rachelandrew (@rachelandrew) on CodePen. The four-track grid. Separation of concerns My younger self petitioned my peers to stop using tables for layout and to move to CSS. One of the rallying cries of that movement was the concept of separating our source and content from how they were displayed. It was something of a failed promise given the tools we had available: the display leaked into the markup with the need for redundant elements to cope with browser bugs, or visual techniques that just could not be achieved without supporting markup. Browsers have improved, but even now we can find ourselves compromising the ideal document structure so we can get the layout we want at various breakpoints. In some ways, the situation has returned to tables-for-layout days. Many of the current grid frameworks rely on describing our layout directly in the markup. We add divs for rows, and classes to describe the number of desired columns. We nest these constructions of divs inside one another. Here is a snippet from the Bootstrap grid examples – two columns with two nested columns: <div class="row"> <div class="col-md-8"> .col-md-8 <div class="row"> <div class="col-md-6"> .col-md-6 </div> <div class="col-md-6"> .col-md-6 </div> </div> </div> <div class="col-md-4"> .col-md-4 </div> </div> Not a million miles away from something I might have written in 1999. <table> <tr> <td class="col-md-8"> .col-md-8 <table> <tr> <td class="col-md-6"> .col-md-6 </td> <td class="col-md-6"> .col-md-6 </td> </tr> </table> </td> <td class="col-md-4"> .col-md-4 </td> </tr> </table> Grid and flexbox layouts do not need to be described in markup. The layout description happens entirely in the CSS, meaning that elements can be moved around from within the presentation layer. Flexbox gives us the ability to reverse the flow of elements, but also to set the order of elements with the order property. This is demonstrated here, where Widget the cat is in position 1 in the source, but I have used the order property to display him after the things that are currently unimpressive to him. See the Pen Flexbox: order by rachelandrew (@rachelandrew) on CodePen. Grid layout takes this a step further. Where flexbox lets us set the order of items in a single dimension, grid layout gives us the ability to position things in two dimensions: both rows and columns. Defined in the CSS, this positioning can be changed at any breakpoint without needing additional markup. Compare the source order with the display order in this example (requires a CSS grid-supporting browser): See the Pen Grid positioning in two dimensions by rachelandrew (@rachelandrew) on CodePen. Laying out our items in two dimensions using grid layout. As these demos show, a straightforward way to decide if you should use grid layout or flexbox is whether you want to position items in one dimension or two. If two, you want grid layout. A note on accessibility and reordering The issues arising from this powerful ability to change the way items are ordered visually from how they appear in the source have been the subject of much discussion. The current flexbox editor’s draft states “Authors must use order only for visual, not logical, reordering of content. Style sheets that use order to perform logical reordering are non-conforming.” —CSS Flexible Box Layout Module Level 1, Editor’s Draft (3 December 2015) This is to ensure that non-visual user agents (a screen reader, for example) can rely on the document source order as being correct. Take care when reordering that you do so from the basis of a sound document that makes sense in terms of source order. Avoid using visual order to convey meaning. Automatic content placement with rules Having control over the order of items, or placing items on a predefined grid, is nice. However, we can often do that already with one method or another and we have frameworks and tools to help us. Tools such as Susy mean we can even get away from stuffing our markup full of grid classes. However, our new layout methods give us some interesting new possibilities. Something that is useful to be able to do when dealing with content coming out of a CMS or being pulled from some other source, is to define a bunch of rules and then say, “Display this content, using these rules.” As an example of this, I will leave you with a Christmas poem displayed in a document alongside Widget the cat and some of the decorations that are bringing him no Christmas cheer whatsoever. The poem is displayed first in the source as a set of paragraphs. I’ve added a class identifying each of the four paragraphs but they are displayed in the source as one text. Below that are all my images, some landscape and some portrait; I’ve added a class of landscape to the landscape ones. The mobile-first grid is a single column and I use line-based placement to explicitly position my poem paragraphs. The grid layout auto-placement rules then take over and place the images into the empty cells left in the grid. At wider screen widths, I declare a four-track grid, and position my poem around the grid, keeping it in a readable order. I also add rules to my landscape class, stating that these items should span two tracks. Once again the grid layout auto-placement rules position the rest of my images without my needing to position them. You will see that grid layout takes items out of source order to fill gaps in the grid. It does this because I have set the property grid-auto-flow to dense. The default is sparse meaning that grid will not attempt this backfilling behaviour. Take a look and play around with the full demo (requires a CSS grid layout-supporting browser): See the Pen Grid auto-flow with rules by rachelandrew (@rachelandrew) on CodePen. The final automatic placement example. My wish for 2016 I really hope that in 2016, we will see CSS grid layout finally emerge from behind browser flags, so that we can start to use these features in production — that we can start to move away from using the wrong tools for the job. However, I also hope that we’ll see developers fully embracing these tools as the new system that they are. I want to see people exploring the possibilities they give us, rather than trying to get them to behave like the grid systems of 2015. As you discover these new modules, treat them as the new paradigm that they are, get creative with them. And, as you find the edges of possibility with them, take that feedback to the CSS Working Group. Help improve the layout systems that will shape the look of the future web. Some further reading I maintain a site of grid layout examples and resources at Grid by Example. The three CSS specifications I’ve discussed can be found as editor’s drafts: CSS grid, flexbox, box alignment. I wrote about the last three years of my interest in CSS grid layout, which gives something of a history of the specification. More examples of box alignment and grid layout. My presentation at Fronteers earlier this year, in which I explain more about these concepts. 2015 Rachel Andrew rachelandrew 2015-12-15T00:00:00+00:00 https://24ways.org/2015/grid-flexbox-box-alignment-our-new-system-for-layout/ code
95 Giving Content Priority with CSS3 Grid Layout Browser support for many of the modules that are part of CSS3 have enabled us to use CSS for many of the things we used to have to use images for. The rise of mobile browsers and the concept of responsive web design has given us a whole new way of looking at design for the web. However, when it comes to layout, we haven’t moved very far at all. We have talked for years about separating our content and source order from the presentation of that content, yet most of us have had to make decisions on source order in order to get a certain visual layout. Owing to some interesting specifications making their way through the W3C process at the moment, though, there is hope of change on the horizon. In this article I’m going to look at one CSS module, the CSS3 grid layout module, that enables us to define a grid and place elements on to it. This article comprises a practical demonstration of the basics of grid layout, and also a discussion of one way in which we can start thinking of content in a more adaptive way. Before we get started, it is important to note that, at the time of writing, these examples work only in Internet Explorer 10. CSS3 grid layout is a module created by Microsoft, and implemented using the -ms prefix in IE10. My examples will all use the -ms prefix, and not include other prefixes simply because this is such an early stage specification, and by the time there are implementations in other browsers there may be inconsistencies. The implementation I describe today may well change, but is also there for your feedback. If you don’t have access to IE10, then one way to view and test these examples is by signing up for an account with Browserstack – the free trial would give you time to have a look. I have also included screenshots of all relevant stages in creating the examples. What is CSS3 grid layout? CSS3 grid layout aims to let developers divide up a design into a grid and place content on to that grid. Rather than trying to fabricate a grid from floats, you can declare an actual grid on a container element and then use that to position the elements inside. Most importantly, the source order of those elements does not matter. Declaring a grid We declare a grid using a new value for the display property: display: grid. As we are using the IE10 implementation here, we need to prefix that value: display: -ms-grid;. Once we have declared our grid, we set up the columns and rows using the grid-columns and grid-rows properties. .wrapper { display: -ms-grid; -ms-grid-columns: 200px 20px auto 20px 200px; -ms-grid-rows: auto 1fr; } In the above example, I have declared a grid on the .wrapper element. I have used the grid-columns property to create a grid with a 200 pixel-wide column, a 20 pixel gutter, a flexible width auto column that will stretch to fill the available space, another 20 pixel-wide gutter and a final 200 pixel sidebar: a flexible width layout with two fixed width sidebars. Using the grid-rows property I have created two rows: the first is set to auto so it will stretch to fill whatever I put into it; the second row is set to 1fr, a new value used in grids that means one fraction unit. In this case, one fraction unit of the available space, effectively whatever space is left. Positioning items on the grid Now I have a simple grid, I can pop items on to it. If I have a <div> with a class of .main that I want to place into the second row, and the flexible column set to auto I would use the following CSS: .content { -ms-grid-column: 3; -ms-grid-row: 2; -ms-grid-row-span: 1; } If you are old-school, you may already have realised that we are essentially creating an HTML table-like layout structure using CSS. I found the concept of a table the most helpful way to think about the grid layout module when trying to work out how to place elements. Creating grid systems As soon as I started to play with CSS3 grid layout, I wanted to see if I could use it to replicate a flexible grid system like this fluid 16-column 960 grid system. I started out by defining a grid on my wrapper element, using fractions to make this grid fluid. .wrapper { width: 90%; margin: 0 auto 0 auto; display: -ms-grid; -ms-grid-columns: 1fr (4.25fr 1fr)[16]; -ms-grid-rows: (auto 20px)[24]; } Like the 960 grid system I was using as an example, my grid starts with a gutter, followed by the first actual column, plus another gutter repeated sixteen times. What this means is that if I want to span two columns, as far as the grid layout module is concerned that is actually three columns: two wide columns, plus one gutter. So this needs to be accounted for when positioning items. I created a CSS class for each positioning option: column position; rows position; and column span. For example: .grid1 {-ms-grid-column: 2;} /* applying this class positions an item in the first column (the gutter is column 1) */ .grid2 {-ms-grid-column: 4;} /* 2nd column - gutter|column 1|gutter */ .grid3 {-ms-grid-column: 6;} /* 3rd column - gutter|column 1|gutter|column2|gutter */ .row1 {-ms-grid-row:1;} .row2 {-ms-grid-row:3;} .row3 {-ms-grid-row:5;} .colspan1 {-ms-grid-column-span:1;} .colspan2 {-ms-grid-column-span:3;} .colspan3 {-ms-grid-column-span:5;} I could then add multiple classes to each element to set the position on on the grid. This then gives me a replica of the fluid grid using CSS3 grid layout. To see this working fire up IE10 and view Example 1. This works, but… This worked, but isn’t ideal. I considered not showing this stage of my experiment – however, I think it clearly shows how the grid layout module works and is a useful starting point. That said, it’s not an approach I would take in production. First, we have to add classes to our markup that tie an element to a position on the grid. This might not be too much of a problem if we are always going to maintain the sixteen-column grid, though, as I will show you that the real power of the grid layout module appears once you start to redefine the grid, using different grids based on media queries. If you drop to a six-column layout for small screens, positioning items into column 16 makes no sense any more. Calculating grid position using LESS As we’ve seen, if you want to use a grid with main columns and gutters, you have to take into account the spacing between columns as well as the actual columns. This means we have to do some calculating every time we place an item on the grid. In my example above I got around this by creating a CSS class for each position, allowing me to think in sixteen rather than thirty-two columns. But by using a CSS preprocessor, I can avoid using all the classes yet still think in main columns. I’m using LESS for my example. My simple grid framework consists of one simple mixin. .position(@column,@row,@colspan,@rowspan) { -ms-grid-column: @column*2; -ms-grid-row: @row*2-1; -ms-grid-column-span: @colspan*2-1; -ms-grid-row-span: @rowspan*2-1; } My mixin takes four parameters: column; row; colspan; and rowspan. So if I wanted to place an item on column four, row three, spanning two columns and one row, I would write the following CSS: .box { .position(4,3,2,1); } The mixin would return: .box { -ms-grid-column: 8; -ms-grid-row: 5; -ms-grid-column-span: 3; -ms-grid-row-span: 1; } This saves me some typing and some maths. I could also add other prefixed values into my mixin as other browsers started to add support. We can see this in action creating a new grid. Instead of adding multiple classes to each element, I can add one class; that class uses the mixin to create the position. I have also played around with row spans using my mixin and you can see we end up with a quite complicated arrangement of boxes. Have a look at example two in IE10. I’ve used the JavaScript LESS parser so that you can view the actual LESS that I use. Note that I have needed to escape the -ms prefixed properties with ~"" to get LESS to accept them. This is looking better. I don’t have direct positioning information on each element in the markup, just a class name – I’ve used grid(x), but it could be something far more semantic. We can now take the example a step further and redefine the grid based on screen width. Media queries and the grid This example uses exactly the same markup as the previous example. However, we are now using media queries to detect screen width and redefine the grid using a different number of columns depending on that width. I start out with a six-column grid, defining that on .wrapper, then setting where the different items sit on this grid: .wrapper { width: 90%; margin: 0 auto 0 auto; display: ~"-ms-grid"; /* escaped for the LESS parser */ -ms-grid-columns: ~"1fr (4.25fr 1fr)[6]"; /* escaped for the LESS parser */ -ms-grid-rows: ~"(auto 20px)[40]"; /* escaped for the LESS parser */ } .grid1 { .position(1,1,1,1); } .grid2 { .position(2,1,1,1); } /* ... see example for all declarations ... */ Using media queries, I redefine the grid to nine columns when we hit a minimum width of 700 pixels. @media only screen and (min-width: 700px) { .wrapper { -ms-grid-columns: ~"1fr (4.25fr 1fr)[9]"; -ms-grid-rows: ~"(auto 20px)[50]"; } .grid1 { .position(1,1,1,1); } .grid2 { .position(2,1,1,1); } /* ... */ } Finally, we redefine the grid for 960 pixels, back to the sixteen-column grid we started out with. @media only screen and (min-width: 940px) { .wrapper { -ms-grid-columns:~" 1fr (4.25fr 1fr)[16]"; -ms-grid-rows:~" (auto 20px)[24]"; } .grid1 { .position(1,1,1,1); } .grid2 { .position(2,1,1,1); } /* ... */ } If you view example three in Internet Explorer 10 you can see how the items reflow to fit the window size. You can also see, looking at the final set of blocks, that source order doesn’t matter. You can pick up a block from anywhere and place it in any position on the grid. Laying out a simple website So far, like a toddler on Christmas Day, we’ve been playing with boxes rather than thinking about what might be in them. So let’s take a quick look at a more realistic layout, in order to see why the CSS3 grid layout module can be really useful. At this time of year, I am very excited to get out of storage my collection of odd nativity sets, prompting my family to suggest I might want to open a museum. Should I ever do so, I’ll need a website, and here is an example layout. As I am using CSS3 grid layout, I can order my source in a logical manner. In this example my document is as follows, though these elements could be in any order I please: <div class="wrapper"> <div class="welcome"> ... </div> <article class="main"> ... </article> <div class="info"> ... </div> <div class="ads"> ... </div> </div> For wide viewports I can use grid layout to create a sidebar, with the important information about opening times on the top righ,t with the ads displayed below it. This creates the layout shown in the screenshot above. @media only screen and (min-width: 940px) { .wrapper { -ms-grid-columns:~" 1fr (4.25fr 1fr)[16]"; -ms-grid-rows:~" (auto 20px)[24]"; } .welcome { .position(1,1,12,1); padding: 0 5% 0 0; } .info { .position(13,1,4,1); border: 0; padding:0; } .main { .position(1,2,12,1); padding: 0 5% 0 0; } .ads { .position(13,2,4,1); display: block; margin-left: 0; } } In a floated layout, a sidebar like this often ends up being placed under the main content at smaller screen widths. For my situation this is less than ideal. I want the important information about opening times to end up above the main article, and to push the ads below it. With grid layout I can easily achieve this at the smallest width .info ends up in row two and .ads in row five with the article between. .wrapper { display: ~"-ms-grid"; -ms-grid-columns: ~"1fr (4.25fr 1fr)[4]"; -ms-grid-rows: ~"(auto 20px)[40]"; } .welcome { .position(1,1,4,1); } .info { .position(1,2,4,1); border: 4px solid #fff; padding: 10px; } .content { .position(1,3,4,5); } .main { .position(1,3,4,1); } .ads { .position(1,4,4,1); } Finally, as an extra tweak I add in a breakpoint at 600 pixels and nest a second grid on the ads area, arranging those three images into a row when they sit below the article at a screen width wider than the very narrow mobile width but still too narrow to support a sidebar. @media only screen and (min-width: 600px) { .ads { display: ~"-ms-grid"; -ms-grid-columns: ~"20px 1fr 20px 1fr 20px 1fr"; -ms-grid-rows: ~"1fr"; margin-left: -20px; } .ad:nth-child(1) { .position(1,1,1,1); } .ad:nth-child(2) { .position(2,1,1,1); } .ad:nth-child(3) { .position(3,1,1,1); } } View example four in Internet Explorer 10. This is a very simple example to show how we can use CSS grid layout without needing to add a lot of classes to our document. It also demonstrates how we can mainpulate the content depending on the context in which the user is viewing it. Layout, source order and the idea of content priority CSS3 grid layout isn’t the only module that starts to move us away from the issue of visual layout being linked to source order. However, with good support in Internet Explorer 10, it is a nice way to start looking at how this might work. If you look at the grid layout module as something to be used in conjunction with the flexible box layout module and the very interesting CSS regions and exclusions specifications, we have, tantalizingly on the horizon, a powerful set of tools for layout. I am particularly keen on the potential separation of source order from layout as it dovetails rather neatly into something I spend a lot of time thinking about. As a CMS developer, working on larger scale projects as well as our CMS product Perch, I am interested in how we better enable content editors to create content for the web. In particular, I search for better ways to help them create adaptive content; content that will work in a variety of contexts rather than being tied to one representation of that content. If the concept of adaptive content is new to you, then Karen McGrane’s presentation Adapting Ourselves to Adaptive Content is the place to start. Karen talks about needing to think of content as chunks, that might be used in many different places, displayed differently depending on context. I absolutely agree with Karen’s approach to content. We have always attempted to move content editors away from thinking about creating a page and previewing it on the desktop. However at some point content does need to be published as a page, or a collection of content if you prefer, and bits of that content have priority. Particularly in a small screen context, content gets linearized, we can only show so much at a time, and we need to make sure important content rises to the top. In the case of my example, I wanted to ensure that the address information was clearly visible without scrolling around too much. Dropping it with the entire sidebar to the bottom of the page would not have been so helpful, though neither would moving the whole sidebar to the top of the screen so a visitor had to scroll past advertising to get to the article. If our layout is linked to our source order, then enabling the content editor to make decisions about priority is really hard. Only a system that can do some regeneration of the source order on the server-side – perhaps by way of multiple templates – can allow those kinds of decisions to be made. For larger systems this might be a possibility; for smaller ones, or when using an off-the-shelf CMS, it is less likely to be. Fortunately, any system that allows some form of custom field type can be used to pop a class on to an element, and with CSS grid layout that is all that is needed to be able to target that element and drop it into the right place when the content is viewed, be that on a desktop or a mobile device. This approach can move us away from forcing editors to think visually. At the moment, I might have to explain to an editor that if a certain piece of content needs to come first when viewed on a mobile device, it needs to be placed in the sidebar area, tying it to a particular layout and design. I have to do this because we have to enforce fairly strict rules around source order to make the mechanics of the responsive design work. If I can instead advise an editor to flag important content as high priority in the CMS, then I can make decisions elsewhere as to how that is displayed, and we can maintain the visual hierarchy across all the different ways content might be rendered. Why frustrate ourselves with specifications we can’t yet use in production? The CSS3 grid layout specification is listed under the Exploring section of the list of current work of the CSS Working Group. While discussing a module at this stage might seem a bit pointless if we can’t use it in production work, there is a very real reason for doing so. If those of us who will ultimately be developing sites with these tools find out about them early enough, then we can start to give our feedback to the people responsible for the specification. There is information on the same page about how to get involved with the disussions. So, if you have a bit of time this holiday season, why not have a play with the CSS3 grid layout module? I have outlined here some of my thoughts on how grid layout and other modules that separate layout from source order can be used in the work that I do. Likewise, wherever in the stack you work, playing with and thinking about new specifications means you can think about how you would use them to enhance your work. Spot a problem? Think that a change to the specification would improve things for a specific use case? Then you have something you could post to www-style to add to the discussion around this module. All the examples are on CodePen so feel free to play around and fork them. 2012 Rachel Andrew rachelandrew 2012-12-18T00:00:00+00:00 https://24ways.org/2012/css3-grid-layout/ code
130 Faster Development with CSS Constants Anyone even slightly familiar with a programming language will have come across the concept of constants – a fixed value that can be used through your code. For example, in a PHP script I might have a constant which is the email address that all emails generated by my application get sent to. $adminEmail = 'info@example.com'; I could then use $adminEmail in my script whenever I wanted an email to go to that address. The benefit of this is that when the client decides they want the email to go to a different address, I only need change it in one place – the place where I initially set the constant. I could also quite easily make this value user defined and enable the administrator to update the email address. Unfortunately CSS doesn’t support constants. It would be really useful to be able to define certain values initially and then use them throughout a CSS file, so in this article I’m going to take a look at some of the methods we do have available and provide pointers to more in depth commentary on each. If you have a different method, or tip to share please add it to the comments. So what options do we have? One way to get round the lack of constants is to create some definitions at the top of your CSS file in comments, to define ‘constants’. A common use for this is to create a ‘color glossary’. This means that you have a quick reference to the colors used in the site to avoid using alternates by mistake and, if you need to change the colors, you have a quick list to go down and do a search and replace. In the below example, if I decide I want to change the mid grey to #999999, all I need to do is search and replace #666666 with #999999 – assuming I’ve remember to always use that value for things which are mid grey. /* Dark grey (text): #333333 Dark Blue (headings, links) #000066 Mid Blue (header) #333399 Light blue (top navigation) #CCCCFF Mid grey: #666666 */ This is a fairly low-tech method, but if used throughout the development of the CSS files can make changes far simpler and help to ensure consistency in your color scheme. I’ve seen this method used by many designers however Garrett Dimon documents the method, with more ideas in the comments. Going server-side To truly achieve constants you will need to use something other than CSS to process the file before it is sent to the browser. You can use any scripting language – PHP, ASP, ColdFusion etc. to parse a CSS file in which you have entered constants. So that in a constants section of the CSS file you would have: $darkgrey = '#333333'; $darkblue = '#000066'; The rest of the CSS file is as normal except that when you come to use the constant value you would use the constant name instead of adding the color: p { color: $darkgrey; } Your server-side script could then parse the CSS file, replace the constant names with the constant values and serve a valid CSS file to the browser. Christian Heilmann has done just this for PHP however this could be adapted for any language you might have available on your server. Shaun Inman came up with another way of doing this that removes the need to link to a PHP script and also enables the adding of constants using the syntax of at-rules . This method is again using PHP and will require you to edit an .htaccess file. A further method is to generate static CSS files either using a script locally – if the constants are just to enable speed of development – or as part of the web application itself. Storing a template stylesheet with constant names in place of the values you will want to update means that your script can simply open the template, replace the variables and save the result as a new stylesheet file. While CSS constants are a real help to developers, they can also be used to add new functionality to your applications. As with the email address example that I used at the beginning of this article, using a combination of CSS and server-side scripting you could enable a site administrator to select the colours for a new theme to be used on a page of a content managed site. By using constants you need only give them the option to change certain parts of the CSS and not upload a whole different CSS file, which could lead to some interesting results! As we are unlikely to find real CSS constants under the tree this Christmas the above methods are some possibilities for better management of your stylesheets. However if you have better methods, CSS Constant horror stories or any other suggestions, add your comments below. 2006 Rachel Andrew rachelandrew 2006-12-02T00:00:00+00:00 https://24ways.org/2006/faster-development-with-css-constants/ process
192 Cleaner Code with CSS3 Selectors The parts of CSS3 that seem to grab the most column inches on blogs and in articles are the shiny bits. Rounded corners, text shadow and new ways to achieve CSS layouts are all exciting and bring with them all kinds of possibilities for web design. However what really gets me, as a developer, excited is a bit more mundane. In this article I’m going to take a look at some of the ways our front and back-end code will be simplified by CSS3, by looking at the ways we achieve certain visual effects now in comparison to how we will achieve them in a glorious, CSS3-supported future. I’m also going to demonstrate how we can use these selectors now with a little help from JavaScript – which can work out very useful if you find yourself in a situation where you can’t change markup that is being output by some server-side code. The wonder of nth-child So why does nth-child get me so excited? Here is a really common situation, the designer would like the tables in the application to look like this: Setting every other table row to a different colour is a common way to enhance readability of long rows. The tried and tested way to implement this is by adding a class to every other row. If you are writing the markup for your table by hand this is a bit of a nuisance, and if you stick a row in the middle you have to change the rows the class is applied to. If your markup is generated by your content management system then you need to get the server-side code to add that class – if you have access to that code. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Striping every other row - using classes</title> <style type="text/css"> body { padding: 40px; margin: 0; font: 0.9em Arial, Helvetica, sans-serif; } table { border-collapse: collapse; border: 1px solid #124412; width: 600px; } th { border: 1px solid #124412; background-color: #334f33; color: #fff; padding: 0.4em; text-align: left; } td { padding: 0.4em; } tr.odd td { background-color: #86B486; } </style> </head> <body> <table> <tr> <th>Name</th> <th>Cards sent</th> <th>Cards received</th> <th>Cards written but not sent</th> </tr> <tr> <td>Ann</td> <td>40</td> <td>28</td> <td>4</td> </tr> <tr class="odd"> <td>Joe</td> <td>2</td> <td>27</td> <td>29</td> </tr> <tr> <td>Paul</td> <td>5</td> <td>35</td> <td>2</td> </tr> <tr class="odd"> <td>Louise</td> <td>65</td> <td>65</td> <td>0</td> </tr> </table> </body> </html> View Example 1 This situation is something I deal with on almost every project, and apart from being an extra thing to do, it just isn’t ideal having the server-side code squirt classes into the markup for purely presentational reasons. This is where the nth-child pseudo-class selector comes in. The server-side code creates a valid HTML table for the data, and the CSS then selects the odd rows with the following selector: tr:nth-child(odd) td { background-color: #86B486; } View Example 2 The odd and even keywords are very handy in this situation – however you can also use a multiplier here. 2n would be equivalent to the keyword ‘odd’ 3n would select every third row and so on. Browser support Sadly, nth-child has pretty poor browser support. It is not supported in Internet Explorer 8 and has somewhat buggy support in some other browsers. Firefox 3.5 does have support. In some situations however, you might want to consider using JavaScript to add this support to browsers that don’t have it. This can be very useful if you are dealing with a Content Management System where you have no ability to change the server-side code to add classes into the markup. I’m going to use jQuery in these examples as it is very simple to use the same CSS selector used in the CSS to target elements with jQuery – however you could use any library or write your own function to do the same job. In the CSS I have added the original class selector to the nth-child selector: tr:nth-child(odd) td, tr.odd td { background-color: #86B486; } Then I am adding some jQuery to add a class to the markup once the document has loaded – using the very same nth-child selector that works for browsers that support it. <script src="http://code.jquery.com/jquery-latest.js"></script> <script> $(document).ready(function(){ $("tr:nth-child(odd)").addClass("odd"); }); </script> View Example 3 We could just add a background colour to the element using jQuery, however I prefer not to mix that information into the JavaScript as if we change the colour on our table rows I would need to remember to change it both in the CSS and in the JavaScript. Doing something different with the last element So here’s another thing that we often deal with. You have a list of items all floated left with a right hand margin on each element constrained within a fixed width layout. If each element has the right margin applied the margin on the final element will cause the set to become too wide forcing that last item down to the next row as shown in the below example where I have used a grey border to indicate the fixed width. Currently we have two ways to deal with this. We can put a negative right margin on the list, the same width as the space between the elements. This means that the extra margin on the final element fills that space and the item doesn’t drop down. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>The last item is different</title> <style type="text/css"> body { padding: 40px; margin: 0; font: 0.9em Arial, Helvetica, sans-serif; } div#wrapper { width: 740px; float: left; border: 5px solid #ccc; } ul.gallery { margin: 0 -10px 0 0; padding: 0; list-style: none; } ul.gallery li { float: left; width: 240px; margin: 0 10px 10px 0; } </style> </head> <body> <div id="wrapper"> <ul class="gallery"> <li><img src="xmas1.jpg" alt="baubles" /></li> <li><img src="xmas2.jpg" alt="star" /></li> <li><img src="xmas3.jpg" alt="wreath" /></li> </ul> </div> </body> </html> View Example 4 The other solution will be to put a class on the final element and in the CSS remove the margin for this class. ul.gallery li.last { margin-right: 0; } This second solution may not be easy if the content is generated from server-side code that you don’t have access to change. It could all be so different. In CSS3 we have marvellously common-sense selectors such as last-child, meaning that we can simply add rules for the last list item. ul.gallery li:last-child { margin-right: 0; } View Example 5 This removed the margin on the li which is the last-child of the ul with a class of gallery. No messing about sticking classes on the last item, or pushing the width of the item out wit a negative margin. If this list of items repeated ad infinitum then you could also use nth-child for this task. Creating a rule that makes every 3rd element margin-less. ul.gallery li:nth-child(3n) { margin-right: 0; } View Example 6 A similar example is where the designer has added borders to the bottom of each element – but the last item does not have a border or is in some other way different. Again, only a class added to the last element will save you here if you cannot rely on using the last-child selector. Browser support for last-child The situation for last-child is similar to that of nth-child, in that there is no support in Internet Explorer 8. However, once again it is very simple to replicate the functionality using jQuery. Adding our .last class to the last list item. $("ul.gallery li:last-child").addClass("last"); We could also use the nth-child selector to add the .last class to every third list item. $("ul.gallery li:nth-child(3n)").addClass("last"); View Example 7 Fun with forms Styling forms can be a bit of a trial, made difficult by the fact that any CSS applied to the input element will effect text fields, submit buttons, checkboxes and radio buttons. As developers we are left adding classes to our form fields to differentiate them. In most builds all of my text fields have a simple class of text whereas I wouldn’t dream of adding a class of para to every paragraph element in a document. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Syling form fields</title> <style type="text/css"> body { padding: 40px; margin: 0; font: 0.9em Arial, Helvetica, sans-serif; } form div { clear: left; padding: 0 0 0.8em 0; } form label { float: left; width: 120px; } form .text, form textarea { border:1px solid #333; padding: 0.2em; width: 400px; } form .button { border: 1px solid #333; background-color: #eee; color: #000; padding: 0.1em; } </style> </head> <body> <h1>Send your Christmas list to Santa</h1> <form method="post" action="" id="christmas-list"> <div><label for="fName">Name</label> <input type="text" name="fName" id="fName" class="text" /></div> <div><label for="fEmail">Email address</label> <input type="text" name="fEmail" id="fEmail" class="text" /></div> <div><label for="fList">Your list</label> <textarea name="fList" id="fList" rows="10" cols="30"></textarea></div> <div><input type="submit" name="btnSubmit" id="btnSubmit" value="Submit" class="button" ></div> </form> </body> </html> View Example 8 Attribute selectors provide a way of targeting elements by looking at the attributes of those elements. Unlike the other examples in this article which are CSS3 selectors, the attribute selector is actually a CSS2.1 selector – it just doesn’t get much use because of lack of support in Internet Explorer 6. Using attribute selectors we can write rules for text inputs and form buttons without needing to add any classes to the markup. For example after removing the text and button classes from my text and submit button input elements I can use the following rules to target them: form input[type="text"] { border: 1px solid #333; padding: 0.2em; width: 400px; } form input[type="submit"]{ border: 1px solid #333; background-color: #eee; color: #000; padding: 0.1em; } View Example 9 Another problem that I encounter with forms is where I am using CSS to position my labels and form elements by floating the labels. This works fine as long as I want all of my labels to be floated, however sometimes we get a set of radio buttons or a checkbox, and I don’t want the label field to be floated. As you can see in the below example the label for the checkbox is squashed up into the space used for the other labels, yet it makes more sense for the checkbox to display after the text. I could use a class on this label element however CSS3 lets me to target the label attribute directly by looking at the value of the for attribute. label[for="fOptIn"] { float: none; width: auto; } Being able to precisely target attributes in this way is incredibly useful, and once IE6 is no longer an issue this will really help to clean up our markup and save us from having to create all kinds of special cases when generating this markup on the server-side. Browser support The news for attribute selectors is actually pretty good with Internet Explorer 7+, Firefox 2+ and all other modern browsers all having support. As I have already mentioned this is a CSS2.1 selector and so we really should expect to be able to use it as we head into 2010! Internet Explorer 7 has slightly buggy support and will fail on the label example shown above however I discovered a workaround in the Sitepoint CSS reference comments. Adding the selector label[htmlFor="fOptIn"] to the correct selector will create a match for IE7. IE6 does not support these selector but, once again, you can use jQuery to plug the holes in IE6 support. The following jQuery will add the text and button classes to your fields and also add a checks class to the label for the checkbox, which you can use to remove the float and width for this element. $('form input[type="submit"]').addClass("button"); $('form input[type="text"]').addClass("text"); $('label[for="fOptIn"]').addClass("checks"); View Example 10 The selectors I’ve used in this article are easy to overlook as we do have ways to achieve these things currently. As developers – especially when we have frameworks and existing code that cope with these situations – it is easy to carry on as we always have done. I think that the time has come to start to clean up our front and backend code and replace our reliance on classes with these more advanced selectors. With the help of a little JavaScript almost all users will still get the full effect and, where we are dealing with purely visual effects, there is definitely a case to be made for not worrying about the very small percentage of people with old browsers and no JavaScript. They will still receive a readable website, it may just be missing some of the finesse offered to the modern browsing experience. 2009 Rachel Andrew rachelandrew 2009-12-20T00:00:00+00:00 https://24ways.org/2009/cleaner-code-with-css3-selectors/ code
214 Christmas Gifts for Your Future Self: Testing the Web Platform In the last year I became a CSS specification editor, on a mission to revitalise CSS Multi-column layout. This has involved learning about many things, one of which has been the Web Platform Tests project. In this article, I’m going to share what I’ve learned about testing the web platform. I’m also going to explain why I think you might want to get involved too. Why test? At one time or another it is likely that you have been frustrated by an issue where you wrote some valid CSS, and one browser did one thing with it and another something else entirely. Experiences like this make many web developers feel that browser vendors don’t work together, or they are actively doing things in a different way to one another to the detriment of those of us who use the platform. You’ll be glad to know that isn’t the case, and that the people who work on browsers want things to be consistent just as much as we do. It turns out however that interoperability, which is the official term for “works in all browsers”, is hard. Thanks to web-platform-tests, a test from another browser vendor just found genuine bug in our code before we shipped 😻— Brian Birtles (@brianskold) February 10, 2017 In order for W3C Specifications to move on to become W3C Recommendations we need to have interoperable implementations. 6.2.4 Implementation Experience Implementation experience is required to show that a specification is sufficiently clear, complete, and relevant to market needs, to ensure that independent interoperable implementations of each feature of the specification will be realized. While no exhaustive list of requirements is provided here, when assessing that there is adequate implementation experience the Director will consider (though not be limited to): is each feature of the current specification implemented, and how is this demonstrated? are there independent interoperable implementations of the current specification? are there implementations created by people other than the authors of the specification? are implementations publicly deployed? is there implementation experience at all levels of the specification’s ecosystem (authoring, consuming, publishing…)? are there reports of difficulties or problems with implementation? https://www.w3.org/2017/Process-20170301/#transition-reqs We all want interoperability, achieving interoperability is part of the standards process. The next question is, how do we make sure that we get it? Unimplemented vs uninteroperable implementations Before looking at how we can try to improve interoperability, I’d like to look at the reasons we don’t always meet that aim. There are a couple of reasons why browser X is not doing the same thing as browser Y. The first reason is that browser X has not implemented that feature yet. Relatively small teams of people work on browser engines, and their resources are spread as thinly as those of any company. Behind those browsers are business or organisational goals which may not match our desire for a shiny feature to be made available. There are ways in which we as the web community can help gently encourage implementations - by requesting the feature, by using it so it shows up in usage reports, or writing about it to show interest. However, there will always be some degree of lag based on priorities. A browser not supporting a feature at all, is reasonably easy to deal with these days. We can test for support with Feature Queries, and create sensible fallbacks. What is harder to deal with is when a feature is implemented in different ways by different browsers. In that situation you use the feature, perhaps referring to the specification to ensure that you are writing your CSS correctly. It looks exactly as you expect in one browser and it’s all broken when you test in another. A frequent cause of this kind of issue is that the specification is not well defined in a particular area or that the specification has changed since one or other browser implemented it. CSS specifications are not developed in a darkened room, then presented to browser vendors to implement as a completed document. It would be nice if it worked like that, however the web platform is a gnarly thing. Before we can be sure that a specification is correct, it needs implementing in order that we can get the interoperable implementations I described earlier. A circular process has to happen. Specifications have to be written, browsers have to implement and find the problems, and then the specification has to be revised. Many people reading this will be familiar with how flexbox changed three times in browsers, leaving us with a mess of incompatibilities and the need to use at least two versions of the spec. This story was an example of this circular process, in this case the specification was flagged as experimental using vendor prefixes. We had become used to using vendor prefixes in production and early adopters of flexbox were bitten by this. Today, specifications are developed behind experimental flags as we saw with CSS Grid Layout. Yet there has to come a time when implementations ship, and remove those flags, and it may be that knowingly or unknowingly some interop issues slip through. You will know these interop issues as “browser bugs”, perhaps you have even reported one (thank you!) and none of us want them, so how do we make the platform as robust as possible? How do we ensure we have interoperability? If you were working on a large web application, with several people committing code, it would be very easy for one person to make a change that inadvertently broke some part of the application. They might not realise the fact that their change would cause a problem, due to not having a complete understanding of the entire codebase. To prevent this from happening, it is accepted good practice to write tests as well as code. The tests can then be run before the application is deployed. Unless you start out from the beginning writing tests, and are very good at writing a test for every bit of code, it is likely that some issues do slip through from time to time. When this happens, a good approach is to not only fix the issue but also to write a test that would stop it ever happening again. That way the test suite improves over time and hopefully fewer issues happen. The web platform is essentially a giant, sprawling application, with a huge range of people working on it in different ways. There is therefore plenty of opportunity for issues to creep in, so it seems like having some way of writing tests and automating those tests on browsers would be a good thing. That, is what the Web Platform Tests project has set out to achieve. Web Platform Tests Web Platform Tests is the test suite for the web platform. It is set of tests for all parts of the web platform, which can be run in any browser and the results reported. This article mostly discusses CSS tests, because I work on CSS. You will find that there are tests covering the full platform, and you can look into whichever area you have the most interest and experience in. If we want to create a test suite for a CSS specification then we need to ensure that every feature of the specification has a related test. If a change is made to the spec, and a test committed that reflects that change, then it should be straightforward to run that test against each browser and see if it passes. Currently, at the CSS Working Group, specifications that are at Candidate Recommendation Status should commit at test with every normative change to the spec. To explain the terminology, a normative change is one that changes some of the normative text of a specification - text that contains instructions as to how a browser should render a certain thing. A Candidate Recommendation is the status at which the Working Group officially request implementations of the spec, therefore it is reasonable to assume that any change may cause an interoperability issue. It is usually the case that representatives from all browsers will have discussed the change, so anyone who needs to change code will be aware. In this case the test allows them to check that their change passes and matches everyone else. Tests would also highlight the situation where a change to the spec caused an issue in a browser that otherwise wouldn’t be aware if it. Just as a test suite for your web application should alert a person committing code, that their change will cause a problem elsewhere. Discovering the tests I’ve found that the more I have understood the effort that goes into interoperability, and the reasons why creating an interoperable web is so hard, running into browser issues has become less frustrating. I have somewhere to go, even if all I can do is log the bug. If you are even slightly interested in the subject, go have a poke around wpt.fyi. You can explore the various parts of the web platform and see how many tests have been committed. All the the CSS tests are under the directory /css where you will find each specification. Find a specification you are interested in, and look at the tests. Each test has a link to run it in your own browser to see if it passes. This can be useful in itself, if you are battling with an issue and have reduced it down to something specific, you can go and look to see if there is a test covering that and whether it appears to pass or fail in the browser you are battling with. If it turns out that the test fails, it’s probably not you! A test on the wpt.fyi dashboard Note: In some tests you will come across mention of a font called Ahem. This is a font designed for testing which contains consistent glyphs. You can read about how to use the font and download it here. Contributing to Web Platform Tests You can also become involved with Web Platform Tests. People often ask me how they can become involved in CSS, and I can think of no better way than by writing tests. You need to really understand a feature to accurately come up with a method of testing if it works or not in the different engines. This is not glamorous work, it is however a very useful thing to be involved with. In addition to helping yourself, and developing the sort of deep knowledge of the platform that enables contribution, you will really help the progress of specifications. There are only a very few people writing specs. If those people also have to write and review all of the tests it slows down their work. If you want a better, more interoperable web, and to massively improve your ability to have nerdy conversations about highly specific things, testing is the place to start. A local testing setup Your first stop should be to visit the home of Web Platform Tests. There is some documentation here, which does tend to assume you know about the tests and what you are looking for - having read this article you know as much as I do. To be able to work on tests you will want to: Clone the WPT repo, this is where all the tests are stored Install some tools so you can run up a local copy of the tests The instructions on the Readme in the repo should get you up and running, you can then load your own version of the test suite in a browser at http://web-platform-test:8000, or whichever port you set up. Running tests locally Finding things to test It’s currently not straightforward to locate low-hanging fruit in order to start committing tests. There are some issues flagged up as a good first issue in the GitHub repo, if any of those match your interest and knowledge. Otherwise, a good place to start is where you know of existing interoperability issues. If you are aware of a browser bug, have a look and see if there is a test that addresses it. If not, then a test highlights the interoperability issue, and if it is an issue that you are running into means that you have a nice way to see if it has been fixed! Talk to people There is an IRC channel at irc://irc.w3.org:6667/testing, where you will find people who are writing tests as well as people who are working on the test suite framework itself. They have always been very friendly, and are likely to welcome people with a real interest in creating tests. Gathering information First you need to read the spec. To be able to create a test you need to know and to understand what the specification says should be happening. As I mentioned, writing tests will improve your knowledge dramatically! In general I find that web developers assume their favourite browser has got it right, this isn’t about right or wrong however, or good browsers versus bad ones. The browser with the incorrect implementation may have had a perfect, as per the spec implementation, until something changed. Do some investigation and work out what the spec says, and which – if any – browser is doing it correctly. Another good place to look when trying to create a test for an interop issue, is to look at the browser issue trackers. It is quite likely that someone has already logged the issue, and detailed what it is, and even which browsers are as per the spec. This is useful information, as you then have a clue as to which browsers should pass your test. Remember to check version numbers - an issue may well be fixed in a pre-release version of Chrome for example, but not in the public release. Edge Issue Tracker Mozilla Issue Tracker WebKit Issue Tracker Chromium Issue Tracker Writing the test If you’ve ever created a Reduced Test Case to isolate a browser issue, you already have some idea of what we are trying to do with a test. We want to test one thing, in isolation, and to be able to confirm “yes this works as per the spec” or “no, this does not”. The main two types of test are: testharness.js tests reftests The testharness.js tests use JavaScript to test an assertion, this framework is designed as a way to test Web APIs and as this quickly gets fairly complicated - and I’m a complete beginner myself at writing these - I’ll refer you to the excellent tutorial Using testharness.js. Many CSS tests will be reftests. A reftest involves getting two pages to lay out in the same way, so that they are visually the same. For example, you can find a reftest for Grid Layout at:https://w3c-test.org/css/css-grid/alignment/grid-gutters-001.html or at http://web-platform.test:8000/css/css-grid/alignment/grid-gutters-001.html if you have run up your own copy of WPT. <!DOCTYPE html> <meta charset="utf-8"> <title>CSS Grid Layout Test: Support for gap shorthand property of row-gap and column-gap</title> <link rel="help" href="https://www.w3.org/TR/css-grid-1/#gutters"> <link rel="help" href="https://www.w3.org/TR/css-align-3/#gap-shorthand"> <link rel="match" href="../reference/grid-equal-gutters-ref.html"> <link rel="author" title="Rachel Andrew" href="mailto:me@rachelandrew.co.uk"> <style> #grid { display: grid; width:200px; gap: 20px; grid-template-columns: 90px 90px; grid-template-rows: 90px 90px; background-color: green; } #grid > div { background-color: silver; } </style> <p>The test passes if it has the same visual effect as reference.</p> <div id="grid"> <div></div> <div></div> <div></div> <div></div> </div> I am testing the new gap property (renamed grid-gap). The reference file can be found by looking for the line: <link rel="match" href="../reference/grid-equal-gutters-ref.html"> In that file, I am using absolute positioning to mock up the way the file would look if gap is implemented correctly. <!DOCTYPE html> <meta charset="utf-8"> <title>CSS Grid Layout Reference: a square with a green cross</title> <link rel="author" title="Rachel Andrew" href="mailto:me@rachelandrew.co.uk" /> <style> #grid { width:200px; height: 200px; background-color: green; position: relative; } #grid > div { background-color: silver; width: 90px; height: 90px; position: absolute; } #grid :nth-child(1) { top: 0; left: 0; } #grid :nth-child(2) { top: 0; left: 110px; } #grid :nth-child(3) { top: 110px; left: 0; } #grid :nth-child(4) { top: 110px; left: 110px; } </style> <div id="grid"> <div></div> <div></div> <div></div> <div></div> </div> The tests are compared in an automated way by taking screenshots of the test and reference. These are relatively simple tests to write, you will find the work is not in writing the test however. The work is really in doing the research, and making sure you understand what is supposed to happen so you can write the test. Which is why, if you really want to get your hands dirty in the web platform, this is a good place to start. Committing a test Once you have written a test you can run the lint tool to make sure that everything is tidy. This tool is run automatically after you submit your pull request, and reviewers won’t accept a test with lint errors, so do this locally first to catch anything obvious. Tests are added as a pull request, once you have your test ready to go you can create a pull request to add it to the repository. Your test will be tested and it will then wait for a review. You may well then find yourself in a bit of a waiting game, as the test needs to be reviewed. How long that takes will depend on how active work is on that spec. People who are in the OWNERS file for that spec should be notified. You can always ask in IRC to see if someone is available who can look at and potentially merge your test. Usually the reviewer will have some comments as to how the test can be improved, in the same as the owner of an open source project you submit a PR to might ask you to change some things. Work with them to make your test as good as it can be, the things you learn on the first test you submit will make future ones easier. You can then bask in the glow of knowing you have done something towards the aim of a more interoperable web for all of us. Christmas gifts for your future self I have been a web developer for over 20 years. I have no idea what the web platform will look like in 20 more years, but for as long as I’m working on it I’ll keep on trying to make it better. Making the web more interoperable makes it a better place to be a web developer, storing up some Christmas gifts for my future self, while learning new things as I do so. Resources I rounded up everything I could find on WPT while researching this article. As well as some other links that might be helpful for you. These links are below. Happy testing! Web Platform Tests Using testharness.js IRC Channel irc://irc.w3.org:6667/testing Edge Issue Tracker Mozilla Issue Tracker WebKit Issue Tracker Chromium Issue Tracker Reducing an Issue - guide to created a reduced test case Effectively Using Web Platform Tests: Slides and Video An excellent walkthrough from Lyza Gardner on her working on tests for the HTML specification - Moving Targets: a case study on testing web standards. Improving interop with web-platform-tests: Slides and Video 2017 Rachel Andrew rachelandrew 2017-12-10T00:00:00+00:00 https://24ways.org/2017/testing-the-web-platform/ code
243 Researching a Property in the CSS Specifications I frequently joke that I’m “reading the specs so you don’t have to”, as I unpack some detail of a CSS spec in a post on my blog, some documentation for MDN, or an article on Smashing Magazine. However waiting for someone like me to write an article about something is a pretty slow way to get the information you need. Sometimes people like me get things wrong, or specifications change after we write a tutorial. What if you could just look it up yourself? That’s what you get when you learn to read the CSS specifications, and in this article my aim is to give you the basic details you need to grab quick information about any CSS property detailed in the CSS specs. Where are the CSS Specifications? The easiest way to see all of the CSS specs is to take a look at the Current Work page in the CSS section of the W3C Website. Here you can see all of the specifications listed, the level they are at and their status. There is also a link to the specification from this page. I explained CSS Levels in my article Why there is no CSS 4. Who are the specifications for? CSS specifications are for everyone who uses CSS. You might be a browser engineer - referred to as an implementor - needing to know how to implement a feature, or a web developer - referred to as an author - wanting to know how to use the feature. The fact that both parties are looking at the same document hopefully means that what the browser displays is what the web developer expected. Which version of a spec should I look at? There are a couple of places you might want to look. Each published spec will have the latest published version, which will have TR in the URL and can be accessed without a date (which is always the newest version) or at a date, which will be the date of that publication. If I’m referring to a particular Working Draft in an article I’ll typically link to the dated version. That way if the information changes it is possible for someone to see where I got the information from at the time of writing. If you want the very latest additions and changes to the spec, then the Editor’s Draft is the place to look. This is the version of the spec that the editors are committing changes to. If I make a change to the Multicol spec and push it to GitHub, within a few minutes that will be live in the Editor’s Draft. So it is possible there are errors, bits of text that we are still working out and so on. The Editor’s Draft however is definitely the place to look if you are wanting to raise an issue on a spec, as it may be that the issue you are about to raise is already fixed. If you are especially keen on seeing updates to specifications keep an eye on https://drafts.csswg.org/ as this is a list of drafts, along with the date they were last updated. How to approach a spec The first thing to understand is that most CSS Specifications start with the most straightforward information, and get progressively further into the weeds. For an author the initial examples and explanations are likely to be of interest, and then the property definitions and examples. Therefore, if you are looking at a vast spec, know that you probably won’t need to read all the way to the bottom, or read every section in detail. The second thing that is useful to know about modern CSS specifications is how modularized they are. It really never is a case of finding everything you need in a single document. If we tried to do that, there would be a lot of repetition and likely inconsistency between specs. There are some key specifications that many other specifications draw on, such as: Values and Units Intrinsic and Extrinsic Sizing Box Alignment When something is defined in another specification the spec you are reading will link to it, so it is worth opening that other spec in a new tab in order that you can refer back to it as you explore. Researching your property As an example we will take a look at the property grid-auto-rows, this property defines row tracks in the implicit grid when using CSS Grid Layout. The first thing you will need to do is find out which specification defines this property. You might already know which spec the property is part of, and therefore you could go directly to the spec and search using your browser or look in the navigation for the spec to find it. Alternatively, you could take a look at the CSS Property Index, which is an automatically generated list of CSS Properties. Clicking on a property will take you to the TR version of the spec, the latest published draft, and the definition of that property in it. This definition begins with a panel detailing the syntax of this property. For grid-auto-rows, you can see that it is listed along with grid-auto-columns as these two properties are essentially identical. They take the same values and work in the same way, one for rows and the other for columns. Value For value we can see that the property accepts a value <track-size>. The next thing to do is to find out what that actually means, clicking will take you to where it is defined in the Grid spec. The <track-size> value is defined as accepting various values: <track-breadth> minmax( <inflexible-breadth> , <track-breadth> ) fit-content( <length-percentage> We need to head down the rabbit hole to find out what each of these mean. From here we essentially go down line by line until we have unpacked the value of track-size. <track-breadth> is defined just below <track-size> as: <length-percentage> <flex> min-content max-content auto So these are all things that would be valid to use as a value for grid-auto-rows. The first value of <length-percentage> is something you will see in many specifications as a value. It means that you can use a length unit - for example px or em - or a percentage. Some properties only accept a <length> in which case you know that you cannot use a percentage as the value. This means that you could have grid-auto-rows with any of the following values. grid-auto-rows: 100px; grid-auto-rows: 1em; grid-auto-rows: 30%; When using percentages, it is important to know what it is a percentage of. As a percentage has to resolve from something. There is text in the spec which explains how column and row percentages work. “<percentage> values are relative to the inline size of the grid container in column grid tracks, and the block size of the grid container in row grid tracks.” This means that in a horizontal writing mode such as when using English, a percentage when used as a track-size in grid-auto-columns would be a percentage of the width of the grid, and a percentage in grid-auto-rows a percentage of the height of the grid. The second value of <flex> is also defined here, as “A non-negative dimension with the unit fr specifying the track’s flex factor.” This is the fr unit, and the spec links to a fuller definition of fr as this unit is only used in Grid Layout so it is therefore defined in the grid spec. We now know that a valid value would be: grid-auto-rows: 1fr; There is some useful information about the fr unit in this part of the spec. It is noted that the fr unit has an automatic minimum. This means that 1fr is really minmax(auto, 1fr). This is why having a number of tracks all at 1fr does not mean that all are equal sized, as a larger item in any of the tracks would have a large auto size and therefore would be larger after spare space had been distributed. We then have min-content and max-content. These keywords can be used for track sizing and the specification defines what they mean in the context of sizing a track, representing the min and max-sizing contributions of the grid tracks. You will see that there are various terms linked in the definition, so if you do not know what these mean you can follow them to find out. For example the spec links max-content contribution to the CSS Intrinsic and Extrinsic Sizing specification. This is one of those specs which is drawn on by many other specifications. If we follow that link we can read the definition there and follow further links to understand what each term means. The more that you read specifications the more these terms will become familiar to you. Just like learning a foreign language, at first you feel like you have to look up every little thing. After a while you remember the vocabulary. We can now add min-content and max-content to our available values. grid-auto-rows: min-content; grid-auto-rows: max-content; The final item in our list is auto. If you are familiar with using Grid Layout, then you are probably aware that an auto sized track for will grow to fit the content used. There is an interesting note here in the spec detailing that auto sized rows will stretch to fill the grid container if there is extra space and align-content or justify-content have a value of stretch. As stretch is the default value, that means these tracks stretch by default. Tracks using other types of length will not behave like this. grid-auto-rows: auto; So, this was the list for <track-breadth>, the next possible value is minmax( <inflexible-breadth> , <track-breadth> ). So this is telling us that we can use minmax() as a value, the final (max) value will be <track-breadth> and we have already unpacked all of the allowable values there. The first value (min) is detailed as an <inflexible-breadth>. If we look at the values for this, we discover that they are the same as <track-breadth>, minus the <flex> value: <length-percentage> min-content max-content auto We already know what all of these do, so we can add possible minmax() values to our list of values for <track-size>. grid-auto-rows: minmax(100px, 200px); grid-auto-rows: minmax(20%, 1fr); grid-auto-rows: minmax(1em, auto); grid-auto-rows: minmax(min-content, max-content); Finally we can use fit-content( <length-percentage>. We can see that fit-content takes a value of <length-percentage> which we already know to be either a length unit, or a percentage. The spec details how fit-content is worked out, and it essentially allows a track which acts as if you had used the max-content keyword, however the track stops growing when it hits the length passed to it. grid-auto-rows: fit-content(200px); grid-auto-rows: fit-content(20%); Those are all of our possible values, and to round things off, check again at the initial <track-size> value, you can see it has a little + sign next to it, click that and you will be taken to the CSS Values and Units module to find that, “A plus (+) indicates that the preceding type, word, or group occurs one or more times.” This means that we can pass a single track size to grid-auto-rows or multiple track sizes as a space separated list. Below the box is an explanation of what happens if you pass in more than one track size: “If multiple track sizes are given, the pattern is repeated as necessary to find the size of the implicit tracks. The first implicit grid track after the explicit grid receives the first specified size, and so on forwards; and the last implicit grid track before the explicit grid receives the last specified size, and so on backwards.” Therefore with the following CSS, if five implicit rows were needed they would be as follows: 100px 1fr auto 100px 1fr .grid { display: grid; grid-auto-rows: 100px 1fr auto; } Initial We can now move to the next line in the box, and you’ll be glad to know that it isn’t going to require as much unpacking! This simply defines the initial value for grid-auto-rows. If you do not specify anything, created rows will be auto sized. All CSS properties have an initial value that they will use if they are invoked as part of the usage of the specification they are in, but you do not set a value for them. In the case of grid-auto-rows it is used whenever rows are created in the implicit grid, so it needs to have a value to be used even if you do not set one. Applies to This line tells us what this property is used for. Some properties are used in multiple places. For example if you look at the definition for justify-content in the Box Alignment specification you can see it is used in multicol containers, flex containers, and grid containers. In our case the property only applies for grid containers. Inherited This tells us if the property can be inherited from a parent element if it is not set. In the case of grid-auto-rows it is not inherited. A property such as color is inherited, so you do not need to set it on each element. Percentages Are percentages allowed for this property, and if so how are they calculated. In this case we are referred to the definition for grid-template-columns and grid-template-rows where we discover that the percentage is from the corresponding dimension of the content area. Media This defines the media group that the property belongs to. In this case visual. Computed Value This details how the value is resolved. The grid-auto-rows property again refers to track sizing as defined for grid-template-columns and grid-template-rows, which tells us the computed value is as specified with lengths made absolute. Canonical Order If you have a property–generally a shorthand property–which takes multiple values in a set order, then those values need to be serialized in the order detailed in the grammar for that property. In general you don’t need to worry about this value in the table. Animation Type This details whether the property can be animated, and if so what type of animation. This is useful if you are trying to animate something and not getting the result that you expect. Note that just because something is listed in the spec as animatable does not mean that browsers will have implemented animation for that property yet! That’s (mostly) it! Sometimes the property will have additional examples - there is one underneath the table for grid-auto-rows. These are worth looking at as they will highlight usage of the property that the spec editor has felt could use an example. There may also be some additional text explaining anythign specific to this property. In selecting grid-auto-rows I chose a fairly complex property in terms of the work we needed to do to unpack the value. Many properties are far simpler than this. However ultimately, even when you come across a complex value, it really is just a case of stepping through the definitions until you come to the bottom of the rabbit hole. Being able to work out what is valid for each property is incredibly useful. It means you don’t waste time trying to use a value that doesn’t work for that property. You also may find that there are values you weren’t aware of, that solve problems for you. Further reading Specifications are not designed to be user manuals, and while they often contain examples, these are pretty terse as they need to be clear to demonstrate their particular point. The manual for the Web Platform is MDN Web Docs. Pairing reading a specification with the examples and information on an MDN property page such as the one for grid-auto-rows is a really great way to ensure that you have all the information and practical usage examples you might need. You may also find useful: Value Definition Syntax on MDN. The MDN Glossary defines many common terms. Understanding the CSS Property Value Syntax goes into more detail in terms of reading the syntax. How to read W3C Specs - from 2001 but still relevant. I hope this article has gone some way to demystify CSS specifications for you. Even if the specifications are not your preferred first stop to learn about new CSS, being able to go directly to the source and avoid having your understanding filtered by someone else, can be very useful indeed. 2018 Rachel Andrew rachelandrew 2018-12-14T00:00:00+00:00 https://24ways.org/2018/researching-a-property-in-the-css-specifications/ code
306 What next for CSS Grid Layout? In 2012 I wrote an article for 24 ways detailing a new CSS Specification that had caught my eye, at the time with an implementation only in Internet Explorer. What I didn’t realise at the time was that CSS Grid Layout was to become a theme on which I would base the next four years of research, experimentation, writing and speaking. As I write this article in December 2016, we are looking forward to CSS Grid Layout being shipped in Chrome and Firefox. What will ship early next year in those browsers is expanded and improved from the early implementation I explored in 2012. Over the last four years the spec has been developed as part of the CSS Working Group process, and has had input from browser engineers, specification writers and web developers. Use cases have been discussed, and features added. The CSS Grid Layout specification is now a Candidate Recommendation. This status means the spec is to all intents and purposes, finished. The discussions now happening are on fine implementation details, and not new feature ideas. It makes sense to draw a line under a specification in order that browser vendors can ship complete, interoperable implementations. That approach is good for all of us, it makes development far easier if we know that a browser supports all of the features of a specification, rather than working out which bits are supported. However it doesn’t mean that works stops here, and that new use cases and features can’t be proposed for future levels of Grid Layout. Therefore, in this article I’m going to take a look at some of the things I think grid layout could do in the future. I would love for these thoughts to prompt you to think about how Grid - or any CSS specification - could better suit the use cases you have. Subgrid - the missing feature of Level 1 The implementation of CSS Grid Layout in Chrome, Firefox and Webkit is comparable and very feature complete. There is however one standout feature that has not been implemented in any browser as yet - subgrid. Once you set the value of the display property to grid, any direct children of that element become grid items. This is similar to the way that flexbox behaves, set display: flex and all direct children become flex items. The behaviour does not apply to children of those items. You can nest grids, just as you can nest flex containers, but the child grids have no relationship to the parent. Nesting Grids by Rachel Andrew (@rachelandrew) on CodePen. The subgrid behaviour would enable the grid defined on the parent to be used by the children. I feel this would be most useful when working with a multiple column flexible grid - for example a typical 12 column grid. I could define a grid on a wrapper, then position UI elements on that grid - from the major structural elements of my page down through the child elements to a form where I wanted the field to line up with items above. The specification contained an initial description of subgrid, with a value of subgrid for grid-template-columns and grid-template-rows, you can read about this in the August 2015 Working Draft. This version of the specification would have meant you could declare a subgrid in one dimension only, and create a different set of tracks in the other. In an attempt to get some implementation of subgrid, a revised specification was proposed earlier this year. This gives a single subgrid value of the display property. As we now cannot specify a subgrid on rows OR columns this limits us to have a subgrid that works in two dimensions. At this point neither version has been implemented by anyone, and subgrids are marked as “at risk” in the Level 1 Candidate Recommendation. With regard to ‘at-risk’ this is explained as follows: “‘At-risk’ is a W3C Process term-of-art, and does not necessarily imply that the feature is in danger of being dropped or delayed. It means that the WG believes the feature may have difficulty being interoperably implemented in a timely manner, and marking it as such allows the WG to drop the feature if necessary when transitioning to the Proposed Rec stage, without having to publish a new Candidate Rec without the feature first.” If we lose subgrid from Level 1, as it looks likely that we will, this does give us a chance to further discuss and iterate on that feature. My current thoughts are that I’m not completely happy about subgrids being tied to both dimensions and feel that a return to the earlier version, or something like it, would be preferable. Further reading about subgrid My post from 2015 detailing why I feel subgrid is important My post based on the revised specification Eric Meyer’s thoughts on subgrid Write-up of a discussion from Igalia who work on the Blink and Webkit browser implementations Styling cells, tracks and areas Having defined a grid with CSS Grid Layout you can place child elements into that grid, however what you can’t do is style the grid tracks or cells. Grid doesn’t even go as far as multiple column layout, which has the column-rule properties. In order to set a background colour on a grid cell at the moment you would have to add an empty HTML element or insert some generated content as in the below example. I’m using a 1 pixel grid gap to fake lines between grid cells, and empty div elements, and some generated content to colour those cells. Faked backgrounds and borders by Rachel Andrew (@rachelandrew) on CodePen. I think it would be a nice addition to Grid Layout to be able to directly add backgrounds and borders to cells, tracks and areas. There is an Issue raised in the CSS WG Drafts repository for Decorative Grid Cell pseudo-elements, if you want to add thoughts to that. More control over auto placement If you haven’t explicitly placed the direct children of your grid element they will be laid out according to the grid auto placement rules. You can see in this example how we have created a grid and the items are placing themselves into cells on that grid. Items auto-place on a defined grid by Rachel Andrew (@rachelandrew) on CodePen. The auto-placement algorithm is very cool. We can position some items, leaving others to auto-place; we can set items to span more than one track; we can use the grid-auto-flow property with a value of dense to backfill gaps in our grid. Websafe colors meet CSS Grid (auto-placement demo) by Rachel Andrew (@rachelandrew) on CodePen. I think however this could be taken further. In this issue posted to my CSS Grid AMA on GitHub, the question is raised as to whether it would be possible to ask grid to place items on the next available line of a certain name. This would allow you to skip tracks in the grid when using auto-placement, an issue that has also been raised by Emil Björklund in this post to the www-style list prior to spec discussion moving to Github. I think there are probably similar issues, if you can think of one add a comment here. Creating non-rectangular grid areas A grid area is a collection of grid cells, defined by setting the start and end lines for columns and rows or by creating the area in the value of the grid-template-areas property as shown below. Those areas however must be rectangular - you can’t create an L-shaped or otherwise non-regular shape. Grid Areas by Rachel Andrew (@rachelandrew) on CodePen. Perhaps in the future we could define an L-shape or other non-rectangular area into which content could flow, as in the below currently invalid code where a quote is embedded into an L-shaped content area. .wrapper { display: grid; grid-template-areas: "sidebar header header" "sidebar content quote" "sidebar content content"; } Flowing content through grid cells or areas Some uses cases I have seen perhaps are not best solved by grid layout at all, but would involve grid working alongside other CSS specifications. As I detail in this post, there are a class of problems that I believe could be solved with the CSS Regions specification, or a revised version of that spec. Being able to create a grid layout, then flow content through the areas could be very useful. Jen Simmons presented to the CSS Working Group at the Lisbon meeting a suggestion as to how this might work. In a post from earlier this year I looked at a collection of ideas from specifications that include Grid, Regions and Exclusions. These working notes from my own explorations might prompt ideas of your own. Solving the keyboard/layout disconnect One issue that grid, and flexbox to a lesser extent, raises is that it is very easy to end up with a layout that is disconnected from the underlying markup. This raises problems for people navigating using the keyboard as when tabbing around the document you find yourself jumping to unexpected places. The problem is explained by Léonie Watson with reference to flexbox in Flexbox and the keyboard navigation disconnect. The grid layout specification currently warns against creating such a disconnect, however I think it will take careful work by web developers in order to prevent this. It’s also not always as straightforward as it seems. In some cases you want the logical order to follow the source, and others it would make more sense to follow the visual. People are thinking about this issue, as you can read in this mailing list discussion. Bringing your ideas to the future of Grid Layout When I’m not getting excited about new CSS features, my day job involves working on a software product - the CMS that is serving this very website, Perch. When we launched Perch there were many use cases that we had never thought of, despite having a good idea of what might be needed in a CMS and thinking through lots of use cases. The additional use cases brought to our attention by our customers and potential customers informed the development of the product from launch. The same will be true for Grid Layout. As a “product” grid has been well thought through by many people. Yet however hard we try there will be use cases we just didn’t think of. You may well have one in mind right now. That’s ok, because as with any CSS specification, once Level One of grid is complete, work can begin on Level Two. The feature set of Level Two will be informed by the use cases that emerge as people get to grips with what we have now. This is where you get to contribute to the future of layout on the web. When you hit up against the things you cannot do, don’t just mutter about how the CSS Working Group don’t listen to regular developers and code around the problem. Instead, take a few minutes and write up your use case. Post it to your blog, to Medium, create a CodePen and go to the CSS Working Group GitHub specs repository and post an issue there. Write some pseudo-code, draw a picture, just make sure that the use case is described in enough detail that someone can see what problem you want grid to solve. It may be that - as with any software development - your use case can’t be solved in exactly the way you suggest. However once we have a use case, collected with other use cases, methods of addressing that class of problems can be investigated. I opened this article by explaining I’d written about grid layout four years ago, and how we’re only now at a point where we will have Grid Layout available in the majority of browsers. Specification development, and implementation into browsers takes time. This is actually a good thing, as it’s impossible to take back CSS once it is out there and being used by production websites. We want CSS in the wild to be well thought through and that takes time. So don’t feel that because you don’t see your use case added to a spec immediately it has been ignored. Do your future self a favour and write down your frustrations or thoughts, and we can all make sure that the web platform serves the use cases we’re dealing with now and in the future. 2016 Rachel Andrew rachelandrew 2016-12-12T00:00:00+00:00 https://24ways.org/2016/what-next-for-css-grid-layout/ code
332 CSS Layout Starting Points I build a lot of CSS layouts, some incredibly simple, others that cause sleepless nights and remind me of the torturous puzzle books that were given to me at Christmas by aunties concerned for my education. However, most of the time these layouts fit quite comfortably into one of a very few standard formats. For example: Liquid, multiple column with no footer Liquid, multiple column with footer Fixed width, centred Rather than starting out with blank CSS and (X)HTML documents every time you need to build a layout, you can fairly quickly create a bunch of layout starting points, that will give you a solid basis for creating the rest of the design and mean that you don’t have to remember how a three column layout with a footer is best achieved every time you come across one! These starting points can be really basic, in fact that’s exactly what you want as the final design, the fonts, the colours and so on will be different every time. It’s just the main sections we want to be able to quickly get into place. For example, here is a basic starting point CSS and XHTML document for a fixed width, centred layout with a footer. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Fixed Width and Centred starting point document</title> <link rel="stylesheet" type="text/css" href="fixed-width-centred.css" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <div id="wrapper"> <div id="side"> <div class="inner"> <p>Sidebar content here</p> </div> </div> <div id="content"> <div class="inner"> <p>Your main content goes here.</p> </div> </div> <div id="footer"> <div class="inner"> <p>Ho Ho Ho!</p> </div> </div> </div> </body> </html> body { text-align: center; min-width: 740px; padding: 0; margin: 0; } #wrapper { text-align: left; width: 740px; margin-left: auto; margin-right: auto; padding: 0; } #content { margin: 0 200px 0 0; } #content .inner { padding-top: 1px; margin: 0 10px 10px 10px; } #side { float: right; width: 180px; margin: 0; } #side .inner { padding-top: 1px; margin: 0 10px 10px 10px; } #footer { margin-top: 10px; clear: both; } #footer .inner { margin: 10px; } 9 times out of 10, after figuring out exactly what main elements I have in a layout, I can quickly grab the ‘one I prepared earlier’, mark-up the relevant sections within the ready-made divs, and from that point on, I only need to worry about the contents of those different areas. The actual layout is tried and tested, one that I know works well in different browsers and that is unlikely to throw me any nasty surprises later on. In addition, considering how the layout is going to work first prevents the problem of developing a layout, then realising you need to put a footer on it, and needing to redevelop the layout as the method you have chosen won’t work well with a footer. While enjoying your mince pies and mulled wine during the ‘quiet time’ between Christmas and New Year, why not create some starting point layouts of your own? The css-discuss Wiki, CSS layouts section is a great place to find examples that you can try out and find your favourite method of creating the various layout types. 2005 Rachel Andrew rachelandrew 2005-12-04T00:00:00+00:00 https://24ways.org/2005/css-layout-starting-points/ code
121 Hide And Seek in The Head If you want your JavaScript-enhanced pages to remain accessible and understandable to scripted and noscript users alike, you have to think before you code. Which functionalities are required (ie. should work without JavaScript)? Which ones are merely nice-to-have (ie. can be scripted)? You should only start creating the site when you’ve taken these decisions. Special HTML elements Once you have a clear idea of what will work with and without JavaScript, you’ll likely find that you need a few HTML elements for the noscript version only. Take this example: A form has a nifty bit of Ajax that automatically and silently sends a request once the user enters something in a form field. However, in order to preserve accessibility, the user should also be able to submit the form normally. So the form should have a submit button in noscript browsers, but not when the browser supports sufficient JavaScript. Since the button is meant for noscript browsers, it must be hard-coded in the HTML: <input type="submit" value="Submit form" id="noScriptButton" /> When JavaScript is supported, it should be removed: var checkJS = [check JavaScript support]; window.onload = function () { if (!checkJS) return; document.getElementById('noScriptButton').style.display = 'none'; } Problem: the load event Although this will likely work fine in your testing environment, it’s not completely correct. What if a user with a modern, JavaScript-capable browser visits your page, but has to wait for a huge graphic to load? The load event fires only after all assets, including images, have been loaded. So this user will first see a submit button, but then all of a sudden it’s removed. That’s potentially confusing. Fortunately there’s a simple solution: play a bit of hide and seek in the <head>: var checkJS = [check JavaScript support]; if (checkJS) { document.write('<style>#noScriptButton{display: none}</style>'); } First, check if the browser supports enough JavaScript. If it does, document.write an extra <style> element that hides the button. The difference with the previous technique is that the document.write command is outside any function, and is therefore executed while the JavaScript is being parsed. Thus, the #noScriptButton{display: none} rule is written into the document before the actual HTML is received. That’s exactly what we want. If the rule is already present at the moment the HTML for the submit button is received and parsed, the button is hidden immediately. Even if the user (and the load event) have to wait for a huge image, the button is already hidden, and both scripted and noscript users see the interface they need, without any potentially confusing flashes of useless content. In general, if you want to hide content that’s not relevant to scripted users, give the hide command in CSS, and make sure it’s given before the HTML element is loaded and parsed. Alternative Some people won’t like to use document.write. They could also add an empty <link /> element to the <head> and give it an href attribute once the browser’s JavaScript capabilities have been evaluated. The <link /> element is made to refer to a style sheet that contains the crucial #noScriptButton{display: none}, and everything works fine. Important note: The script needs access to the <link />, and the only way to ensure that access is to include the empty <link /> element before your <script> tag. 2006 Peter-Paul Koch ppk 2006-12-06T00:00:00+00:00 https://24ways.org/2006/hide-and-seek-in-the-head/ code
199 Knowing the Future - Tips for a Happy Launch Day You’ve chosen your frameworks and libraries. You’ve learned how to write code which satisfies the buzzword and performance gods. Now you need to serve it to a global audience, and make things easy to preview, to test, to sign-off, and to evolve. But infrastructure design is difficult and boring for most of us. We just want to get our work out into the wild. If only we had tools which would let us go, “Oh yeah! It all deploys perfectly every time” and shout, “You need another release? BAM! What’s next?” A truth that can be hard to admit is that very often, the production environment and its associated deployment processes are poorly defined until late into a project. This can be a problem. It makes my palms sweaty just thinking about it. If like me, you have spent time building things for clients, you’ll probably have found yourself working with a variety of technical partners and customers who bring different constraints and opportunities to your projects. Knowing and proving the environments and the deployment processes is often very difficult, but can be a factor which profoundly impacts our ability to deliver what we promised. To say nothing of our ability to sleep at night or leave our fingernails un-chewed. Let’s look at this a little, and see if we can’t set you up for a good night’s sleep, with dry palms and tidy fingernails. A familiar problem You’ve been here too, right? The project development was tough, but you’re pleased with what you are running in your local development environments. Now you need to get the client to see and approve your build, and hopefully indicate with a cheery thumbs up that it can “go live”. Chances are that we have a staging environment where the client can see the build. But be honest, is this exactly the same as the production environment? It should be, but often it’s not. Often the staging environment is nothing more than a visible server with none of the optimisations, security, load balancing, caching, and other vital bits of machinery that we’ll need (and need to test) in “prod”. Often the production environment is still being “set up” and you’ll have to wait and see. In development, “wait and see” is the enemy. Instead of waiting to see, we need to make the provisioning of, and deployment to our different environments one of the very first jobs of our project. I’ve often needed to be the unpopular voice in the room who makes a big fuss when this is delayed. I’ve described it as being a “critical blocker” during project meetings and suggested that everything should halt until it is fixed. It is that important. Clients don’t often like hearing a wary, disruptive voice saying “whoa there Nelly!”, because the development should be able to continue while the production environment gets sorted out, right? Sure. But if it is not seen as a blocker, it is seen as something that can just happen later. And if it happens later, all the ugly surprises and unknowns surface later too. And later is when we’ll need to be thinking about other things. Not the plumbing. Trust me, it pays to face up to the issue right away rather than press on optimistically. The client will thank you later. Attitudes and expectations We should, I think, exhibit these four attitudes towards production deployment: Make it scripted Make it automated Make it real Make it first Make it scripted Let’s face it, we are going to need to deploy more than once over the course of the project. We are not going to get things perfect on our first shot. Nor should we expect to. And if we are going to repeat something, we want to be able to do it identically and predictably every time without needing to rely on our memories. Developers are great at scripting things which they would otherwise need to repeat. It makes us faster and it also helps us keep track of the steps we need to take. I’m not crazy enough to try suggest the best technology to script your builds or deployments (holy wars lie down that path). A lot will depend on your languages and your tastes. Some will like Fabric, others will prefer Gulp, you might prefer Make or NPM. It doesn’t really matter as long as you can script the process of building, packaging and deploying your project. Wait. Won’t we need to know everything about the build from the start in order to do this? Aren’t our dependencies likely to change over time? Yes. That would be ideal. But it’s ok. Like our code, our deployment script will evolve over the life of a project. So evolve it. Start by scripting what is needed to support the first iteration of the project, and then maintain that script. It will become a valuable “source of truth”, providing a form of documentation of what your project needs for a successful deployment. Another bonus. Make it automated If we have a scripted deployment which we can run by executing a single command, then we are in great shape to automate that process by triggering the build and deployment via suitable events. Again, I prefer not to offer one single suggestion of when this should occur. That will depend on your approach to the project, how your development team is organised, and how your QA team operate. You can tune this to suit. For one project I worked on, we chose to trigger the build and deployment to our production environment every time we used Git to tag the master branch of our version control repository. There were a few moving parts, and we needed to do some upfront work to get everything working, but that upfront effort was repaid many fold as we deployed time and time again, and exposed some issues with our environment long before we got to “launch day”. With a scripted and automated process, we can make deployments “cheap”. This is our goal. When there are minimal cognitive or time overheads associated with deploying, we’re likely to do it all the more often and become more confident that it will behave as expected. Make it real Alright, we have written scripts to build and deploy our projects. Anyone tagging our repo will trigger things to happen as if by magic, but where are we pushing things to? We need to target a real environment if this is to have any value. A useful pattern is to have all activity on our develop branch trigger deployments to our staging server. Meanwhile tagging master will deploy a version to the production environment. How we organise this will depend on our git branching approach. (I’ve seen as many ways of approaching Git Flow as I have seen ways of approaching “Agile”). It’s vital though, that we ensure that we are deploying to, and testing against, our real infrastructure. We want to see real results. That’s the best way to learn real lessons. Make it first Building our site to run in an environment not yet fully defined or available to test is like climbing without ropes – it’s possible, but we put ourselves at risk. And the higher we climb the greater the risk. So it is important to do this as early as we possibly can. Don’t have a certificate for our HTTPS yet? Fine, but let’s still deploy to this evolving production environment and introduce HTTPS as soon as we can. Before we know it we’ll be proving that this is set up correctly and we’ll not be surprised by mixed security alerts or other nasties further down the line. Mailchimp perfectly capture the anxiety of sending emails to gazillions of people for a campaign. But we’re lucky. Launching a site doesn’t need to be like performing a mailshot. We can do things to banish that sweaty hand. Doing preparation work upfront means that by the time we need to launch the site into the wild, we have exercised the deployment mechanics, and tested the production environment so rigorously that this task will be boring. (It won’t be boring. Launching should always be exciting because the world will finally get to see our beautiful, painstaking work. But nor should it be terrifying. Especially as a result of not knowing for certain if our processes and environments are going to work or burst into flames on the big day.) What tools exist? Well this all sounds lovely. But how should we tackle this? Where are the tools for us to use? As it happens, there are many service and tools that we can use to work this way. Hosting All of the big players like Amazon, Azure and Google offer tools which can help us here. Google for example, can host multiple deployed versions of your project in parallel and you can manage them via their App Engine console. Each build receives its own URL which you can use to access any deployed version of your site. Having immutable deployments which stick around in perpetuity (or until you bin them) is a key feature which unlocks the ability to confidently direct your traffic to any version of your site. With that comes the capacity to test any version or feature in its real environment, and then promote a version, or rollback to a previous version whenever you want. A liberating power to have. Continuous integration In order to create all of those different versions, we’ll need somewhere to run our build and deployment scripts. Jenkins has been a popular Continuous Integration (CI) option for some time, and can be configured to perform all sorts of tasks, giving you extensive control over your deployment pipeline. You need to host Jenkins yourself, but it provides some simple ways to do that. The landscape for CI is getting richer and richer. With many hosted services like Circle CI providing this kind of automation up in the cloud. One stop shop Netlify combines both hosting and continuous integration services. It monitors your git repositories and automatically runs your build in a container on its servers when it finds changes. Each branch and pull request in your git repository will result in an immutable version of your site with its own URL. Netlify is unlike Google Cloud, AWS or Azure in that it cannot host a dynamic server-side application for you. Instead it specialises in hosting static, or so called JAMstack sites. Personally, I find that its simplicity makes it an approachable option, and a good place to learn and adopt some of these valuable habits. Full disclosure: I’m a Netlify employee. But before I was, I was an avid customer, and it was through using Netlify that I first encountered some of these principles in practice. Conclusion. It’s all about the approach No matter what tools or services you use (and there are many which can support these practices), the most important thing is to adopt an approach which lets you prove your environments as quickly as possible. Front-loading this effort will cast light onto the issues that you’ll need to address early and often, leaving no infrastructure surprises to spoil things for you on launch day. Automating the process will mean that when you do find things that you need to fix or to improve later (and you will), issuing another release will be trivial. It is a lovely feeling when you have confidence that releasing v1.0.0 will be no more stressful v0.0.1. In fact it should actually be less stressful, as you’ll have been down this road many times by then. Fixing the potholes and smoothing the way as you went. From here, it should be a smooth ride. 2017 Phil Hawksworth philhawksworth 2017-12-21T00:00:00+00:00 https://24ways.org/2017/knowing-the-future/ process
36 Naming Things There are only two hard things in computer science: cache invalidation and naming things. Phil Karlton Being a professional web developer means taking responsibility for the code you write and ensuring it is comprehensible to others. Having a documented code style is one means of achieving this, although the size and type of project you’re working on will dictate the conventions used and how rigorously they are enforced. Working in-house may mean working with multiple developers, perhaps in distributed teams, who are all committing changes – possibly to a significant codebase – at the same time. Left unchecked, this codebase can become unwieldy. Coding conventions ensure everyone can contribute, and help build a product that works as a coherent whole. Even on smaller projects, perhaps working within an agency or by yourself, at some point the resulting product will need to be handed over to a third party. It’s sensible, therefore, to ensure that your code can be understood by those who’ll eventually take ownership of it. Put simply, code is read more often than it is written or changed. A consistent and predictable naming scheme can make code easier for other developers to understand, improve and maintain, presumably leaving them free to worry about cache invalidation. Let’s talk about semantics Names not only allow us to identify objects, but they can also help us describe the objects being identified. Semantics (the meaning or interpretation of words) is the cornerstone of standards-based web development. Using appropriate HTML elements allows us to create documents and applications that have implicit structural meaning. Thanks to HTML5, the vocabulary we can choose from has grown even larger. HTML elements provide one level of meaning: a widely accepted description of a document’s underlying structure. It’s only with the mutual agreement of browser vendors and developers that <p> indicates a paragraph. Yet (with the exception of widely accepted microdata and microformat schemas) only HTML elements convey any meaning that can be parsed consistently by user agents. While using semantic values for class names is a noble endeavour, they provide no additional information to the visitor of a website; take them away and a document will have exactly the same semantic value. I didn’t always think this was the case, but the real world has a habit of changing your opinion. Much of my thinking around semantics has been informed by the writing of my peers. In “About HTML semantics and front-end architecture”, Nicholas Gallagher wrote: The important thing for class name semantics in non-trivial applications is that they be driven by pragmatism and best serve their primary purpose – providing meaningful, flexible, and reusable presentational/behavioural hooks for developers to use. These thoughts are echoed by Harry Roberts in his CSS Guidelines: The debate surrounding semantics has raged for years, but it is important that we adopt a more pragmatic, sensible approach to naming things in order to work more efficiently and effectively. Instead of focussing on ‘semantics’, look more closely at sensibility and longevity – choose names based on ease of maintenance, not for their perceived meaning. Naming methodologies Front-end development has undergone a revolution in recent years. As the projects we’ve worked on have grown larger and more important, our development practices have matured. The pros and cons of object-orientated approaches to CSS can be endlessly debated, yet their introduction has highlighted the usefulness of having documented naming schemes. Jonathan Snook’s SMACSS (Scalable and Modular Architecture for CSS) collects style rules into five categories: base, layout, module, state and theme. This grouping makes it clear what each rule does, and is aided by a naming convention: By separating rules into the five categories, naming convention is beneficial for immediately understanding which category a particular style belongs to and its role within the overall scope of the page. On large projects, it is more likely to have styles broken up across multiple files. In these cases, naming convention also makes it easier to find which file a style belongs to. I like to use a prefix to differentiate between layout, state and module rules. For layout, I use l- but layout- would work just as well. Using prefixes like grid- also provide enough clarity to separate layout styles from other styles. For state rules, I like is- as in is-hidden or is-collapsed. This helps describe things in a very readable way. SMACSS is more a set of suggestions than a rigid framework, so its ideas can be incorporated into your own practice. Nicholas Gallagher’s SUIT CSS project is far more strict in its naming conventions: SUIT CSS relies on structured class names and meaningful hyphens (i.e., not using hyphens merely to separate words). This helps to work around the current limits of applying CSS to the DOM (i.e., the lack of style encapsulation), and to better communicate the relationships between classes. Over the last year, I’ve favoured a BEM-inspired approach to CSS. BEM stands for block, element, modifier, which describes the three types of rule that contribute to the style of a single component. This means that, given the following markup: <ul class=“sleigh”> <li class=“sleigh__reindeer sleigh__reindeer––famous”>Rudolph</li> <li class=“sleigh__reindeer”>Dasher</li> <li class=“sleigh__reindeer”>Dancer</li> <li class=“sleigh__reindeer”>Prancer</li> <li class=“sleigh__reindeer”>Vixen</li> <li class=“sleigh__reindeer”>Comet</li> <li class=“sleigh__reindeer”>Cupid</li> <li class=“sleigh__reindeer”>Dunder</li> <li class=“sleigh__reindeer”>Blixem</li> </ul> I know that: .sleigh is a containing block or component. .sleigh__reindeer is used only as a descendent element of .sleigh. .sleigh__reindeer––famous is used only as a modifier of .sleigh__reindeer. With this naming scheme in place, I know which styles relate to a particular component, and which are shared. Beyond reducing specificity-related head-scratching, this approach has given me a framework within which I can consistently label items, and has sped up my workflow considerably. Each of these methodologies shows that any robust CSS naming convention will have clear rules around case (lowercase, camelCase, PascalCase) and the use of special (allowed) characters like hyphens and underscores. What makes for a good name? Regardless of higher-level conventions, there’s no getting away from the fact that, at some point, we’re still going to have to name things. Recognising that classes should be named with other developers in mind, what makes for a good name? Understandable The most important aspect is for a name to be understandable. Words used in your project may come from a variety of sources: some may be widely understood, and others only be recognised by people working within a particular environment. Culture Most words you’ll choose will have common currency outside the world of web development, although they may have a particular interpretation among developers (think menu, list, input). However, words may have a narrower cultural significance; for example, in Germany and other German-speaking countries, impressum is the term used for legally mandated statements of ownership. Industry Industries often use specific terms to describe common business practices and concepts. Publishing has a number of these (headline, standfirst, masthead, colophon…) all have well understood meanings – and not all of them are relevant to online usage. Organisation Companies may have internal names (or nicknames) for their products and services. The Guardian is rife with such names: bisons (and buffalos), pixies (and super-pixies), bentos (and mini-bentos)… all of which mean something very different outside the organisation. Although such names can be useful inside smaller teams, in larger organisations they can become a barrier to entry, a sort of secret code used among employees who have been around long enough to know what they mean. Product Your team will undoubtedly have created names for specific features or interface components used in your product. For example, at Clearleft we coined the term gravigation for a navigation bar that was pinned to the bottom of the viewport. Elements of a visual design language may have names, too. Transport for London’s bar and circle logo is known internally as the roundel, while Nike’s logo is called the swoosh. Branding agencies often christen colours within a brand palette, too, either to evoke aspects of the identity or to indicate intended usage. Once you recognise the origin of the words you use, you’ll be better able to judge their appropriateness. Using Latin words for class names may satisfy a need to use semantic-sounding terms but, unless you work in a company whose employees have a basic grasp of Latin, a degree of translation will be required. Military ranks might be a clever way of declaring sizes without implying actual values, but I’d venture most people outside the armed forces don’t know how they’re ordered. Obvious Quite often, the first name that comes into your head will be the best option. Names that obliquely reference the function of a class (e.g. receptacle instead of container, kevlar instead of no-bullets) only serve to add an additional layer of abstraction. Don’t overthink it! One way of knowing if the names you use are well understood is to look at what similar concepts are called in existing vocabularies. schema.org, Dublin Core and the BBC’s ontologies are all useful sources for object names. Functional While we’ve learned to avoid using presentational classes, there remains a tension between naming things based on their content, and naming them for their intended presentation or behaviour (which may change at different breakpoints). Rather than think about a component’s appearance or behaviour, instead look to its function, its purpose. To clarify, ask what a component’s function is, and not how the component functions. For example, the Guardian’s internal content system uses the following names for different types of image placement: supporting, showcase and thumbnail, with inline being the default. These options make no promise of the resulting position on a webpage (or smartphone app, or television screen…), but do suggest intended use, and therefore imply the likely presentation. Consistent Being consistent in your approach to names will allow for easier naming of successive components, and extending the vocabulary when necessary. For example, a predictably named hierarchy might use names like primary and secondary. Should another level need to be added, tertiary is clearly be preferred over third. Appropriate Your project will feature a mix of style rules. Some will perform utility functions (clearing floats, removing bullets from a list, reseting margins), while others will perform specific functions used only once or twice in a project. Names should reflect this. For commonly used classes, be generic; for unique components be more specific. It’s also worth remembering that you can use multiple classes on an element, so combining both generic and specific can give you a powerful modular design system: Generic: list Specific: naughty-children Combined: naughty-children list If following the BEM methodology, you might use the following classes: Generic: list Specific: list––nice-children Combined: list list––nice-children Extensible Good naming schemes can be extended. One way of achieving this is to use namespaces, which are basically a way of grouping related names under a higher-level term. Microformats are a good example of a well-designed naming scheme, with many of its vocabularies taking property names from existing and related specifications (e.g. hCard is a 1:1 representation of vCard). Microformats 2 goes one step further by grouping properties under several namespaces: h-* for root class names (e.g. h-card) p-* for simple (text) properties (e.g. p-name) u-* for URL properties (e.g. u-photo) dt-* for date/time properties (e.g. dt-bday) e-* for embedded markup properties (e.g. e-note) The inclusion of namespaces is a massive improvement over the earlier specification, but the downside is that microformats now occupy five separate namespaces. This might be problematic if you are using u-* for your utility classes. While nothing will break, your naming system won’t be as robust, so plan accordingly. (Note: Microformats perform a very specific function, separate from any presentational concerns. It’s therefore considered best practice to not use microformat classes as styling hooks, but instead use additional classes that relate to the function of the component and adhere to your own naming conventions.) Short Names should be as long as required, but no longer. When looking for words to describe a particular function, I try to look for single words where possible. Avoid abbreviations unless they are understood within the contexts described above. rrp is fine if labelling a recommended retail price in an online shop, but not very helpful if used to mean ragged-right paragraph, for example. Fun! Finally, names can be an opportunity to have some fun! Names can give character to a project, be it by providing an outlet for in-jokes or adding little easter eggs for those inclined to look. The copyright statement on Apple’s website has long been named sosumi, a word that has a nice little history inside Apple. Until recently, the hamburger menu icon on the Guardian website was labelled honest-burger, after the developer’s favourite burger restaurant. A few thoughts on preprocessors CSS preprocessors have solved a lot of problems, but they have an unfortunate downside: they require you to name yet more things! Whereas we needed to worry only about style rules, now we need names for variables, mixins, functions… oh my! A second article could be written about naming these, so for now I’ll offer just a few thoughts. The first is to note that preprocessors make it easier to change things, as they allow for DRYer code. So while the names of variables are important (and the advice in this article still very much applies), you can afford to relax a little. Looking to name colour variables? If possible, find out if colours have been assigned names in a brand palette. If not, use obvious names (based on appearance or function, depending on your preference) and adapt as the palette grows. If it becomes difficult to name colours that are too similar, I’d venture that the problem lies with the design rather than the naming scheme. The same is true for responsive breakpoints. Preprocessors allow you to move awkward naming conventions out of the markup and into the CSS. Although terms like mobile, tablet and desktop are not desirable given the need to think about device-agnostic design, if these terms are widely understood within a product team and among stakeholders, using them will ensure everyone is using the same language (they can always be changed later). It still feels like we’re at the very beginning of understanding how preprocessors fit into a development workflow, if at all! I suspect over the next few years, best practices will emerge for all of these considerations. In the meantime, use your brain! Even with sensible rules and conventions in place, naming things can remain difficult, but hopefully I’ve made this exercise a little less painful. Christmas is a time of giving, so to the developer reading your code in a year’s time, why not make your gift one of clearer class names. 2014 Paul Lloyd paulrobertlloyd 2014-12-21T00:00:00+00:00 https://24ways.org/2014/naming-things/ code
58 Beyond the Style Guide Much like baking a Christmas cake, designing for the web involves creating an experience in layers. Starting with a solid base that provides the core experience (the fruit cake), we can add further layers, each adding refinement (the marzipan) and delight (the icing). Don’t worry, this isn’t a misplaced cake recipe, but an evaluation of modular design and the role style guides can play in acknowledging these different concerns, be they presentational or programmatic. The auteur’s style guide Although trained as a graphic designer, it was only when I encountered the immediacy of the web that I felt truly empowered as a designer. Given a desire to control every aspect of the resulting experience, I slowly adopted the role of an auteur, exploring every part of the web stack: front-end to back-end, and everything in between. A few years ago, I dreaded using the command line. Today, the terminal is a permanent feature in my Dock. In straddling the realms of graphic design and programming, it’s the point at which they meet that I find most fascinating, with each dicipline valuing the creation of effective systems, be they for communication or code efficiency. Front-end style guides live at this intersection, demonstrating both the modularity of code and the application of visual design. Painting by numbers In our rush to build modular systems, design frameworks have grown in popularity. While enabling quick assembly, these come at the cost of originality and creative expression – perhaps one reason why we’re seeing the homogenisation of web design. In editorial design, layouts should accentuate content and present it in an engaging manner. Yet on the web we see a practice that seeks templated predictability. In ‘Design Machines’ Travis Gertz argued that (emphasis added): Design systems still feel like a novelty in screen-based design. We nerd out over grid systems and modular scales and obsess over style guides and pattern libraries. We’re pretty good at using them to build repeatable components and site-wide standards, but that’s sort of where it ends. […] But to stop there is to ignore the true purpose and potential of a design system. Unless we consider how interface patterns fully embrace the design systems they should be built upon, style guides may exacerbate this paint-by-numbers approach, encouraging conformance and suppressing creativity. Anatomy of a button Let’s take a look at that most canonical of components, the button, and consider what we might wish to document and demonstrate in a style guide. The different layers of our button component. Content The most variable aspect of any component. Content guidelines will exert the most influence here, dictating things like tone of voice (whether we should we use stiff, formal language like ‘Submit form’, or adopt a more friendly tone, perhaps ‘Send us your message’) and appropriate language. For an internationalised interface, this may also impact word length and text direction or orientation. Structure HTML provides a limited vocabulary which we can use to structure content and add meaning. For interactive elements, the choice of element can also affect its behaviour, such as whether a button submits form data or links to another page: <button type="submit">Button text</button> <a href="/index.html">Button text</a> Note: One of the reasons I prefer to use <button> instead of <input type=“button”>, besides allowing the inclusion of content other than text, is that it has a markup structure similar to links, therefore keeping implementation differences to a minimum. We should also think about each component within the broader scope of our particular product. For this we can employ a further vocabulary, which can be expressed by adding values to the class attribute. For a newspaper, we might use names like lede, standfirst and headline, while a social media application might see us reach for words like stream, action or avatar. Presentation The appearance of a component can never be considered in isolation. Informed by its relationship to other elements, style guides may document different stylistic variations of a component, even if the underlying function remains unchanged: primary and secondary button styles, for example. Behaviour A component can exhibit various states: blank, loading, partial, error and ideal, and a style guide should reflect that. Our button component is relatively simple, yet even here we need to consider hover, focused, active and disabled states. Transcending layers This overview reinforces Ethan’s note from earlier in this series: I’ve found that thinking about my design as existing in broad experience tiers – in layers – is one of the best ways of designing for the modern web. While it’s tempting to describe a component as series of layers, certain aspects will transcend several of these. The accessibility of a component, for example, may influence the choice of language, the legibility of text, colour contrast and which affordances are provided in different states. Visual design language: documenting the missing piece Even given this small, self-contained component, we can see several concerns at play, and in reviewing our button it seems we have most things covered. However, a few questions remain unanswered. Why does it have a blue background? Why are the borders 2px thick, with a radius of 4px? Why are we using that font, at that size and with that weight? These questions can be answered by our visual design language. More than a set of type choices and colour palettes, a design language can dicate common measures, ratios and the resulting grid(s) these influence. Ideally governed by a set of broader design principles, it can also inform an illustration style, the type of photography sourced or commissioned, and the behaviour of any animations. Whereas a style guide ensures conformity, having it underpinned by an effective design language will allow for flexibility; only by knowing the rules can you know how to break them! Type pairings in the US Web Design Standards guide. For a style guide to thoroughly articulate a visual design system, the spectrum of choices it allows for should be acknowledged. A fantastic example of this can be found in the US Web Design Standards. By virtue of being a set of standards designed to apply to a number of different sites, this guide offers a range of type pairings (that take into account performance considerations) and provides primary, secondary and tertiary palette relationships, with shades and tones thereof: Colour palettes in the US Web Design Standards guide. A visual language in code form Properly documenting our design language in a style guide is a good start, yet even better if it can be expressed in code. This is where CSS preprocessors become a powerful ally. In Sass, methods like mixins and maps can help us represent relationships between values. Variables (and CSS variables) extend the vocabulary provided natively by CSS, meaning we can describe patterns in terms of our own visual language. These tools effectively become an interface to our design system. Furthermore, they help maintain a separation of concerns, with visual presentation remaining where it should be: in our style sheets. Take this simple example, an article summary on a website counting down the best Christmas movies: The design for our simple component example. Our markup is as follows, using appropriate semantic HTML elements and incorporating the vocabulary from our collection of design patterns (expressed using the BEM methodology): <article class="summary"> <h1 class="summary__title"> <a href="scrooged.html"> <span class="summary__position">12</span> Scrooged (1988) </a> </h1> <div class="summary__body"> <p>It’s unlikely that Bill Murray could ever have got through his career without playing a version of Scrooge…</p> </div> <footer class="summary__meta"> <strong>Director:</strong> Richard Donner<br/> <strong>Stars:</strong> Bill Murray, Buddy Hackett, Karen Allen </footer> </article> We can then describe the presentation of this HTML by using Sass maps to define our palettes, mixins to include predefined font metrics, and variables to recall common measurements: .summary { margin-bottom: ($baseline * 4) } .summary__title { @include font-family(display-serif); @include font-size(title); color: palette(neutral, dark); margin-bottom: ($baseline * 4); border-top: $rule-height solid palette(primary, purple); padding-top: ($baseline * 2); } .summary__position { @include font-family(display-sans, 300); color: palette(neutral, mid); } .summary__body { @include font-family(text-serif); @include font-size(body); margin-bottom: ($baseline * 2); } .summary__meta { @include font-family(text-sans); @include font-size(caption); } Of course, this is a simplistic example for the purposes of demonstration. However, such thinking was employed at a much larger scale at the Guardian. Using a set of Sass components, complex patterns could be described using a language familar to everyone on the product team, be they a designer, developer or product owner: The design of a component on the Guardian website, described in terms of its Sass-powered design system. Unlocking possibility Alongside tools like preprocessors, newer CSS layout modules like flexbox and grid layout mean the friction we’ve long been accustomed to when creating layouts on the web is no longer present, and the full separation of presentation from markup is now possible. Now is the perfect time for graphic designers to advocate design systems that these developments empower, and ensure they’re fully represented in both documentation and code. That way, together, we can build systems that allow for greater visual expression. After all, there’s more than one way to bake a Christmas cake. 2015 Paul Lloyd paulrobertlloyd 2015-12-16T00:00:00+00:00 https://24ways.org/2015/beyond-the-style-guide/ design
79 Responsive Images: What We Thought We Needed If you were to read a web designer’s Christmas wish list, it would likely include a solution for displaying images responsively. For those concerned about users downloading unnecessary image data, or serving images that look blurry on high resolution displays, finding a solution has become a frustrating quest. Having experimented with complex and sometimes devilish hacks, consensus is forming around defining new standards that could solve this problem. Two approaches have emerged. The <picture> element markup pattern was proposed by Mat Marquis and is now being developed by the Responsive Images Community Group. By providing a means of declaring multiple sources, authors could use media queries to control which version of an image is displayed and under what conditions: <picture width="500" height="500"> <source media="(min-width: 45em)" src="large.jpg"> <source media="(min-width: 18em)" src="med.jpg"> <source src="small.jpg"> <img src="small.jpg" alt=""> <p>Accessible text</p> </picture> A second proposal put forward by Apple, the srcset attribute, uses a more concise syntax intended for use with the <img> element, although it could be compatible with the <picture> element too. This would allow authors to provide a set of images, but with the decision on which to use left to the browser: <img src="fallback.jpg" alt="" srcset="small.jpg 640w 1x, small-hd.jpg 640w 2x, med.jpg 1x, med-hd.jpg 2x "> Enter Scrooge Men’s courses will foreshadow certain ends, to which, if persevered in, they must lead. Ebenezer Scrooge Given the complexity of this issue, there’s a heated debate about which is the best option. Yet code belies a certain truth. That both feature verbose and opaque syntax, I’m not sure either should find its way into the browser – especially as alternative approaches have yet to be fully explored. So, as if to dampen the festive cheer, here are five reasons why I believe both proposals are largely redundant. 1. We need better formats, not more markup As we move away from designs defined with fixed pixel values, bitmap images look increasingly unsuitable. While simple images and iconography can use scalable vector formats like SVG, for detailed photographic imagery, raster formats like GIF, PNG and JPEG remain the only suitable option. There is scope within current formats to account for varying bandwidth but this requires cooperation from browser vendors. Newer formats like JPEG2000 and WebP generate higher quality images with smaller file sizes, but aren’t widely supported. While it’s tempting to try to solve this issue by inventing new markup, the crux of it remains at the file level. Daan Jobsis’s experimentation with image compression strengthens this argument. He discovered that by increasing the dimensions of a JPEG image while simultaneously reducing its quality, a smaller files could be produced, with the resulting image looking just as good on both standard and high-resolution displays. This may be a hack in lieu of a more permanent solution, but it’s applied in the right place. Easy to accomplish with existing tools and without compatibility issues, it has few downsides. Further experimentation in this area should be encouraged, with standardisation efforts more helpful if focused on developing new image formats or, preferably, extending existing ones. 2. Art direction doesn’t belong in markup A desired benefit of the <picture> markup pattern is to allow for greater art direction. For example, rather than scaling down images on smaller displays to the point that their content is hard to discern, we could present closer crops instead: This can be achieved with CSS of course, although with a download penalty for those parts of an image not shown. This point may be negligible, however, since in the context of adaptable layouts, these hidden areas may end up being revealed anyway. Art direction concerns design, not content. If we wish to maintain a separation of concerns, including presentation within our markup seems misguided. 3. The size of a display has little relation to the size of an image By using media queries, the <picture> element allows authors to choose which characteristics of the screen or viewport to query for different images to be displayed. In developing sites at Clearleft, we have noticed that the viewport is essentially arbitrary, with the size of an image’s containing element more important. For example, look at how this grid of images may adapt at different viewport widths: As we build more modular systems, components need to be adaptable in and of themselves. There is a case to be made for developing more contextual methods of querying, rather than those based on attributes of the display. 4. We haven’t lived with the problem long enough A key strength of the web is that the underlying platform can be continually iterated. This can also be problematic if snap judgements are made about what constitutes an improvement. The early history of the web is littered with such examples, be it the perceived need for blinking text or inline typographic styling. To build a platform for the future, additions to it should be carefully considered. And if we want more consistent support across browsers, burdening vendors with an ever increasing list of features seems counterproductive. Only once the need for a new feature is sufficiently proven, should we look to standardise it. Before we could declare hover effects, rounded corners and typographic styling in CSS, we used JavaScript as a polyfill. Sure, doing so was painful, but use cases were fully explored, and the CSS specification better reflected the needs of authors. 5. Images and the web aesthetic The srcset proposal has emerged from a company that markets its phones as being able to browse the real – yet squashed down, tapped and zoomable – web. Perhaps Apple should make its own website responsive before suggesting how the rest of us should do so. Converserly, while the <picture> proposal has the backing of a few respected developers and designers, it was born out of the work Mat Marquis and Filament Group did for the Boston Globe. As the first large-scale responsive design, this was a landmark project that ignited the responsive web design movement and proved its worth. But it was the first. Its design shares a vernacular to that of contemporary newspaper websites, with a columnar, image-laden and densely packed layout. Compared to more recent examples – Quartz, The Next Web and the New York Times Skimmer – it feels out of step with the future direction of news sites. In seeking out a truer aesthetic for the web in which software interfaces have greater influence, we might discover that the need for responsive images isn’t as great as originally thought. Building for the future With responsive design, we’ve accepted the idea that a fully fluid layout, rather than a set of fixed layouts, is best suited to the web’s unpredictable nature. Current responsive image proposals are antithetical to this approach. We need solutions that lack complexity, are device-agnostic and work within existing workflows. Any proposal that requires different versions of the same image to be created, is likely to have to acquiesce under the pressure of reality. While it’s easy to get distracted about the size and quality of an image, and how we might choose to serve it, often the simplest solution is not to include it at all. After years of gluttonous design practice, in which fast connections and expansive display sizes were an accepted norm, we have got use to filling pages with needless images and countless items of page furniture. To design more adaptable experiences, the presence of every element needs to be questioned, for its existence requires additional data to be downloaded or futher complexity within a design system. Conditional loading techniques mean that the inclusion of images is no longer a binary choice, but can instead appear in a progressively enhanced manner. So here is my proposal. Instead of spending the next year worrying about responsive images, let’s embrace the constraints of the medium, and seek out new solutions that can work within them. 2012 Paul Lloyd paulrobertlloyd 2012-12-11T00:00:00+00:00 https://24ways.org/2012/responsive-images-what-we-thought-we-needed/ code
252 Turn Jekyll up to Eleventy Sometimes it pays not to over complicate things. While many of the sites we use on a daily basis require relational databases to manage their content and dynamic pages to respond to user input, for smaller, simpler sites, serving pre-rendered static HTML is usually a much cheaper — and more secure — option. The JAMstack (JavaScript, reusable APIs, and prebuilt Markup) is a popular marketing term for this way of building websites, but in some ways it’s a return to how things were in the early days of the web, before developers started tinkering with CGI scripts or Personal HomePage. Indeed, my website has always served pre-rendered HTML; first with the aid of Movable Type and more recently using Jekyll, which Anna wrote about in 2013. By combining three approachable languages — Markdown for content, YAML for data and Liquid for templating — the ergonomics of Jekyll found broad appeal, influencing the design of the many static site generators that followed. But Jekyll is not without its faults. Aside from notoriously slow build times, it’s also built using Ruby. While this is an elegant programming language, it is yet another ecosystem to understand and manage, and often alongside one we already use: JavaScript. For all my time using Jekyll, I would think to myself “this, but in Node”. Thankfully, one of Santa’s elves (Zach Leatherman) granted my Atwoodian wish and placed such a static site generator under my tree. Introducing Eleventy Eleventy is a more flexible alternative Jekyll. Besides being written in Node, it’s less strict about how to organise files and, in addition to Liquid, supports other templating languages like EJS, Pug, Handlebars and Nunjucks. Best of all, its build times are significantly faster (with future optimisations promising further gains). As content is saved using the familiar combination of YAML front matter and Markdown, transitioning from Jekyll to Eleventy may seem like a reasonable idea. Yet as I’ve discovered, there are a few gotchas. If you’ve been considering making the switch, here are a few tips and tricks to help you on your way1. Note: Throughout this article, I’ll be converting Matt Cone’s Markdown Guide site as an example. If you want to follow along, start by cloning the git repository, and then change into the project directory: git clone https://github.com/mattcone/markdown-guide.git cd markdown-guide Before you start If you’ve used tools like Grunt, Gulp or Webpack, you’ll be familiar with Node.js but, if you’ve been exclusively using Jekyll to compile your assets as well as generate your HTML, now’s the time to install Node.js and set up your project to work with its package manager, NPM: Install Node.js: Mac: If you haven’t already, I recommend installing Homebrew, a package manager for the Mac. Then in the Terminal type brew install node. Windows: Download the Windows installer from the Node.js website and follow the instructions. Initiate NPM: Ensure you are in the directory of your project and then type npm init. This command will ask you a few questions before creating a file called package.json. Like RubyGems’s Gemfile, this file contains a list of your project’s third-party dependencies. If you’re managing your site with Git, make sure to add node_modules to your .gitignore file too. Unlike RubyGems, NPM stores its dependencies alongside your project files. This folder can get quite large, and as it contains binaries compiled to work with the host computer, it shouldn’t be version controlled. Eleventy will also honour the contents of this file, meaning anything you want Git to ignore, Eleventy will ignore too. Installing Eleventy With Node.js installed and your project setup to work with NPM, we can now install Eleventy as a dependency: npm install --save-dev @11ty/eleventy If you open package.json you should see the following: … "devDependencies": { "@11ty/eleventy": "^0.6.0" } … We can now run Eleventy from the command line using NPM’s npx command. For example, to covert the README.md file to HTML, we can run the following: npx eleventy --input=README.md --formats=md This command will generate a rendered HTML file at _site/README/index.html. Like Jekyll, Eleventy shares the same default name for its output directory (_site), a pattern we will see repeatedly during the transition. Configuration Whereas Jekyll uses the declarative YAML syntax for its configuration file, Eleventy uses JavaScript. This allows its options to be scripted, enabling some powerful possibilities as we’ll see later on. We’ll start by creating our configuration file (.eleventy.js), copying the relevant settings in _config.yml over to their equivalent options: module.exports = function(eleventyConfig) { return { dir: { input: "./", // Equivalent to Jekyll's source property output: "./_site" // Equivalent to Jekyll's destination property } }; }; A few other things to bear in mind: Whereas Jekyll allows you to list folders and files to ignore under its exclude property, Eleventy looks for these values inside a file called .eleventyignore (in addition to .gitignore). By default, Eleventy uses markdown-it to parse Markdown. If your content uses advanced syntax features (such as abbreviations, definition lists and footnotes), you’ll need to pass Eleventy an instance of this (or another) Markdown library configured with the relevant options and plugins. Layouts One area Eleventy currently lacks flexibility is the location of layouts, which must reside within the _includes directory (see this issue on GitHub). Wanting to keep our layouts together, we’ll move them from _layouts to _includes/layouts, and then update references to incorporate the layouts sub-folder. We could update the layout: frontmatter property in each of our content files, but another option is to create aliases in Eleventy’s config: module.exports = function(eleventyConfig) { // Aliases are in relation to the _includes folder eleventyConfig.addLayoutAlias('about', 'layouts/about.html'); eleventyConfig.addLayoutAlias('book', 'layouts/book.html'); eleventyConfig.addLayoutAlias('default', 'layouts/default.html'); return { dir: { input: "./", output: "./_site" } }; } Determining which template language to use Eleventy will transform Markdown (.md) files using Liquid by default, but we’ll need to tell Eleventy how to process other files that are using Liquid templates. There are a few ways to achieve this, but the easiest is to use file extensions. In our case, we have some files in our api folder that we want to process with Liquid and output as JSON. By appending the .liquid file extension (i.e. basic-syntax.json becomes basic-syntax.json.liquid), Eleventy will know what to do. Variables On the surface, Jekyll and Eleventy appear broadly similar, but as each models its content and data a little differently, some template variables will need updating. Site variables Alongside build settings, Jekyll let’s you store common values in its configuration file which can be accessed in our templates via the site.* namespace. For example, in our Markdown Guide, we have the following values: title: "Markdown Guide" url: https://www.markdownguide.org baseurl: "" repo: http://github.com/mattcone/markdown-guide comments: false author: name: "Matt Cone" og_locale: "en_US" Eleventy’s configuration uses JavaScript which is not suited to storing values like this. However, like Jekyll, we can use data files to store common values. If we add our site-wide values to a JSON file inside a folder called _data and name this file site.json, we can keep the site.* namespace and leave our variables unchanged. { "title": "Markdown Guide", "url": "https://www.markdownguide.org", "baseurl": "", "repo": "http://github.com/mattcone/markdown-guide", "comments": false, "author": { "name": "Matt Cone" }, "og_locale": "en_US" } Page variables The table below shows a mapping of common page variables. As a rule, frontmatter properties are accessed directly, whereas derived metadata values (things like URLs, dates etc.) get prefixed with the page.* namespace: Jekyll Eleventy page.url page.url page.date page.date page.path page.inputPath page.id page.outputPath page.name page.fileSlug page.content content page.title title page.foobar foobar When iterating through pages, frontmatter values are available via the data object while content is available via templateContent: Jekyll Eleventy item.url item.url item.date item.date item.path item.inputPath item.name item.fileSlug item.id item.outputPath item.content item.templateContent item.title item.data.title item.foobar item.data.foobar Ideally the discrepancy between page and item variables will change in a future version (see this GitHub issue), making it easier to understand the way Eleventy structures its data. Pagination variables Whereas Jekyll’s pagination feature is limited to paginating posts on one page, Eleventy allows you to paginate any collection of documents or data. Given this disparity, the changes to pagination are more significant, but this table shows a mapping of equivalent variables: Jekyll Eleventy paginator.page pagination.pageNumber paginator.per_page pagination.size paginator.posts pagination.items paginator.previous_page_path pagination.previousPageHref paginator.next_page_path pagination.nextPageHref Filters Although Jekyll uses Liquid, it provides a set of filters that are not part of the core Liquid library. There are quite a few — more than can be covered by this article — but you can replicate them by using Eleventy’s addFilter configuration option. Let’s convert two used by our Markdown Guide: jsonify and where. The jsonify filter outputs an object or string as valid JSON. As JavaScript provides a native JSON method, we can use this in our replacement filter. addFilter takes two arguments; the first is the name of the filter and the second is the function to which we will pass the content we want to transform: // {{ variable | jsonify }} eleventyConfig.addFilter('jsonify', function (variable) { return JSON.stringify(variable); }); Jekyll’s where filter is a little more complicated in that it takes two additional arguments: the key to look for, and the value it should match: {{ site.members | where: "graduation_year","2014" }} To account for this, instead of passing one value to the second argument of addFilter, we can instead pass three: the array we want to examine, the key we want to look for and the value it should match: // {{ array | where: key,value }} eleventyConfig.addFilter('where', function (array, key, value) { return array.filter(item => { const keys = key.split('.'); const reducedKey = keys.reduce((object, key) => { return object[key]; }, item); return (reducedKey === value ? item : false); }); }); There’s quite a bit going on within this filter, but I’ll try to explain. Essentially we’re examining each item in our array, reducing key (passed as a string using dot notation) so that it can be parsed correctly (as an object reference) before comparing its value to value. If it matches, item remains in the returned array, else it’s removed. Phew! Includes As with filters, Jekyll provides a set of tags that aren’t strictly part of Liquid either. This includes one of the most useful, the include tag. LiquidJS, the library Eleventy uses, does provide an include tag, but one using the slightly different syntax defined by Shopify. If you’re not passing variables to your includes, everything should work without modification. Otherwise, note that whereas with Jekyll you would do this: <!-- page.html --> {% include include.html value="key" %} <!-- include.html --> {{ include.value }} in Eleventy, you would do this: <!-- page.html --> {% include "include.html", value: "key" %} <!-- include.html --> {{ value }} A downside of Shopify’s syntax is that variable assignments are no longer scoped to the include and can therefore leak; keep this in mind when converting your templates as you may need to make further adjustments. Tweaking Liquid You may have noticed in the above example that LiquidJS expects the names of included files to be quoted (else it treats them as variables). We could update our templates to add quotes around file names (the recommended approach), but we could also disable this behaviour by setting LiquidJS’s dynamicPartials option to false. Additionally, Eleventy doesn’t support the include_relative tag, meaning you can’t include files relative to the current document. However, LiquidJS does let us define multiple paths to look for included files via its root option. Thankfully, Eleventy allows us to pass options to LiquidJS: eleventyConfig.setLiquidOptions({ dynamicPartials: false, root: [ '_includes', '.' ] }); Collections Jekyll’s collections feature lets authors create arbitrary collections of documents beyond pages and posts. Eleventy provides a similar feature, but in a far more powerful way. Collections in Jekyll In Jekyll, creating collections requires you to add the name of your collections to _config.yml and create corresponding folders in your project. Our Markdown Guide has two collections: collections: - basic-syntax - extended-syntax These correspond to the folders _basic-syntax and _extended-syntax whose content we can iterate over like so: {% for syntax in site.extended-syntax %} {{ syntax.title }} {% endfor %} Collections in Eleventy There are two ways you can set up collections in 11ty. The first, and most straightforward, is to use the tag property in content files: --- title: Strikethrough syntax-id: strikethrough syntax-summary: "~~The world is flat.~~" tag: extended-syntax --- We can then iterate over tagged content like this: {% for syntax in collections.extended-syntax %} {{ syntax.data.title }} {% endfor %} Eleventy also allows us to configure collections programmatically. For example, instead of using tags, we can search for files using a glob pattern (a way of specifying a set of filenames to search for using wildcard characters): eleventyConfig.addCollection('basic-syntax', collection => { return collection.getFilteredByGlob('_basic-syntax/*.md'); }); eleventyConfig.addCollection('extended-syntax', collection => { return collection.getFilteredByGlob('_extended-syntax/*.md'); }); We can extend this further. For example, say we wanted to sort a collection by the display_order property in our document’s frontmatter. We could take the results of collection.getFilteredByGlob and then use JavaScript’s sort method to sort the result: eleventyConfig.addCollection('example', collection => { return collection.getFilteredByGlob('_examples/*.md').sort((a, b) => { return a.data.display_order - b.data.display_order; }); }); Hopefully, this gives you just a hint of what’s possible using this approach. Using directory data to manage defaults By default, Eleventy will maintain the structure of your content files when generating your site. In our case, that means /_basic-syntax/lists.md is generated as /_basic-syntax/lists/index.html. Like Jekyll, we can change where files are saved using the permalink property. For example, if we want the URL for this page to be /basic-syntax/lists.html we can add the following: --- title: Lists syntax-id: lists api: "no" permalink: /basic-syntax/lists.html --- Again, this is probably not something we want to manage on a file-by-file basis but again, Eleventy has features that can help: directory data and permalink variables. For example, to achieve the above for all content stored in the _basic-syntax folder, we can create a JSON file that shares the name of that folder and sits inside it, i.e. _basic-syntax/_basic-syntax.json and set our default values. For permalinks, we can use Liquid templating to construct our desired path: { "layout": "syntax", "tag": "basic-syntax", "permalink": "basic-syntax/{{ title | slug }}.html" } However, Markdown Guide doesn’t publish syntax examples at individual permanent URLs, it merely uses content files to store data. So let’s change things around a little. No longer tied to Jekyll’s rules about where collection folders should be saved and how they should be labelled, we’ll move them into a folder called _content: markdown-guide └── _content ├── basic-syntax ├── extended-syntax ├── getting-started └── _content.json We will also add a directory data file (_content.json) inside this folder. As directory data is applied recursively, setting permalink to false will mean all content in this folder and its children will no longer be published: { "permalink": false } Static files Eleventy only transforms files whose template language it’s familiar with. But often we may have static assets that don’t need converting, but do need copying to the destination directory. For this, we can use pass-through file copy. In our configuration file, we tell Eleventy what folders/files to copy with the addPassthroughCopy option. Then in the return statement, we enable this feature by setting passthroughFileCopy to true: module.exports = function(eleventyConfig) { … // Copy the `assets` directory to the compiled site folder eleventyConfig.addPassthroughCopy('assets'); return { dir: { input: "./", output: "./_site" }, passthroughFileCopy: true }; } Final considerations Assets Unlike Jekyll, Eleventy provides no support for asset compilation or bundling scripts — we have plenty of choices in that department already. If you’ve been using Jekyll to compile Sass files into CSS, or CoffeeScript into Javascript, you will need to research alternative options, options which are beyond the scope of this article, sadly. Publishing to GitHub Pages One of the benefits of Jekyll is its deep integration with GitHub Pages. To publish an Eleventy generated site — or any site not built with Jekyll — to GitHub Pages can be quite involved, but typically involves copying the generated site to the gh-pages branch or including that branch as a submodule. Alternatively, you could use a continuous integration service like Travis or CircleCI and push the generated site to your web server. It’s enough to make your head spin! Perhaps for this reason, a number of specialised static site hosts have emerged such as Netlify and Google Firebase. But remember; you can publish a static site almost anywhere! Going one louder If you’ve been considering making the switch, I hope this brief overview has been helpful. But it also serves as a reminder why it can be prudent to avoid jumping aboard bandwagons. While it’s fun to try new software and emerging technologies, doing so can require a lot of work and compromise. For all of Eleventy’s appeal, it’s only a year old so has little in the way of an ecosystem of plugins or themes. It also only has one maintainer. Jekyll on the other hand is a mature project with a large community of maintainers and contributors supporting it. I moved my site to Eleventy because the slowness and inflexibility of Jekyll was preventing me from doing the things I wanted to do. But I also had time to invest in the transition. After reading this guide, and considering the specific requirements of your project, you may decide to stick with Jekyll, especially if the output will essentially stay the same. And that’s perfectly fine! But these go to 11. Information provided is correct as of Eleventy v0.6.0 and Jekyll v3.8.5 ↩ 2018 Paul Lloyd paulrobertlloyd 2018-12-11T00:00:00+00:00 https://24ways.org/2018/turn-jekyll-up-to-eleventy/ content
266 Collaborative Development for a Responsively Designed Web In responsive web design we’ve found a technique that allows us to design for the web as a medium in its own right: one that presents a fluid, adaptable and ever changing canvas. Until this point, we gave little thought to the environment in which users will experience our work, caring more about the aggregate than the individual. The applications we use encourage rigid layouts, whilst linear processes focus on clients signing off paintings of websites that have little regard for behaviour and interactions. The handover of pristine, pixel-perfect creations to developers isn’t dissimilar to farting before exiting a crowded lift, leaving front-end developers scratching their heads as they fill in the inevitable gaps. If you haven’t already, I recommend reading Drew’s checklist of things to consider before handing over a design. Somehow, this broken methodology has survived for the last fifteen years or so. Even the advent of web standards has had little impact. Now, as we face an onslaught of different devices, the true universality of the web can no longer be ignored. Responsive web design is just the thin end of the wedge. Largely concerned with layout, its underlying philosophy could ignite a trend towards interfaces that adapt to any number of different variables: input methods, bandwidth availability, user preference – you name it! With such adaptability, a collaborative and iterative process is required. Ethan Marcotte, who worked with the team behind the responsive redesign of the Boston Globe website, talked about such an approach in his book: The responsive projects I’ve worked on have had a lot of success combining design and development into one hybrid phase, bringing the two teams into one highly collaborative group. Whilst their process still involved the creation of desktop-centric mock-ups, these were presented to the entire team early on, where questions about how pages might adapt and behave at different sizes were asked. Mock-ups were quickly converted into HTML prototypes, meaning further decisions could be based on usage rather than guesswork (and endless hours spent in Photoshop). Regardless of the exact process, it’s clear that the relationship between our two disciplines is more crucial than ever. Yet, historically, it seems a wedge has been driven between us – perhaps a result of segregation and waterfall-style processes – resulting in animosity. So how can we improve this relationship? Ultimately, we’ll need to adapt, but even within existing workflows we can start to overlap. Simply adjusting our attitude can effect change, and bring design and development teams closer together. Good design is constant contact. Mark Otto The way we work needs to be more open and inclusive. For example, ensuring members of the development team attend initial kick-off meetings and design workshops will not only ensure technical concerns are raised, but mean that those implementing our designs better understand the problems we’re trying to solve. It can also be useful at this stage to explain how you work and the sort of deliverables you expect to produce. This will give developers a chance to make recommendations on how these can be optimized for their own needs. You may even find opportunities to share the load. On a recent project I worked on, our development partners offered to produce the interactive prototypes needed for user testing. This allowed us to concentrate on refining the experience, whilst they were able to get a head start on building the product. While developers should be involved at the beginning of projects, it’s also important that designers are able to review and contribute to a product as it’s being built. Any handover should be done in person, and ideally you’ll have a day set aside to do so. Having additional budget available for follow-up design reviews is also recommended. Learning how to use version control tools like Subversion or Git will allow you to work within the same environment as developers, and allow you to contribute code or graphic assets directly to a project if needed. Don’t underestimate the benefits of designer and developer sitting next to each other. Subtle nuances can be explored far more easily than if they were conducted over email or phone. As Ethan writes, “‘Design’ is the means, not merely the end; the path we walk over the course of a project, the choices we make”. It’s from collaboration like this that I’ve become fond of producing visual style guides. These demonstrate typographic treatments for common markup and patterns (blockquotes, lists, pagination, basic form controls and so on). Thinking in terms of components rather than individual pages not only fits in better with how a developer will implement a site, but can also ensure your design works as a coherent whole. Despite the amount of research and design produced, when it comes to the crunch, there will always be a need for compromise. As the old saying goes, ‘fast, cheap and good – pick two.’ It’s important that you know which pieces are crucial to a design and which areas can allow for movement. Pick your battles wisely. Having an agreed set of design principles can be useful when making such decisions, as they help everyone focus on the goals of the project. The best compromises are reached when both sides understand the issues of the other. Richard Rutter Ultimately, better collaboration comes through a shared understanding of the different competencies required to build a website. Instead of viewing ourselves in terms of discrete roles, we should instead look to emphasize our range of abilities, and work with others whose skills are complementary. Perhaps somebody who actively seeks to broaden their knowledge is the mark of a professional. Seek these people out. The best developers I’ve worked with have a respect for design, probably having attempted to do some themselves! Having wrangled with a few MySQL databases myself, I certainly believe the obverse is true. While knowing HTML won’t necessarily make you a better designer, it will help you understand the issues being faced by a front-end developer and, more importantly, allow you to offer solutions or alternative approaches. So take a moment to think about how you work with developers and how you could improve your relationship with them. What are you doing to ease the path towards our collaborative future? 2011 Paul Lloyd paulrobertlloyd 2011-12-05T00:00:00+00:00 https://24ways.org/2011/collaborative-development-for-a-responsively-designed-web/ business
219 Speed Up Your Site with Delayed Content Speed remains one of the most important factors influencing the success of any website, and the first rule of performance (according to Yahoo!) is reducing the number of HTTP requests. Over the last few years we’ve seen techniques like sprites and combo CSS/JavaScript files used to reduce the number of HTTP requests. But there’s one area where large numbers of HTTP requests are still a fact of life: the small avatars attached to the comments on articles like this one. Avatars Many sites like 24 ways use a fantastic service called Gravatar to provide user images. As a user, you can sign up to Gravatar, give them your e-mail address, and upload an image to represent you. Sites can then include your image by generating a one way hash of your e-mail address and using that to build an image URL. For example, the markup for the comments on this page looks something like this: <div> <h4><a href="http://allinthehead.com/"> <img src="http://www.gravatar.com/avatar.php?gravatar_id=13734b0cb20708f79e730809c29c3c48&size=100" class="gravatar" alt="" height="100" width="100" /> Drew McLellan </a></h4> <p>This is a great article!</p> </div> The Gravatar URL contains two parts. 100 is the size in pixels of the image we want. 13734b0cb20708f79e730809c29c3c48 is an MD5 digest of Drew’s e-mail address. Using MD5 means we can request an image for a user without sharing their e-mail address with anyone who views the source of the page. So what’s wrong with avatars? The problem is that a popular article can easily get hundreds of comments, and every one of them means another image has to be individually requested from Gravatar’s servers. Each request is small and the Gravatar servers are fast but, when you add them up, it can easily add seconds to the rendering time of a page. Worse, they can delay the loading of more important assets like the CSS required to render the main content of the page. These images aren’t critical to the page, and don’t need to be loaded up front. Let’s see if we can delay loading them until everything else is done. That way we can give the impression that our site has loaded quickly even if some requests are still happening in the background. Delaying image loading The first problem we find is that there’s no way to prevent Internet Explorer, Chrome or Safari from loading an image without removing it from the HTML itself. Tricks like removing the images on the fly with JavaScript don’t work, as the browser has usually started requesting the images before we get a chance to stop it. Removing the images from the HTML means that people without JavaScript enabled in their browser won’t see avatars. As Drew mentioned at the start of the month, this can affect a large number of people, and we can’t completely ignore them. But most sites already have a textual name attached to each comment and the avatars are just a visual enhancement. In most cases it’s OK if some of our users don’t see them, especially if it speeds up the experience for the other 98%. Removing the images from the source of our page also means we’ll need to put them back at some point, so we need to keep a record of which images need to be requested. All Gravatar images have the same URL format; the only thing that changes is the e-mail hash. Storing this is a great use of HTML5 data attributes. HTML5 data what? Data attributes are a new feature in HTML5. The latest version of the spec says: A custom data attribute is an attribute in no namespace whose name starts with the string “data-”, has at least one character after the hyphen, is XML-compatible, and contains no characters in the range U+0041 to U+005A (LATIN CAPITAL LETTER A to LATIN CAPITAL LETTER Z). […] Custom data attributes are intended to store custom data private to the page or application, for which there are no more appropriate attributes or elements. These attributes are not intended for use by software that is independent of the site that uses the attributes. In other words, they’re attributes of an HTML element that start with “data-” which you can use to share data with scripts running on your site. They’re great for adding small bits of metadata that don’t fit into an existing markup pattern the way microformats do. Let’s see this in action Take a look at the markup for comments again: <div> <h4><a href="http://allinthehead.com/"> <img src="http://www.gravatar.com/avatar.php?gravatar_id=13734b0cb20708f79e730809c29c3c48&size=100" class="gravatar" alt="" height="100" width="100" /> Drew McLellan </a></h4> <p>This is a great article!</p> </div> Let’s replace the <img> element with a data-gravatar-hash attribute on the <a> element: <div> <h4><a href="http://allinthehead.com/" data-gravatar-hash="13734b0cb20708f79e730809c29c3c48"> Drew McLellan </a></h4> <p>This is a great article!</p> </div> Once we’ve done this, we’ll need a small bit of JavaScript to find all these attributes, and replace them with images after the page has loaded. Here’s an example using jQuery: $(window).load(function() { $('a[data-gravatar-hash]').prepend(function(index){ var hash = $(this).attr('data-gravatar-hash') return '<img width="100" height="100" alt="" src="http://www.gravatar.com/avatar.php?size=100&gravatar_id=' + hash + '">' }) }) This code waits until everything on the page is loaded, then uses jQuery.prepend to insert an image into every link containing a data-gravatar-hash attribute. It’s short and relatively simple, but in tests it reduced the rendering time of a sample page from over three seconds to well under one. Finishing touches We still need to consider the appearance of the page before the avatars have loaded. When our script adds extra content to the page it will cause a browser reflow, which is visually annoying. We can avoid this by using CSS to reserve some space for each image before it’s inserted into the HTML: #comments div { padding-left: 110px; min-height: 100px; position: relative; } #comments div h4 img { display: block; position: absolute; top: 0; left: 0; } In a real world example, we’ll also find that the HTML for a comment is more varied as many users don’t provide a web page link. We can make small changes to our JavaScript and CSS to handle this case. Put this all together and you get this example. Taking this idea further There’s no reason to limit this technique to sites using Gravatar; we can use similar code to delay loading any images that don’t need to be present immediately. For example, this year’s redesigned Flickr photo page uses a “data-defer-src” attribute to describe any image that doesn’t need to be loaded straight away, including avatars and map tiles. You also don’t have to limit yourself to loading the extra resources once the page loads. You can get further bandwidth savings by waiting until the user takes an action before downloading extra assets. Amazon has taken this tactic to the extreme on its product pages – extra content is loaded as you scroll down the page. So next time you’re building a page, take a few minutes to think about which elements are peripheral and could be delayed to allow more important content to appear as quickly as possible. 2010 Paul Hammond paulhammond 2010-12-18T00:00:00+00:00 https://24ways.org/2010/speed-up-your-site-with-delayed-content/ ux
158 10 Ways To Get Design Approval One of the most challenging parts of the web design process is getting design sign off. It can prove time consuming, demoralizing and if you are not careful can lead to a dissatisfied client. What is more you can end up with a design that you are ashamed to include in your portfolio. How then can you ensure that the design you produce is the one that gets built? How can you get the client to sign off on your design? Below are 10 tips learnt from years of bitter experience. 1. Define the role of the client and designer Many of the clients you work with will not have been involved in a web project before. Even if they have they may have worked in a very different way to what you would expect. Take the time at the beginning of the project to explain their role in the design of the site. The best approach is to emphasis that their job is to focus on the needs of their users and business. They should concentrate on the broad issues, while you worry about the details of layout, typography and colour scheme. By clarifying what you expect from the client, you help them to provide the right kind of input throughout the process. 2. Understand the business Before you open up Photoshop or put pen to paper, take the time to make sure you properly understand not only the brief but the organization behind the site. By understanding their business objectives, organizational structure and marketing strategy your design decisions will be better informed. You cannot rely upon the brief to provide all of the information you need. It is important to dig deeper and get as good an understanding of their business as possible. This information will prove invaluable when justifying your design decisions. 3. Understand the users We all like to think of ourselves as user centric designers, but exactly how much effort do you put into knowing your users before beginning the design process? Take the time to really understand them the best you can. Try to meet with some real prospective users and get to know their needs. Failing that work with the client to produce user personas to help picture exactly what kind of people they are. Understanding your users not only improves the quality of your work, but also helps move the discussion away from the personal preferences of the client, to the people who’s opinion really matters. 4. Avoid multiple concepts Many clients like the idea of having the option to choose between multiple design concepts. However, although on the surface this might appear to be a good idea it can ultimately be counterproductive for design sign off. In a world of limited budgets it is unwise to waste money on producing designs that are ultimately going to be thrown away. The resources would be better spent refining a single design through multiple iterations. What is more, multiple concepts often cause confusion rather than clarity. It is common for a client to request one element from one design and another from the second. As any designer knows this seldom works. 5. Use mood boards Clients are often better at expressing what they don’t like than what they do. This is one of the reasons why they favour producing multiple design concepts. An alternative less costly approach is to create a series of mood boards. These boards contain a collection of colours, typography and imagery which represent different “moods” or directions, which the design could take. Mood boards are quick and easy to produce allowing you to try out various design approaches with the client without investing the time needed to produce complete design concepts. This means that by the time you develop a concept the client and designer have already established an understanding about the direction of the design. 6. Say what you like It is not uncommon for a client to ask for a design that looks similar to another site they like. The problem is that it can often be hard to establish exactly what it is about the site that attracts them. Also in many cases the sites they like are not something you are keen to emulate! A better approach that was suggested to me by Andy Budd is to show them sites that you think the design should emulate. Keep a collection of screen captures from well designed sites and pick out a few that are relevant to that particular client. Explain why you feel these designs might suit their project and ask for their feedback. If they don’t like your choices then expose them to more of your collection and see what they pick out. 7. Wireframe the homepage Often clients find it hard to distinguish between design and content and so sometimes reject a design on the basis that the content is not right. This is particularly true when signing off the homepage. You may therefore find it useful to establish the homepage content before producing the design. That way once they see the design they will not be distracted by the content. One of the best ways to do this is by producing a basic wireframe consisting of a series of content boxes. Once this has been approved you will find the sign off of design much easier. 8. Present your designs Although it is true that a good design should speak for itself it still needs presenting to the client. The client needs to understand why you have made the design decisions you have, otherwise they will judge the design purely on personal preference. Talk them through the design explaining how it meets the needs of their users and business objectives. Refer to the mood boards and preferred sites the client approved and explain how the design is a continuation of those. Never simply email the design through and hope the client interprets your work correctly! 9. Provide written supporting material Unfortunately, no matter how well you justify the design to the client he is almost certain to want to show it to others. He may need his bosses approval or require internal buy in. At the very least he is going to want to get a second opinion from a friend or colleague. The problem with this is that you are not going to be there to present to these people in the same way you did for the client. You cannot expect the client to present your ideas as well as you did. The reality is that you have lost control of how the design is perceived. One way to minimize this problem is to provide written documentation supporting the design. This can be a summary of the presentation you gave to the client and allows him to distribute this along with the design. By putting a written explanation with the design you ensure that everybody who sees it gets the same message. 10. Control the feedback My final piece of advice for managing design sign off is to control the way you receive feedback. A clients natural inclination will be to give you his personal opinion on the design. This is reinforced because you ask them what they think of the design. Instead ask them what their users will think of the design. Encourage them to think from the users perspective. Also encourage them to keep that overarching focus I talked about in my first tip. Their tendency will be to try to improve the design, however that should be your problem not theirs. The role of a client should be to defend the needs of their users and business not do the design. Encourage the client to make comments such as “I am not sure that my female users will like the masculine colours” rather than “can we make the whole design pink.” It is down to them to identify the problems and for you as the designer to find the most appropriate solution. So there you have it. My 10 tips to improve design sign off. Will this ensure design approval every time? Unfortunately not. However it should certainly help smooth the way. 2007 Paul Boag paulboag 2007-12-10T00:00:00+00:00 https://24ways.org/2007/10-ways-to-get-design-approval/ business
176 What makes a website successful? It might not be what you expect! What makes some sites succeed and others fail? Put another way, when you are asked to redesign an existing website, what problems are you looking out for and where do you concentrate your efforts? I would argue that as web designers we spend too much time looking at the wrong kind of problem. I recently ran a free open door consultancy clinic to celebrate the launch of my new book (yes I know, two shameless plugs in one sentence). This involved various website owners volunteering their sites for review. Both myself and the audience then provided feedback. What quickly became apparent is that the feedback being given by the audience was biased towards design and development. Although their comments were excellent it focused almost exclusively on the quality of code, site aesthetics and usability. To address these issues in isolation is similar to treating symptoms and ignoring the underlying illness. Cure the illness not the symptoms Poor design, bad usability and terribly written code are symptoms of bigger problems. Often when we endeavour to address these symptoms, we meet resistance from our clients and become frustrated. This is because our clients are still struggling with fundamental concepts we take for granted. Before we can address issues of aesthetics, usability and code, we need to tackle business objectives, calls to action and user tasks. Without dealing with these fundamental principles our clients’ website will fail. Let me address each in turn: Understand the business objectives Do you ask your clients why they have a website? It feels like an obvious question. However, it is surprising how many clients do not have an answer. Without having a clear idea of the siteʼs business objectives, the client has no way to know whether it is succeeding. This means they have no justification for further investment and that leads to quibbling over every penny. However most importantly, without clearly defined business aims they have no standard against which to base their decisions. Everything becomes subjective and that will inevitably lead to problems. Before we start discussing design, usability and development, we need to focus our clients on establishing concrete business objectives. This will provide a framework for decision making during the development phase. This will not only help the client make decisions, it will also focus them on the business and away from micro managing the design. Establish clear calls to action Once business objectives have been set this opens up the possibility to establish clear calls to action. I am amazed at how few website owners can name their calls to action. However, I am even more staggered at how few web designers ask about them. Calls to action are not just limited to ecommerce sites. Whether you are asking people to sign up for a newsletter or complete a contact us form, every site should have a desired objective for users. What is more, each page of a site should have micro calls to action that always draw users on and never leave them at a dead end. Without clearly defined calls to action you cannot successfully design a site, structure the user experience or measure its success. They bring focus to the site and encourage the client to concentrate their efforts on helping people reach those goals. Of course in order to know if a call to action is going to work, it is necessary to do some user testing. Test against the right tasks As web designers we all like to boast about being ʻuser centricʼ whatever that means! However, in reality I think many of us are paying lip service to the subject. Sure, we ask our clients about who their users are and maybe even do some usability testing. However, usability testing is no good if we are not asking the right questions. Again we find ourselves working on a superficial level rather than tackling the deeper issues. Clients find it relatively easy to tell you who their target audience is. Admittedly the list they come back with is often overly long and contains a lot of edge cases. However, where they begin to struggle is articulating what these users will want to achieve on the website. They know who they want to reach. However, they cannot always tell you why those people would be interested in the site. These user tasks are another fundamental building block for any successful website. Although it is important for a website owner to understand what their objectives are and what they want users to do, it is even more important that they understand the users objectives as well. Again, this provides context for the decisions they are making about design, usability and functionality. Without it the site will become self serving, largely ignoring the needs of users. User tasks help to focus the clientʼs mind on the needs of their user, rather than what they can get out of them. So am I claiming that design, usability and code do not matter? Well the shocking truth is that to some extent I am! The shocking truth Whether we like it or not there is significant evidence that you can create a successful website with bad design, terrible code and without ever running a usability test session. You only need to look at the design of Craigslist or the code of Amazon to see that this is true. However, I do not believe it is possible to build a successful website without business objectives, calls to action and a clear idea of user tasks. Do not misunderstand me. I do believe design, usability and code matters. I just believe that they only matter if the fundamentals are already in place. These things improve a solid foundation but are no use in their own right. As web designers it is our responsibility to ensure fundamental questions are being asked, before we start exploring other issues. If we do not, our websites will look great, be well coded and have gone through endless usability tests, however it will not be truly successful. 2009 Paul Boag paulboag 2009-12-04T00:00:00+00:00 https://24ways.org/2009/what-makes-a-website-successful/ business
229 Sketching to Communicate As a web designer I’ve always felt that I’d somehow cheated the system, having been absent on the day God handed out the ability to draw. I didn’t study fine art, I don’t have a natural talent to effortlessly knock out a realistic bowl of fruit beside a water jug, and yet somehow I’ve still managed to blag my way this far. I’m sure many of you may feel the same. I had no intention of becoming an artist, but to have enough skill to convey an idea in a drawing would be useful. Instead, my inadequate instrument would doodle drunkenly across the page leaving a web of unintelligible paths instead of the refined illustration I’d seen in my mind’s eye. This – and the natural scrawl of my handwriting – is fine (if somewhat frustrating) when it’s for my eyes only but, when sketching to communicate a concept to a client, such amateur art would be offered with a sense of embarrassment. So when I had the opportunity to take part in some sketching classes whilst at Clearleft I jumped at the chance. Why sketch? In UX workshops early on in a project’s life, sketching is a useful and efficient way to convey and record ideas. It’s disposable and inexpensive, but needn’t look amateur. A picture may be worth a thousand words, but a well executed sketch of how you’ll combine funny YouTube videos with elephants to make Lolephants.com could be worth millions in venture capital. Actually, that’s not bad… ;-) Although (as you will see) the basics of sketching are easy to master, the kudos you will receive from clients for being a ‘proper designer’ makes it worthwhile! Where to begin? Start by not buying yourself a sketch pad. If you were the type of child who ripped the first page out of a school exercise book and started again if you made even a tiny mistake (you’re not alone!), Wreck This Journal may offer a helping hand. Practicing on plain A4 paper instead of any ‘special’ notepad will make the process a whole lot easier, no matter how deliciously edible those Moleskines look. Do buy yourself a black fine-liner pen and a set of grey Pro Markers for shading. These pens are unlike any you will have used before, and look like blended watercolours once the ink is dry. Although multiple strokes won’t create unsightly blotches of heavy ink on the page, they will go right through your top sheet so always remember to keep a rough sheet in the second position as an ink blotter. photo by Tom Harrison Don’t buy pencils to sketch with, as they lack the confidence afforded by the heavy black ink strokes of marker pens and fine-liners. If you’re going to be sketching with clients then invest in some black markers and larger sheets of paper. At the risk of sounding like a stationery brand whore, Sharpies are ideal, and these comedy-sized Post-Its do the job far better than cheaper, less sticky alternatives. Although they’re thicker than most standard paper, be sure to double-layer them if you’re writing on them on a wall, unless you fancy a weekend redecorating your client’s swanky boardroom. The best way to build confidence and improve your sketching technique is, obviously, to practise. Reading this article will be of no help unless you repeat the following examples several times each. Go grab a pen and some paper now, and notice how you improve within even a short period of time. Sketching web UI Most elements of any website can be drawn as a combination of geometric shapes. photo by Nathanael Boehm Circles To draw a circle, get in position and start by resting your hand on the page and making the circular motion a few times without putting pen to paper. As you lower your pen whilst continuing the motion, you should notice the resulting shape is more regular than it otherwise would have been. Squares and rectangles Draw one pair of parallel lines first, followed by the others to complete the shapes. Slightly overlap the ends of the lines to make corners feel more solid than if you were to leave gaps. If you’re drawing a container, always draw the contents first, that way it won’t be a squash to fit them in. If you’re drawing a grid (of thumbnails, for instance), draw all parallel lines first as a series of long dashes to help keep line lengths and angles consistent. Shadows To lift elements from the page for emphasis, add a subtle shadow with a grey marker. For the most convincing look, assume the light source to be at the top left of the page – the shadow should simply be a thick grey line along the bottom and up the right edge of your shape. If the shape is irregular, the shadow should follow its outline. This is a good way to emphasise featured items, speech bubbles, form buttons, and so on. Sketching ideas Arrows Use arrows to show steps in a process or direction of movement. Giving shadows a 3-D feel, or adding a single colour, will help separate them from the rest of the sketch. Faces Start by drawing the circle. The direction of the nose (merely a point) indicates the direction of the person’s gaze. The eyes and mouth show emotion: more open and curvy for happy thoughts; more closed and jagged for angry thoughts. Try out a few shapes and see what emotions they convey. People Remember, we’re aiming for communication rather than realism here. A stick man would be fine. Give him a solid body, as shown in this example, and it becomes easier to pose him. I know you think hands are hard, but they’re quite important to convey some ideas, and for our purposes we don’t need to draw hands with any detail. An oval with a stick does the job of a pointing hand. Close-ups might need more fingers showing, but still don’t require any degree of realism. Signage Don’t be afraid to use words. We’re sketching to communicate, so if the easiest way to show an office block is a building with a big ‘office’ sign on the roof, that’s fine! Labels Likewise, feel free to label interactions. Use upper-case letters for legibility and slightly angle the horizontal bars upwards to create a more positive feel. Clichés Clichés are your friend! Someone’s having an idea? Light bulb above the head. Computer’s crashed? Cloud of smoke with “$£%*!” It’s good to practise regularly. Try applying these principles to still life, too. Look around you now and draw the cup on the table, or the books on the shelf. Think of it as a combination of shapes and aim for symbolism rather than realism, and it’s not as hard as you’d think. I hope this has given you the confidence to give it a shot, and the ability to at least not be mortified with the results! Tip: If you’re involving clients in design games like Leisa Reichelt’s ‘Design Consequences’ it may be wise to tone down the quality of your drawings at that point so they don’t feel intimidated. Remember, it’s important for them to feel at ease with the idea of wireframing in front of you and their colleagues, no matter how bad their line work. For more information see davegrayinfo.com – Dave Gray taught me everything I know :-) 2010 Paul Annett paulannett 2010-12-19T00:00:00+00:00 https://24ways.org/2010/sketching-to-communicate/ business
188 Don't Lose Your :focus For many web designers, accessibility conjures up images of blind users with screenreaders, and the difficulties in making sites accessible to this particular audience. Of course, accessibility covers a wide range of situations that go beyond the extreme example of screenreader users. And while it’s true that making a complex site accessible can often be a daunting prospect, there are also many small things that don’t take anything more than a bit of judicious planning, are very easy to test (without having to buy expensive assistive technology), and can make all the difference to certain user groups. In this short article we’ll focus on keyboard accessibility and how careless use of CSS can potentially make your sites completely unusable. Keyboard Access Users who for whatever reason can’t use a mouse will employ a keyboard (or keyboard-like custom interface) to navigate around web pages. By default, they will use TAB and SHIFT + TAB to move from one focusable element (links, form controls and area) of a page to the next. Note: in OS X, you’ll first need to turn on full keyboard access under System Preferences > Keyboard and Mouse > Keyboard Shortcuts. Safari under Windows needs to have the option Press Tab to highlight each item on a webpage in Preferences > Advanced enabled. Opera is the odd one out, as it has a variety of keyboard navigation options – the most relevant here being spatial navigation via Shift+Down, Shift+Up, Shift+Left, and Shift+Right). But I Don’t Like Your Dotted Lines… To show users where they are within a page, browsers place an outline around the element that currently has focus. The “problem” with these default outlines is that some browsers (Internet Explorer and Firefox) also display them when a user clicks on a focusable element with the mouse. Particularly on sites that make extensive use of image replacement on links with “off left” techniques this can create very unsightly outlines that stretch from the replaced element all the way to the left edge of the browser. Outline bleeding off to the left (image-replacement example from carsonified.com) There is a trivial workaround to prevent outlines from “spilling over” by adding a simple overflow:hidden, which keeps the outline in check around the clickable portion of the image-replaced element itself. Outline tamed with overflow:hidden But for many designers, even this is not enough. As a final solution, many actively suppress outlines altogether in their stylesheets. Controversially, even Eric Meyer’s popular reset.css – an otherwise excellent set of styles that levels the playing field of varying browser defaults – suppresses outlines. html, body, div, span, applet, object, iframe ... { ... outline: 0; ... } /* remember to define focus styles! */ :focus { outline: 0; } Yes, in his explanation (and in the CSS itself) Eric does remind designers to define relevant styles for :focus… but judging by the number of sites that seem to ignore this (and often remove the related comment from the stylesheet altogether), the message doesn’t seem to have sunk in. Anyway… hurrah! No more unsightly dotted lines on our lovely design. But what about keyboard users? Although technically they can still TAB from one element to the next, they now get no default cue as to where they are within the page (one notable exception here is Opera, where the outline is displayed regardless of stylesheets)… and if they’re Safari users, they won’t even get an indication of a link’s target in the status bar, like they would if they hovered over it with the mouse. Only Suppress outline For Mouse Users Is there a way to allow users navigating with the keyboard to retain the standard outline behaviour they’ve come to expect from their browser, while also ensuring that it doesn’t show display for mouse users? Testing some convoluted style combinations After playing with various approaches (see Better CSS outline suppression for more details), the most elegant solution also seemed to be the simplest: don’t remove the outline on :focus, do it on :active instead – after all, :active is the dynamic pseudo-class that deals explicitly with the styles that should be applied when a focusable element is clicked or otherwise activated. a:active { outline: none; } The only minor issues with this method: if a user activates a link and then uses the browser’s back button, the outline becomes visible. Oh, and old versions of Internet Explorer notoriously get confused by the exact meaning of :focus, :hover and :active, so this method fails in IE6 and below. Personally, I can live with both of these. Note: at the last minute before submitting this article, I discovered a fatal flaw in my test. It appears that outline still manages to appear in the time between activating a link and the link target loading (which in hindsight is logical – after activation, the link does indeed receive focus). As my test page only used in-page links, this issue never came up before. The slightly less elegant solution is to also suppress the outline on :hover. a:hover, a:active { outline: none; } In Conclusion Of course, many web designers may argue that they know what’s best, even for their keyboard-using audience. Maybe they’ve removed the default outline and are instead providing some carefully designed :focus styles. If they know for sure that these custom styles are indeed a reliable alternative for their users, more power to them… but, at the risk of sounding like Jakob “blue underlined links” Nielsen, I’d still argue that sometimes the default browser behaviours are best left alone. Complemented, yes (and if you’re already defining some fancy styles for :hover, by all means feel free to also make them display on :focus)… but not suppressed. 2009 Patrick Lauke patricklauke 2009-12-09T00:00:00+00:00 https://24ways.org/2009/dont-lose-your-focus/ code
331 Splintered Striper Back in March 2004, David F. Miller demonstrated a little bit of DOM scripting magic in his A List Apart article Zebra Tables. His script programmatically adds two alternating CSS background colours to table rows, making them more readable and visually pleasing, while saving the document author the tedious task of manually assigning the styling to large static data tables. Although David’s original script performs its duty well, it is nonetheless very specific and limited in its application. It only: works on a single table, identified by its id, with at least a single tbody section assigns a background colour allows two colours for odd and even rows acts on data cells, rather than rows, and then only if they have no class or background colour already defined Taking it further In a recent project I found myself needing to apply a striped effect to a medium sized unordered list. Instead of simply modifying the Zebra Tables code for this particular case, I decided to completely recode the script to make it more generic. Being more general purpose, the function in my splintered striper experiment is necessarily more complex. Where the original script only expected a single parameter (the id of the target table), the new function is called as follows: striper('[parent element tag]','[parent element class or null]','[child element tag]','[comma separated list of classes]') This new, fairly self-explanatory function: targets any type of parent element (and, if specified, only those with a certain class) assigns two or more classes (rather than just two background colours) to the child elements inside the parent preserves any existing classes already assigned to the child elements See it in action View the demonstration page for three usage examples. For simplicity’s sake, we’re making the calls to the striper function from the body’s onload attribute. In a real deployment situation, we would look at attaching a behaviour to the onload programmatically — just remember that, as we need to pass variables to the striper function, this would involve creating a wrapper function which would then be attached…something like: function stripe() { striper('tbody','splintered','tr','odd,even'); } window.onload=stripe; A final thought Just because the function is called striper does not mean that it’s limited to purely applying a striped look; as it’s more of a general purpose “alternating class assignment” script, you can achieve a whole variety of effects with it. 2005 Patrick Lauke patricklauke 2005-12-15T00:00:00+00:00 https://24ways.org/2005/splintered-striper/ code
329 Broader Border Corners A note from the editors: Since this article was written the CSS border-radius property has become widely supported in browsers. It should be preferred to this image technique. A quick and easy recipe for turning those single-pixel borders that the kids love so much into into something a little less right-angled. Here’s the principle: We have a box with a one-pixel wide border around it. Inside that box is another box that has a little rounded-corner background image sitting snugly in one of its corners. The inner-box is then nudged out a bit so that it’s actually sitting on top of the outer box. If it’s all done properly, that little background image can mask the hard right angle of the default border of the outer-box, giving the impression that it actually has a rounded corner. Take An Image, Finely Chopped Add A Sprinkle of Markup <div id="content"> <p>Lorem ipsum etc. etc. etc.</p> </div> Throw In A Dollop of CSS #content { border: 1px solid #c03; } #content p { background: url(corner.gif) top left no-repeat; position: relative; left: -1px; top: -1px; padding: 1em; margin: 0; } Bubblin’ Hot The content div has a one-pixel wide red border around it. The paragraph is given a single instance of the background image, created to look like a one-pixel wide arc. The paragraph is shunted outside of the box – back one pixel and up one pixel – so that it is sitting over the div’s border. The white area of the image covers up that part of the border’s corner, and the arc meets up with the top and left border. Because, in this example, we’re applying a background image to a paragraph, its top margin needs to be zeroed so that it starts at the top of its container. Et voilà. Bon appétit. Extra Toppings If you want to apply a curve to each one of the corners and you run out of meaningful markup to hook the background images on to, throw some spans or divs in the mix (there’s nothing wrong with this if that’s the effect you truly want – they don’t hurt anybody) or use some nifty DOM Scripting to put the scaffolding in for you. Note that if you’ve got more than one of these relative corners, you will need to compensate for the starting position of each box which is nested in an already nudged parent. You’re not limited to one pixel wide, rounded corners – the same principles apply to thicker borders, or corners with different shapes. 2005 Patrick Griffiths patrickgriffiths 2005-12-14T00:00:00+00:00 https://24ways.org/2005/broader-border-corners/ design
19 In Their Own Write: Web Books and their Authors The currency of written communication — words on the page, words on the screen — comprises many denominations. To further our ends in web design and development, we freely spend and receive several: tweets aphoristic and trenchant, banal and perfunctory; blog posts and articles that call us to action or reflection; anecdotes, asides, comments, essays, guides, how-tos, manuals, musings, notes, opinions, stories, thoughts, tips pro and not-so-pro. So many, many words. Our industry (so much more than this, but what on earth are we, collectively?), our community thrives on writing and sharing knowledge and experience. 24 ways is a case in point. Everyone can learn and contribute through reading and writing — it’s what we’ve always done. To web authors and readers seeking greater returns, though, broader culture has vouchsafed an enduring and singular artefact: the book. Last month I asked a small sample of web book authors if they would be prepared to answer a few questions; most of them kindly agreed. In spirit, the survey was informal: I had neither hypothesis nor unground axe. I work closely with writers — and yes, I’ve edited or copy-edited books by several of the authors I surveyed — and wanted to share their thoughts about what it was like to write a book (“…it was challenging to find a coherent narrative”), why they did it (“Who wouldn’t want to?”) and what they learned from the experience (“That I could!”). Reasons for writing a book In web development the connection between authors and readers is unusually close and immediate. Working in our medium precipitates a unity that’s rare elsewhere. Yet writing and publishing a book, even during the current books revolution, is something only a few of us attempt and it remains daunting and a little remote. What spurs an author to try it? For some, it’s a deeply held resistance to prevailing trends: I felt that designers and developers needed to be shaken out of what seemed to me had been years of stagnation. —Andrew Clarke Or even a desire to protect us from ourselves: I felt that without a book that clearly defined progressive enhancement in a very approachable and succinct fashion, the web was at risk. I was seeing Tim Berners-Lee’s vision of universal availability slip away… —Aaron Gustafson Sometimes, there’s a knowledge gap to be filled by an author with the requisite excitement and need to communicate. Jon Hicks took his “pet subject” and was “enthused enough to want to spend all that time writing”, particularly because: …there was a gap in the market for it. No one had done it before, and it’s still on its own out there, with no competition. It felt like I was able to contribute something. Cennydd Bowles felt a professional itch at a particular point in his career, understanding that [a]s a designer becomes more senior, they start looking for ways to scale the effects of their work. For some, that leads into management. For others, into writing. Often, though, it’s also simply a personal challenge and ambition to explore a subject at length and create something substantial. Anna Debenham describes a motivation shared by several authors: To be able to point to something more tangible than an article and be able to say “I did that.” That sense of a book’s significance, its heft and gravity even, stems partly from the cultural esteem which honours books and their authors. Books have a long history as sources of wisdom, truth and power. Even with more books being published each year than ever before, writing one is still commonly considered a laudable achievement, including in our field. Challenges of writing a book Received wisdom has it that writing online should be brief and chunky and approachable: get to the point; divide it all up; subheadings and lists are our friends; write like you’re talking; no one has time to read. Much of such advice is true. Followed well, it lends our writing punch and pith, vigour and vim. The web is nimble, the web keeps up, and it suits what we write about developing for it. It’s perfect for delivering our observations, queries and investigations into all the various aspects of the work, professional and personal. Yet even for digital natives like web authors, books printed and electronic retain an attractive glister. Ideas can be developed more fully, their consequences explored to greater depth and extended with more varied examples, and the whole conveyed with more eloquence, more style. Why shouldn’t authors delay their conclusions if the intervening text is apposite, rich with value and helps to flesh out the skeleton of an argument? Conclusions might or might not be reached, of course, but a writer is at greater liberty in a book to digress in tangential and interesting ways. Writing a book involves committing time, energy, thought and money. As Brian Suda found, it can be tough “getting the ideas out of my head into a cohesive blob of text.” Some authors end up talking to themselves… It helps me to keep a real person in mind, someone who I’m talking to as I write. Sometimes I have the same conversations over and over in my head. —Andrew Clarke …while others are thinking ahead, concerned with how their book will be received: Would anyone want to read it? Would they care? Would it be respected by my peers? —Joe Leech Challenges that arose time and again included “starting” and “getting words on the page” as well as “knowing when to stop” or “letting go”. Personal organization problems and those caused by publishers were also widely mentioned. Time loomed large. Making time, finding time. Giving up “sleep and some sanity” and realizing “it will take you far, far, far longer than you naively assumed”. Importantly, writing time is time away from gainful employment: Aaron Gustafson found the hardest thing about writing a book to be “the loss of income while I was writing.” Perils and pleasures of editing Editing, be it structural, technical or copy editing, is founded on reciprocity. Without openness and a shared belief that the book is worthwhile, work can founder in acrimony and mistrust. Editors are a book’s first and most critical (in every sense) readers. Effective and perceptive editing makes a book as good as it can be, finding the book within the draft like sculpture reveals the statue in the stone. A good editor calls you out on poor assumptions and challenges you to really clarify your thinking. Whilst it can be difficult during the process to have your thinking challenged, it’s always been worth it — for me personally — in the long run. A good editor also reins you in when you’ve perhaps wandered off track or taken a little too long to make a point. —Christopher Murphy Andy Croll found editing “all positive” and Aaron Gustafson loves “working with a strong editor […] I want someone to tell it to me straight.” But it can be a rollercoaster, “both terrifying and the real moment of elation”. Mixed emotions during the editing process are common: It was very uncomfortable! I knew it was making the work stronger, but it was awkward having my inconsistencies and waffle picked apart. —Jon Hicks It can be distressing to have written work looked over by a professional, particularly for first-time book authors whose expertise lies elsewhere: I was a little nervous because I don’t consider myself a skilled writer — I never dreamed of becoming an author. I’m a designer, after all. —Geri Coady Communication is key, particularly when it comes to checking or changing the author’s words. I like a good banter between me and the tech editor — if we can have a proper argument in Word comments, that’s great. —Rachel Andrew But if handled poorly, small battles can break out. Rachel Andrew again: However, having had plenty of times where the technical editor has done nothing more than give a cursory glance, I started to leave little issues in for them to spot. If they picked them up I knew they were actually testing the code and I could be sure the work was being properly tech edited. If they didn’t spot them, I’d find someone myself to read through and check it! A major concern for writers is that their voices will be altered, filtered, mangled or otherwise obscured by the editing process. Good copy editing must remain unnoticed while enhancing the author’s voice in print. Donna Spencer appreciated the way her editor “tidied up my work and made it a million times better, but left it sounding exactly like me.” Similarly, Andrew Travers “was incredibly impressed at how well my editor tightened up my own writing without it feeling like another’s voice” and Val Head sums up the consensus that: the editor was able to help me express what I was trying to say in a better way […] I want to have editors for everything now. At the keyboard, keep your friends close, but your editors closer. Publishing and publishers Conditions ought to militate against the allure of writing a book about web design and development. More books are published each year than ever before, so readerships elude new authors and readers can struggle to find authors to trust in their fields of interest. New spaces for more expansive online writing about working on and with the web are opening up (sites like Contents Magazine and STET), and seminal online web development texts are emerging. Publishing online is simple, far-reaching and immediate. Much more so than articles and blog posts, books take time to research, write and read; add the complexity of commissioning, editing, designing, proofreading, printing, marketing and distribution processes, and it can take many months, even years to publish. The ceaseless headlong momentum of the web can leave articles more than a few weeks old whimpering in its wake, but updating them at least is straightforward; printed books about web development can depreciate as rapidly as the technology and techniques they describe, while retaining the “terrifying permanence that print bestows: your opinions will follow you forever”. So much moves on, and becomes out of date. Companies featured get bought by larger companies and die, techniques improve and solutions featured become terribly out of date. Unlike a website, which could be updated continuously, a book represents the thinking ‘at that time’. —Jon Hicks Publishers work hard to mitigate these issues, promoting new books and new authors, bringing authors and readers together under a trusted banner. When a publisher packages up and releases a writer’s words, it confers a seal of approval and “badge of quality”, very important to new authors. Publishers have other benefits to offer, from expert knowledge: My publisher was extraordinarily supportive (and patient). Her expertise in my chosen subject was both a pressure (I didn’t want to let her down) and a reassurance (if she liked it, I knew it was going to be fine). —Andrew Travers …to systems and support mechanisms set up specifically to encourage writers and publish books: Working as a team means you’re bringing in everyone’s expertise. —Chui Chui Tan As a writer, the best part about writing for a publisher was the writing infrastructure offered. —Christopher Murphy There can be drawbacks, however, and the occasional horror story: We were just one small package on a huge conveyor belt. The publisher’s process ruled all. —Cennydd Bowles It’s only looking back I realise how poorly some publishers treat writers — especially when the work is so poorly remunerated.My worst experience was when a publisher decided, after I had completed the book, that they wanted to push a different take on the subject than the brief I had been given. Instead of talking to me, they rewrote chunks of my words, turning my advice into something that I would never have encouraged. Ultimately, I refused to let the book go out under my name alone, and I also didn’t really promote the book as I would have had to point out the things I did not agree with that had been inserted! —Rachel Andrew Self-publishing is now a realistic option for web authors, and can offers “complete control over the end product” as well as the possibility of earning more than a “pathetic author revenue percentage”. There can be substantial barriers, of course, as self-publishing authors must face for themselves the risks and challenges conventional publishers usually bear. Ideally, creating a book is a collaboration between author and publisher. Geri Coady found that “working with my publisher felt more like working with a partner or co-worker, rather than working for a boss.” Wise words So, after meeting the personal costs of writing and publishing a web book — fear, uncertainty, doubt, typing (so much typing) — and then smelling the roses of success, what’s left for an author to say? Some words, perhaps, to people thinking of writing a book. Donna Spencer identifies a stumbling block common to many writers with an insight into the writing process: Having talked to a lot of potential authors, I think most have the problem that they haven’t actually figured out the ‘answer’ to their premise yet. They feel like they are stuck in the writing, but they are actually stuck in the thinking. For some no-nonsense, straightforward advice to cut through any anxiety or inadequacy, Rachel Andrew encourages authors to “treat it like any other work. There is no mystery to writing, you just have to write. Schedule the time, sit down, write words.” Tim Brown notes the importance of the editing process to refine a book and help authors reach their readers: Hire good editors. Editors are amazing thinkers who can vastly improve the quality and clarity of a piece of writing. We are too much beholden to the practical demands and challenges of technology, so Aaron Gustafson suggests a writer should “favor philosophies over techniques and your book will have a longer shelf life.” Most intimations of renown and recognition are nipped in the bud by Joe Leech’s warning: “Don’t expect fame and fortune.” Although Cennydd Bowles’ bitter experience can be discouraging: The sacrifices required are immense. You probably won’t make it. …he would do things differently for a future book: I would approach the book with […] far more concern about conveying the damn joy of what I do for a living. The pleasure of writing, not just having written is captured by James Chudley when he recalls: How much I enjoy writing and also how much I enjoy the discipline or having a side project like this. It’s a really good supplement to working life. And Jon Hicks has words that any author will find comforting: It will be fine. Everything will be fine. Just get on with it! As the web expands effortlessly and ceaselessly to make room for all our words, yet it can also discourage the accumulation of any particular theme in one space, dividing rich seams and scattering knowledge across the web’s surface and into its deepest reaches. How many words become weightless and insubstantial, signals lost in the constant white noise of indistinguishable voices, unloved, unlinked? The web forgets constantly, despite the (somewhat empty) promise of digital preservation: articles and data are sacrificed to expediency, profit and apathy; online attention, acknowledgement and interest wax and wane in days, hours even. Books can encourage deeper engagement in readers, and foster faith in an author, particularly if released under the imprint of a recognized publisher within the field. And books are changing. Although still not widely adopted, EPUB3 is the new standard in ebooks, bringing with it new possibilities for interaction and connection: readers with the text; readers with readers; and readers with authors. EPUB3 is built on HTML, CSS and JavaScript — sound familiar? In the past, we took what we could from the printed page to make the web; now books are rubbing up against what we’ve made. So: a book. Ever thought you could write one? Should write one? Would? I’d like to thank all the authors who wrote their books and answered my questions. Rachel Andrew · CSS3 Layout Modules, The CSS3 Anthology and more Cennydd Bowles · Undercover User Experience Design, with James Box Tim Brown · Combining Typefaces James Chudley · Usability of Web Photos Andrew Clarke · Hardboiled Web Design Geri Coady · Colour Accessibility Andy Croll · HTML Email Anna Debenham · Front-end Style Guides Aaron Gustafson · Adaptive Web Design Val Head · CSS Animations Jon Hicks · The Icon Handbook Joe Leech · Psychology for Designers Christopher Murphy · The Craft of Words, with Niklas Persson Donna Spencer · Information Architecture, Card Sorting and How to Write Great Copy for the Web Brian Suda · Designing with Data Chui Chui Tan · International User Research Andrew Travers · Interviewing for Research 2013 Owen Gregory owengregory 2013-12-15T00:00:00+00:00 https://24ways.org/2013/web-books/ content
285 Composing the New Canon: Music, Harmony, Proportion Ohne Musik wäre das Leben ein Irrtum —Friedrich NIETZSCHE, Götzen-Dämmerung, Sprüche und Pfeile 33, 1889 Somehow, music is hardcoded in human beings. It is something we understand and respond to without prior knowledge. Music exercises the emotions and our imaginative reflex, not just our hearing. It behaves so much like our emotions that music can seem to symbolize them, to bear them from one person to another. Not surprisingly, it conjures memories: the word music derives from Greek μουσική (mousike), art of the Muses, whose mythological mother was Mnemosyne, memory. But it can also summon up the blood, console the bereaved, inspire fanaticism, bolster governments and dissenters alike, help us learn, and make web designers dance. And what would Christmas be without music? Music moves us, often in ways we can’t explain. By some kind of alchemy, music frees us from the elaborate nuisance and inadequacy of words. Across the world and throughout recorded history – and no doubt well before that – people have listened and made (and made out to) music. [I]t appears probable that the progenitors of man, either the males or females or both sexes, before acquiring the power of expressing their mutual love in articulate language, endeavoured to charm each other with musical notes and rhythm. —Charles DARWIN, The Descent of Man, and Selection in Relation to Sex, 1871 It’s so integral to humankind, we’ve sent it into space as a totem for who we are. (Who knows? It might be important.) Music is essential, a universal compulsion; as Nietzsche wrote, without music life would be a mistake. Music, design and web design There are some obvious and notable similarities between music and visual design. Both can convey mood and evoke emotion but, even under close scrutiny, how they do that remains to a great extent mysterious. Each has formal qualities or parts that can be abstracted, analysed and discussed, often using the same terminology: composition, harmony, rhythm, repetition, form, theme; even colour, texture and tone. A possible reason for these shared aspects is that both visual design and music are means to connect with people in deep and lasting ways. Furthermore, I believe the connections to be made can complement direct emotional appeal. Certain aesthetic qualities in music work on an unconscious and, it could be argued, universal level. Using musical principles in our designs, then, can help provide the connectedness between content, device and user that we now seek as web designers. Yet, when we talk about music and web design, the conversation is almost always about the music designers listen to while working, a theme finding its apotheosis in Designers.MX. Sometimes, articles in that dreary list format seek inspiration from music industry websites. There’s even a service offering pre-templated web designs for bands, and at least one book surveyed the landscape back in 2006. Occasionally, discussions broaden somewhat into whether and how different kinds of music can inspire and influence the design work we produce. Such enquiries, it seems to me, are beside the point. Do I really design differently when I listen to Bach rather than Bacharach? Will the barely restrained energy of Count Basie’s The Kid from Red Bank mean I choose a lively colour palette, and rural, autumnal shades when inspired by Fleet Foxes? Mahler means a thirteen-column layout? Gillian Welch leads to distressed black and white photography? While reflecting the importance we place in music and how it seems to help us in our work, surveys on musical taste and lists of favourite artists fail to recognize that some of the fundamental aesthetic characteristics of music can be adapted and incorporated into modern web design. Antiphonal geometry Over recent years, web designers have embraced grid systems as powerful tools to help create good-looking and intuitive user experiences. With the advent of responsive design, these grids and their contents must adapt to the different screen sizes and properties of all kinds of user devices. Finding and using grid values that can scale well and retain or enhance their proportions and relationships while making the user experience meaningful in several different contexts is more important than ever. In print, this challenge has always started with the dimensions and proportions of the page. Content can thereby be made to belong inside the page and be bound to it. And music has been used for centuries to further this aim. As Robert Bringhurst says in The Elements of Typographical Style: Indeed, one of the simplest of all systems of page proportions is based on the familiar intervals of the diatonic scale. Pages that embody these basic musical proportions have been in common use in Europe for more than a thousand years. Very well. But while he goes on to list (from the full chromatic scale, rather than just diatonic) the proportions and the musical intervals they’re based on, Bringhurst fails to mention what they’re ratios of or their potential effects. Shame. In his favour, however, he later touches on how proportions in print might be considered to work: The page is a piece of paper. It is also a visible and tangible proportion, silently sounding the thoroughbass of the book. On it lies the textblock, which must answer to the page. The two together – page and textblock – produce an antiphonal geometry. That geometry alone can bond the reader to the book. Or conversely, it can put the reader to sleep, or put the reader’s nerves on edge, or drive the reader away. So what does Bringhurst mean by antiphonal geometry, a phrase that marries the musical to the spatial? By stating that the textblock “must answer to the page”, the implication is that the relationship between the proportions of the page and the shape of the textblock printed on it embodies a spatial (geometrical) call-and-response (antiphony) that can be appealing or not. Boulton’s new canon But, as Mark Boulton has pointed out, on the web “there are no edges. There are no ‘pages’. We’ve made them up.” So, what is to be done? In January 2011 at the New Adventures in Web Design conference, Boulton presented his vision of a new canon of web design, a set of principles to guide us as we design the web. There are three overlapping tenets: design from the content out create connectedness between the different content elements bind the content to the web device Rather than design from the edges in, we need to design layout systems from the content out. To this end, Boulton asserts that grid system design should begin with a constraint, and he suggests we use the size of a fixed content element, such as an advertising unit or image, as a starting point for online grid calculations. Khoi Vinh advocates the same approach in his book, Ordering Disorder: Grid Principles for Web Design. Boulton’s second and third tenets, however, are more complex and overlap significantly with each other. Connecting the different parts of the content and binding the content to the device share many characteristics and solutions: adopting ems and percentages as units of size for layout elements altering text size, line length and line height for different viewport dimensions providing higher resolution images for devices with greater pixel densities fluid layout grids, flexible images and responsive design All can help relate the presentation of the content to its delivery in a certain context. But how do we determine the relationship between one element of a layout and another? How can we avoid making arbitrary decisions about the relative sizes of parts of our designs? What can we use to connect the parts of our design to one another, and how can we bind the presentation of the content to the user’s device? Tim Brown’s application of modular typographic scales hints at an answer. In the very useful tool he created for calculating such scales, Brown includes two musical ratios: the perfect fifth (2:3); and the perfect fourth (3:4). Why? Where do they come from? And what do they mean? Harmonies musical and visual Fundamental to music are rhythm and harmony. As any drummer will tell you, without rhythm there is no music. Even when there’s no regular beat, any tune follows a rhythm, however irregular, simply because a change of note is a point of change in the music. Although rhythm, timing and pacing are all relevant to interaction design, right now it’s harmony we’re interested in. Sometimes harmony is called the vertical aspect of music, and melody the horizontal. But this conceit overlooks the fact that harmony is both vertical and horizontal. A single melodic line, as it is played, implies various sets of harmonies on which it is grounded, whether or not those harmonies are played. So, harmony doesn’t just sit vertically beneath the horizontal melody, but moves horizontally as well, through harmonic progression. To stretch this arrangement pixel-thin, we could argue that in onscreen design melody is the content, and the layout and arrangement of the content is the harmony. We sometimes say a design is harmonious when the interplay of different elements of a design is pleasing or balanced or in proportion, and the content (the melody) is set off or conveyed well by or appropriate to the design. We seem to know instinctively whether a layout is harmonious… In the design of The Great Discontent, the relationships between different elements combine to form a balanced whole. …or not. There’s no harmony in the Department for Education’s website because the different parts of the content don’t feel related to one another. What is it that makes one design harmonious and another dissonant? It’s not just whether things line up, though that’s a start. I believe there are much deeper aesthetic forces at work, forces we can tap into in our onscreen designs. Now, I’m not going start a difficult discussion about aesthetics. For our purposes, we just need to know that it’s the branch of philosophy dealing with the nature of beauty, and the creation and perception of beauty. And among the key components in the perception of beauty are harmony and proportion. These have been part of traditional western aesthetics since Plato (about 2,500 years). One of the ways we appreciate the beauty of music is through the harmonic intervals we hear. A musical interval is a combination of two notes and it describes the distance between the two pitches. For example, the distance between C and the G above it (if we take C as the tonic or root) is called a perfect fifth. Left: C to G, a perfect fifth. Right: C and G, not a perfect fifth. And, to get superficially scientific for a moment, each musical interval can be expressed as a ratio of the wavelength frequencies of the notes; for our perfect fifth, with every two wavelengths of C, there are three of G. And what is a ratio, if not a proportion of one thing to another? So, simple musical harmony (using what’s known as just intonation1) affords us a set of proportions, expressed as ratios. Where better to apply these ideas of harmony and proportion from music in web design, than grid systems? A digression: whither φ? Quite often in our discussions of pure design and aesthetics, we mention the golden ratio and regurgitate the same justifications for its use: roots in antiquity; embodied in classical and Renaissance architecture and art; occurrence in nature; the New Twitter, and so forth (oh, really?). Yet the ratios of musical intervals from just intonation are equally venerable and much more widespread: described by Pythagorus; employed in Palladian architecture, and printing, books and art from the Renaissance onwards; in modern times, film and television dimensions; standard international paper sizes (ISO 216, the A and B series); and, again and again, screen dimensions – chances are that screen you’re probably looking at right now has the proportions 2:3 (iPhone and iPod Touch), 3:4 (iPad and Kindle), 3:5 (many smartphones), 5:8 or 16:9 (many widescreen monitors), all ratios of musical intervals. Back to our theme… Musical interval ratios Let’s take a look at most of the ratios within a couple of octaves and crunch some numbers to generate some percentages and other values that we can use in our designs. First, the intervals and their ratios in just intonation and expressed as ratios of one: Name Interval in C Ratio Ratio (1:x) unison C→C 1:1 1:1 minor second C→D♭ 15:16 1:1.067 major second C→D 8:9 1:1.125 minor third C→E♭ 5:6 1:1.2 major third C→E 4:5 1:1.25 perfect fourth C→F 3:4 1:1.333 augmented fourth or diminished fifth C→F♯/G♭ 1:√2 1:1.414 perfect fifth C→G 2:3 1:1.5 minor sixth C→A♭ 5:8 1:1.6 major sixth C→A 3:5 1:1.667 minor seventh C→B♭ 9:16 1:1.778 major seventh C→B 8:15 1:1.875 octave C→C↑ 1:2 1:2 major tenth C→E↑ 2:5 1:2.5 major eleventh C→F↑ 3:8 1:2.667 major twelfth C→G↑ 1:3 1:3 double octave C→C↑ 1:4 1:4 Name Interval in C Ratio Ratio (1:x) And now as percentages, of both the larger and smaller values in the ratios: Name Ratio % of larger value % of smaller value unison 1:1 100% 100% minor second 15:16 93.75% 106.667% major second 8:9 88.889% 112.5% minor third 5:6 83.333% 120% major third 4:5 80% 125% perfect fourth 3:4 75% 133.333% augmented fourth or diminished fifth 1:√2 70.711% 141.421% perfect fifth 2:3 66.667% 150% minor sixth 5:8 62.5% 160% major sixth 3:5 60% 166.667% minor seventh 9:16 56.25% 177.778% major seventh 8:15 53.333% 187.5% octave 1:2 50% 200% major tenth 2:5 40% 250% major eleventh 3:8 37.5% 266.667% major twelfth 1:3 33.333% 300% double octave 1:4 25% 400% Name Ratio % of larger value % of smaller value As you can see, the simple musical intervals are expressed as ratios of small whole numbers (integers). We can then normalize them as ratios of one, as well as derive percentage values, both in terms of the smaller value to the larger, and vice versa. These are the numbers we can incorporate into our designs. If you’ve ever written something like body { font: 100%/1.5 "Museo Sans", Helvetica, sans-serif; } in your CSS, you’re already using a musical ratio: the perfect fifth. Modular scales allow us to generate a set of numbers based on a musical interval that can be used for all kinds of typographic and layout decisions to create harmony in a visual design for the web. As Tim Brown said at the 2010 Build conference: I think that from that most atomic unit – type – whole experiences can resonate, whole experiences can be harmonious. And whole experiences can have a purpose suited to our design intentions. Once more, with feeling: connectedness As well as modular scales, there are other methods of incorporating musical interval ratios into our work. Setting the ratio of font size to line height in CSS is one such example. We could also create a typographic hierarchy using the same principle and combining several ratios that we know harmonize well musically in a chord: body { font-size: 75%; } /* =12px = base size or tonic */ h1 { font-size: 32px; font-size: 2.667rem; } /* =32px = 3:8 = major eleventh (C→F↑) */ h2 { font-size: 24px; font-size: 2rem; } /* =24px = 1:2 = octave (C→C↑) */ h3 { font-size: 20px; font-size: 1.667rem; } /* =20px = 3:5 = major sixth (C→A) */ figcaption, small { font-size: 9px; font-size : 0.75rem } /* =9px = 3:4 = perfect fourth (C→F) */ Whoa! Hold your reindeer, Santa! How can we know what interval combinations work well together to form chords? Well, I’m a classically trained musician, so perhaps I have an advantage. To avoid a long, technically complex digression into musical harmony, here are a few basic combinations of intervals that are harmonious in one way or another: unison; major third; perfect fifth; octave unison; perfect fourth; major sixth; octave unison; minor third; minor sixth; octave unison; minor third; diminished fifth; major sixth; octave This isn’t to say that other combinations can’t be used to interesting effect and particular purpose – they surely can – but I have to make sure there’s something left for you to experiment with in the wee small hours over the holiday. Bear in mind, though, were I to play you two notes from the same scale to form a minor second, for example, you’d probably say it was dissonant and maybe that quality of the 15:16 ratio would be translated to the design. In the typographic hierarchy above, you’ll notice I used an interval in the higher octave, which affords a broader range of ratios while retaining the harmony. Thus, a perfect fifth (2:3) becomes a major twelfth (1:3), or a major sixth (3:5) becomes a major thirteenth (3:10). The harmonic ratios can obviously be used as proportions for layout as well, in several different ways: image width and height (for example, 450×800px = 9:16 = minor seventh) main content to page width (67%:100% = 2:3 = perfect fifth) page width to viewport width (80%:100% = 4:5 = major third) One great benefit of using such ratios in web design work is that they can be applied in responsive web design. Proportional values, based on percentages or equivalent em units, will scale with changing viewports, so your layout and image proportions can be maintained or deliberately changed, as we’re about to find out, across devices. Small speakers, tall speakers: binding to the device The musical interval ratios also provide an opportunity, not only to create connectedness between the parts of a layout, but to bind the content to a device – that elusive antiphonal geometry. Just as a textblock and page resonate together, so too can web content and the screen. Earlier, I mentioned that several common screen aspect ratios match musical interval ratios. It would seem, then, that we have a set of proportions that we can use in different ways to establish and retain a sense of harmony that can be based on and change with those contexts. Using musical interval ratios, we can bind the display of our content to the device it’s displayed on. If you haven’t met already, let me introduce you to the device-aspect-ratio property of CSS media queries. @media only screen and (device-aspect-ratio: 3/4) { } @media only screen and (device-aspect-ratio: 480/640) { } @media only screen and (device-aspect-ratio: 600/800) { } @media only screen and (device-aspect-ratio: 768/1024) { } Regardless of the precise pixel values, each of these media queries would apply to devices whose display area has an aspect ratio of 3:4. It works by comparing the device-width with the device-height. (It’s not to be confused with aspect-ratio, which is defined by the width and height of the browser within the device.) The values in the media query are always presented as width/height, with portrait being the default orientation for smartphones and tablets; that is, to match an iPhone screen, you’d use device-aspect-ratio: 2/3, not 3/2, which won’t work. Here’s a table of the musical intervals with their corresponding screens. Name device-aspect-ratio Screens Common resolutions (pixels) major third 5/4 TFT LCD computer screens 1,280×1,024 perfect fourth 3/4 or 4/3 iPad, Kindle and other tablets, PDAs 320×240, 768×1,024 perfect fifth 2/3 iPhone, iPod Touch 320×480, 640×960 minor sixth 8/5 (16/10) Many widescreens 1,152×720, 1,440×900, 1,920×1,200 major sixth 3/5 Many smartphones 240×400, 480×800 minor seventh 16/9 or 9/16 Many widescreens and some smartphones 720×1,280, 1,366×768, 1,920×1,080, 2,560×1,440 [You might argue that I’m playing fast and loose with the ratios. I suppose, mathematically speaking, 9:16 is not the same as 16:9: I’m no expert. But let’s not throw the baby out with the bath water, particularly at Christmas.] With this in mind, we can begin to write media queries that will influence various typographic and layout values in line with the aspect ratios of specific screens and in combination with em-based min-width queries that work from smaller, mobile screens to larger, desktop screens. Here’s a very simple demo page with only some text, an image with a caption and a little basic layout: no seasonal overindulgence here. Demo: Sample page using device-aspect-ratio media queries based on musical interval ratios Our initial styles for all devices are based on the perfect fifth, with the major third and octave rounding things out into a harmonious whole, whether or not media queries are supported. For example: html { font-size: 100%; line-height: 1.5; } /* font-size:line-height = 16:24 = 2:3 = perfect fifth */ h1 { font-size: 32px; font-size: 2rem; line-height: 1.25; } /* font-size:line-height = 32:40 = 4:5 = major third body:h1 = 16:32 = 1:2 = octave */ While we should really consider methods of delivering images appropriate to the screen size, let’s just stick to a single image for all devices. But why don’t we change its aspect ratio from 4:3 to 3:2, to fit with our harmonic scheme? It’s easy enough to do with overflow:hidden on the <figure> element to hide a part of the image, and a negative margin fudge: figure img { margin: -8.5% 0 0 0; width: 100%; max-width: 100%; } Our first break point targets devices 320 pixels wide with an aspect ratio of 2:3, namely the iPhone and iPod Touch: /* 320px = 20×16 */ @media only screen and (min-width: 20em) and (device-aspect-ratio: 2/3) { } We’re actually already there, of course, as the intervals we’ve chosen resonate with this aspect ratio – the content is already bound to the device. Our next media query, then, will make some changes to match a different ratio, the major sixth (3:5), which is same as that of many smartphones: /* 480px = 30×16 */ @media only screen and (min-width: 30em) and (device-aspect-ratio: 3/5) { } A different aspect ratio might require a change in harmony. For devices with these proportions, we’ll now use the perfect fourth (3:4) and the major sixth (3:5) along with the octave we already have to create a new resonating harmony. For instance, a slightly wider screen means we can increase the line-height to aid the legibility of longer lines: html { line-height: 1.667; } /* font-size:line-height = 16:26.672 = 3:5 = major sixth */ h1 { font-size: 32px; font-size: 2rem; line-height: 1.667; } /* font-size:line-height = 32:53.333 = 3:5 = major sixth body:h1 = 16:32 = 1:2 = octave */ and we can remove the negative margin to display our 4:3 image in its entirety. Each screen displays content styled using relationships related to its own proportions. On the left, an iPhone 4 (2:3); on the right, a Samsung Nexus S (3:5). Your mileage may vary. Another device, another media query. At 768 pixels, screens are wide enough to add columns. The ratios we’ve used for the 3:5 screens include the perfect fourth (3:4) so we don’t need to change any of the font measurements, but we can base the proportions of the columns on the major sixth interval: article { float: left; width: 56%; } /* width of main column 3:5 (60% of 100%, major sixth) incorporating gutter width */ aside { float : right; width : 36%; } On devices with a 3:4 aspect ratio, this works even better in landscape orientation. While not every screen over 768 pixels wide will have 3:4 proportions, the range of intervals informing the design ensure harmonious relationships between the different parts of the layout. For wide screens proper (break point at 1,280 pixels) we can employ a new set of harmonious intervals. Many laptop and desktop screens have a 16:10 aspect ratio, which boils down to 8:5, equivalent to the minor sixth (5:8). Combined with a minor third (5:6) and the octave (1:2), this creates a new harmony appropriate to these devices. Let’s increase the font size and change the image’s aspect ratio to match: html { font-size: 120%; line-height: 1.6; } /* font-size increased for wider screens from 16px to 19.2px (5:6 = minor third) font-size:line-height = 19.2:30.72 = 5:8 = minor sixth */ figure img { margin: -12.5% 0 0 ; } /* using -ve margin combined with overflow:hidden on the figure element to crop the image from 4:3 to 8:5 = minor sixth */ A wide screen with a 8:5 (16:10) aspect ratio and an image to match. With more pixels at our disposal, we can also now use the musical interval ratios to determine the width of the layout, and change the column proportions as well: section { margin: 0 auto; width: 83.333%; } /* content width:screen width = 5:6 = minor third */ article { width: 60%; } /* width of main column 5:8 (62.5% of 100%, minor sixth) incorporating gutter width */ aside { width: 35%; } With some carefully targeted media queries, we can begin to reach towards fulfilling the second and third tenets of Boulton’s new canon for web design: connecting the parts of content through relationships embodied in the layout design; and binding the content to the devices people use to access it. Coda Musical interval ratios and screen aspect ratios reveal more than convenient correspondence. These proportions work on a deep aesthetic level. Much is claimed for the golden ratio φ, but none of the screens pervading our lives use it. Perhaps that’s an accident of technology, but can making screens to φ’s proportions be more difficult or expensive than 2:3 or 3:4 or 16:10? Here, then, is not just one but a set of proportions with a uniquely human focus, originating in nature, recognized in antiquity, fundamental still. We find music to be an art steeped with meaning, yet, unlike literary and representational arts, purely instrumental music has no obvious semantic content. It boasts an ability to express emotions while remaining an abstract art in some sense, which makes it very like design. These days, we’re rightly encouraged to design for emotion, to make our users’ experience meaningful, seductive, delightful. Using musical ideas and principles in our designs can help achieve those ends. Let’s not be naïve, of course; designing web pages is even less like composing music than it’s like designing for print. In visual design, the eye will always be sovereign to the ear; following these principles will only get us so far. We cannot truly claim that a carefully composed web page layout will have the same qualities and effect as any musical patterns that inform it. In music, a set of intervals is always harmonious in relation to other sets of intervals: music rarely stands still. What aspect ratios will future screens take? Already today there is great variation in devices and support for media queries (and within that, support for device-aspect-ratio). And what of non-western musical traditions? Or rhythm, form, tempo and dynamics? What I’ve demonstrated above is only a suggestion, a tentative exploration of one possible way forward. But as our discipline matures and we become more articulate about what we do, we must look longer and deeper into areas of human endeavour already rich with value. Music is a fertile ground to explore and has the potential to yield up new approaches for web design. Footnotes Just intonation is a system of tuning that uses small integers to describe the musical intervals, based initially on the perfect fifth, that most consonant of intervals. Simple instruments such as vibrating strings and natural horns, as well as unaccompanied voices, tend to fall into just intonation naturally. 2011 Owen Gregory owengregory 2011-12-09T00:00:00+00:00 https://24ways.org/2011/composing-the-new-canon/ design
12 Untangling Web Typography When I was a carpenter, I noticed how homeowners often had this deer-in-the-headlights look when the contractor I worked for would ask them to make tons of decisions, seemingly all at once. Square or subway tile? Glass or ceramic? Traditional or modern trim details? Flat face or picture frame cabinets? Real wood or laminate flooring? Every day the decisions piled up and were usually made in the context of that room, or that part of that room. Rarely did the homeowner have the benefit of taking that particular decision in full view of the larger context of the project. And architectural plans? Sure, they lay out the broad strokes, but there is still so much to decide. Typography is similar. Designers try to make sites that are easy to use and understand visually. They labour over the details of line height, font size, line length, and font weights. They consider the relative merits of different typographical scales for applications versus content-driven sites. Frequently, designers consider all of this in the context of one page, feature, or view of an application. They are asked to make a million tiny decisions. Sometimes designers just bump up the font size until it looks right. I don’t see anything wrong with that. Instincts are important. Designing in context is easier. It’s OK to leave the big picture until later. Design a bunch of things, and then look for the patterns. You can’t always know everything up front. How does the current feature relate to all the other features on the site? For a large site, just like for a substantial remodel, the number of decisions you would need to internalize to make that knowable would be prohibitively large. When typography goes awry I should be honest. I know very little about typography. I struggle to understand vertical rhythm and the math in Tim Ahrens’s talks about the interaction between type design and rendering technology kind of melted my brain. I have an unusual perspective because I’m not the one making the design decisions, but I am the one implementing them and often cleaning up when a project goes off the rails. I’ve seen projects with thousands of font-size declarations and headings. One project even had over ten thousand margin declarations. So while I appreciate creative exploration, I’m also eager to establish patterns in typography and make sure we aren’t choosing not to choose. Or, choosing all the things. Analyzing a site’s typography Most of my projects start out with an evaluation of the client’s existing CSS. I look for duplication in the CSS by using Grep, though functionality is landing soon in CSS Lint to do the same thing automatically. The goal is to find the underlying missing abstractions that, once in place, would allow developers to create new functionality without needing to write additional CSS. In addition to that, my team and I would comb through each site (generally, around ten pages is enough to get the big picture), and take screenshots of each of the components we found. In this way, we could look for subtle visual differences that were unlikely to add value to the user. By correcting these differences, we could help make the design more consistent, and at the same time the code leaner and more performant. Typography is much like a homeowner who chooses to incorporate too many disparate design elements, pairing a mid-century modern sofa with flowered country cottage curtains. Often the typography of a site ends up collecting an endless array of new typefaces as the site’s overall styles evolve. Designers come and go on a project, and eventually no one can remember how the 16px Verdana got into the codebase. Automation We used to do this work by hand. It was incredibly tedious. We’d go through the site, taking screenshots and meticulously documenting the style information we found. We didn’t have to do that many times before it became incredibly clear that the task needed to be automated. So we built a little tool called the Type-o-matic that could do it for us. To try it on your site: Download and install the Firebug extension to Firefox Download and install the Type-o-matic extension to Firebug (I know, I fully intend to port it to Chrome) Now, visit the site you’d like to test Right click and choose Inspect element with Firebug Now click on the Typography tab Click Persist Click Generate Report Choose which pages to analyze (we’ve found that ten is a good number to get the big picture, but you can analyze as many as you’d like — it will even work on just one page!) Now navigate to other pages, and on each subsequent page, click Generate Report The table of results can be a bit difficult to interact with, so you can always click Copy to clipboard, and copy the results (JSON). A screenshot of Type-o-matic in action What does this data mean? When you’ve analyzed as many pages or different views as you’d like, you’ll start to see some interesting patterns emerge in the data. In the right-hand column, you’ll see examples of how each kind of typography we found has been used in a real context on your site. It is organized by color and then by size so you can easily see how you are using typography. The next thing you’ll want to take a look at is in the first column, called “Count”. We’ve counted how many times you’ve used each combination of typographical styles. This can be incredibly helpful when deciding which styles were intentional, versus one-off color pick errors or experiments that never got removed from the code base. If you’ve used one color blue 1,400 times, and another just 23, it’s pretty obvious which is more in line with broader site-wide styles. Consistency before perfection It can be really tempting to try to make everything perfect — to try to make every decision final. When you use the data you can collect from this tool, I’d recommend trying to get to consistent before you try to make things perfect. Stop using fifteen different shades of blue type first, and then if you want to change to a new blue, go for it! You’ll be able to make design changes much more easily once you’ve reduced the total number of typographical styles you rely on. Lower the importance of the decisions you are making. Our sites, like ourselves, are always a work in progress. Or, as a carpenter I used to work with said, “You’re not building a fucking piano.” We’re not building houses. We can choose one typeface today and a different one tomorrow. It is OK to experiment. Be brave. 2013 Nicole Sullivan nicolesullivan 2013-12-20T00:00:00+00:00 https://24ways.org/2013/untangling-web-typography/ design
91 Infinite Canvas: Moving Beyond the Page Remember Web 2.0? I do. In fact, that phrase neatly bifurcates my life on the internet. Pre-2.0, I was occupied by chatting on AOL and eventually by learning HTML so I could build sites on Geocities. Around 2002, however, I saw a WYSIWYG demo in Dreamweaver. The instructor was dragging boxes and images around a canvas. With a few clicks he was able to build a dynamic, single-page interface. Coming from the world of tables and inline HTML styles, I was stunned. As I entered college the next year, the web was blossoming: broadband, Wi-Fi, mobile (proud PDA owner, right here), CSS, Ajax, Bloglines, Gmail and, soon, Google Maps. I was a technology fanatic and a hobbyist web developer. For me, the web had long been informational. It was now rapidly becoming something else, something more: sophisticated, presentational, actionable. In 2003 we watched as the internet changed. The predominant theme of those early Web 2.0 years was the withering of Internet Explorer 6 and the triumph of web standards. Upon cresting that mountain, we looked around and collectively breathed the rarefied air of pristine HMTL and CSS, uncontaminated by toxic hacks and forks – only to immediately begin hurtling down the other side at what is, frankly, terrifying speed. Ten years later, we are still riding that rocket. Our days (and nights) are spent cramming for exams on CSS3 and RWD and Sass and RESS. We are the proud, frazzled owners of tiny pocket computers that annihilate the best laptops we could have imagined, and the architects of websites that are no longer restricted to big screens nor even segregated by device. We dragoon our sites into working any time, anywhere. At this point, we can hardly ask the spec developers to slow down to allow us to catch our breath, nor should we. It is, without a doubt, a most wonderful time to be a web developer. But despite the newfound luxury of rounded corners, gradients, embeddable fonts, low-level graphics APIs, and, glory be, shadows, the canyon between HTML and native appears to be as wide as ever. The improvements in HTML and CSS have, for the most part, been conveniences rather than fundamental shifts. What I’d like to do now, if you’ll allow me, is outline just a few of the remaining gaps that continue to separate web sites and applications from their native companions. What I’d like for Christmas There is one irritant which is the grandfather of them all, the one from which all others flow and have their being, and it is, simply, the page refresh. That’s right, the foundational principle of the web is our single greatest foe. To paraphrase a patron saint of designers everywhere, if you see a page refresh, we blew it. The page refresh brings with it, of course, many noble and lovely benefits: addressability, for one; and pagination, for another. (See also caching, resource loading, and probably half a dozen others.) Still, those concerns can be answered (and arguably answered more compellingly) by replacing the weary page with the young and hearty document. Flash may be dead, but it has many lessons yet to bequeath. Preparing a single document when the site loads allows us to engage the visitor in a smooth and engrossing experience. We have long known this, of course. Twitter was not the first to attempt, via JavaScript, to envelop the user in a single-page application, nor the first to abandon it. Our shared task is to move those technologies down the stack, to make them more primitive, so that the next Twitter can be built with the most basic combination of HTML and CSS rather than relying on complicated, slow, and unreliable scripted solutions. So, let’s take a look at what we can do, right now, that we might have a better idea of where our current tools fall short. A print magazine in HTML clothing Like many others, I suspect, one of my earliest experiences with publishing was laying out newsletters and newspapers on a computer for print. If you’ve ever used InDesign or Quark or even Microsoft Publisher, you’ll remember reflowing content from page to page. The advent of the internet signaled, in many ways, the abandonment of that model. Articles were no longer constrained by the physical limitations of paper. In shedding our chains, however, it is arguable that we’ve lost something useful. We had a self-contained and complete package, a closed loop. It was a thing that could be handled and finished, and doing so provided a sense of accomplishment that our modern, infinitely scrolling, ever-fractal web of content has stolen. For our purposes today, we will treat 24 ways as the online equivalent of that newspaper or magazine. A single year’s worth of articles could easily be considered an issue. Right now, navigating between articles means clicking on the article you’d like to view and being taken to that specific address via a page reload. If Drew wanted to, it wouldn’t be difficult to update the page in place (via JavaScript) and change the address (again via JavaScript with the History API) to reflect the new content found at the new location. But what if Drew wanted to do that without JavaScript? And what if he wanted the site to not merely load the content but actually whisk you along the page in a compelling and delightful way, à la the Mag+ demo we all saw a few years ago when the iPad was first introduced? Uh, no. We’re all familiar with websites that have attempted to go beyond the page by weaving many chunks of content together into a large document and for good reason. There is tremendous appeal in opening and exploring the canvas beyond the edges of our screens. In one rather straightforward example from last year, Mozilla contacted Full Stop to build a website promoting Aza Raskin’s proposal for a set of Creative Commons-style privacy icons. Like a lot of the sites we build (including our own), the amount of information we were presenting was minimal. In these instances, we encourage our clients to consider including everything on a single page. The result was a horizontally driven site that was, if not whimsical, at least clever and attractive to the intended audience. An experience that is taken for granted when using device-native technology is utterly, maddeningly impossible to replicate on the web without jumping through JavaScript hoops. In another, more complex example, we again had the pleasure of working with Aza earlier this year, this time on a redesign of the Massive Health website. Our assignment was to design and build a site that communicated Massive’s commitment to modern personal health. The site had to be visually and interactively stunning while maintaining a usable and clear interface for the casual visitor. Our solution was to extend the infinite company logo into a ribbon that carried the visitor through the site narrative. It also meant we’d be asking the browser to accommodate something it was never designed to handle: a non-linear design. (Be sure to play around. There’s a lot going on under the hood. We were also this close to a ZUI, if WebKit didn’t freak out when pages were scaled beyond 10×.) Despite the apparent and deliberate design simplicity, the techniques necessary to implement it are anything but. From updating the URL to moving the visitor from section to section, we’re firmly in JavaScript territory. And that’s a shame. What can we do? We might not be able to specify these layouts in HTML and CSS just yet, but that doesn’t mean we can’t learn a few new tricks while we wait. Let’s see how close we can come to recreating the privacy icons design, the Massive design, or the Mag+ design without resorting to JavaScript. A horizontally paginated site The first thing we’re going to need is the concept of a page within our HTML document. Using plain old HTML and CSS, we can stack a series of <div>s sideways (with a little assist from our new friend, the viewport-width unit, not that he was strictly necessary). All we need to know is how many pages we have. (And, boy, wouldn’t it be nice to be able to know that without having to predetermine it or use JavaScript?) .window { overflow: hidden; width: 100%; } .pages { width: 200vw; } .page { float: left; overflow: hidden; width: 100vw; } If you look carefully, you’ll see that the conceit we’ll use in the rest of the demos is in place. Despite the document containing multiple pages, only one is visible at any given time. This allows us to keep the user focused on the task (or content) at hand. By the way, you’ll need to use a modern, WebKit-based browser for these demos. I recommend downloading the WebKit nightly builds, Chrome Canary, or being comfortable with setting flags in Chrome. A horizontally paginated site, with transitions Ah, here’s the rub. We have functional navigation, but precious few cues for the user. It’s not much good shoving the visitor around various parts of the document if they don’t get the pleasant whooshing experience of the journey. You might be thinking, what about that new CSS selector, target-something…? Well, my friend, you’re on the right track. Let’s test it. We’re going to need to use a bit of sleight of hand. While we’d like to simply offset the containing element by the number of pages we’re moving (like we did on Massive), CSS alone can’t give us that information, and that means we’re going to need to fake it by expanding and collapsing pages as you navigate. Here are the bits we’re going to need: .page { -webkit-transition: width 1s; // Naturally you're going to want to include all the relevant prefixes here float: left; left: 0; overflow: hidden; position: relative; width: 100vw; } .page:not(:target) { width: 0; } Ah, but we’re not fooling anyone with that trick. As soon as you move beyond a single page, the visitor’s disbelief comes tumbling down when the linear page transitions are unaffected by the distance the pages are allegedly traveling. And you may have already noticed an even more fatal flaw: I secretly linked you to the first page rather than the unadorned URL. If you visit the same page with no URL fragment, you get a blank screen. Sure, we could force a redirect with some server-side trickery, but that feels like cheating. Perhaps if we had the CSS4 subject selector we could apply styles to the parent based on the child being targeted by the URL. We might also need a few more abilities, like determining the total number of pages and having relative sibling selectors (e.g. nth-sibling), but we’d sure be a lot closer. A horizontally paginated site, with transitions – no cheating Well, what other cards can we play? How about the checkbox hack? Sure, it’s a garish trick, but it might be the best we can do today. Check it out. label { cursor: pointer; } input { display: none; } input:not(:checked) + .page { max-height: 100vh; width: 0; } Finally, we can see the first page thanks to the state we are able to set on the appropriate radio button. Of course, now we don’t have URLs, so maybe this isn’t a winning plan after all. While our HTML and CSS toolkit may feel primitive at the moment, we certainly don’t want to sacrifice the addressability of the web. If there’s one bedrock principle, that’s it. A horizontally paginated site, with transitions – no cheating and a gorgeous homepage Gorgeous may not be the right word, but our little magazine is finally shaping up. Thanks to the CSS regions spec, we’ve got an exciting new power, the ability to begin an article in one place and bend it to our will. (Remember, your everyday browser isn’t going to work for these demos. Try the WebKit nightly build to see what we’re talking about.) As with the rest of the examples, we’re clearly abusing these features. Off-canvas layouts (you can thank Luke Wroblewski for the name) are simply not considered to be normal patterns… yet. Here’s a quick look at what’s going on: .excerpt-container { float: left; padding: 2em; position: relative; width: 100%; } .excerpt { height: 16em; } .excerpt_name_article-1, .page-1 .article-flow-region { -webkit-flow-from: article-1; } .article-content_for_article-1 { -webkit-flow-into: article-1; } The regions pattern is comprised of at least three components: a beginning; an ending; and a source. Using CSS, we’re able to define specific elements that should be available for the content to flow through. If magazine-style layouts are something you’re interested in learning more about (and you should be), be sure to check out the great work Adobe has been doing. Looking forward, and backward As designers, builders, and consumers of the web, we share a desire to see the usability and enjoyability of websites continue to rise. We are incredibly lucky to be working in a time when a three-month-old website can be laughably outdated. Our goal ought to be to improve upon both the weaknesses and the strengths of the web platform. We seek not only smoother transitions and larger canvases, but fine-grained addressability. Our URLs should point directly and unambiguously to specific content elements, be they pages, sections, paragraphs or words. Moreover, off-screen design patterns are essential to accommodating and empowering the multitude of devices we use to access the web. We should express the desire that interpage links take advantage of the CSS transitions which have been put to such good effect in every other aspect of our designs. Transitions aren’t just nice to have, they’re table stakes in the highly competitive world of native applications. The tools and technologies we have right now allow us to create smart, beautiful, useful webpages. With a little help, we can begin removing the seams and sutures that bind the web to an earlier, less sophisticated generation. 2012 Nathan Peretic nathanperetic 2012-12-21T00:00:00+00:00 https://24ways.org/2012/infinite-canvas-moving-beyond-the-page/ code
75 A Harder-Working Class Class is only becoming more important. Focusing on its original definition as an attribute for grouping (or classifying) as well as linking HTML to CSS, recent front-end development practices are emphasizing class as a vessel for structured, modularized style packages. These patterns reduce the need for repetitive declarations that can seriously bloat file sizes, and instil human-readable understanding of how the interface, layout, and aesthetics are constructed. In the next handful of paragraphs, we will look at how these emerging practices – such as object-oriented CSS and SMACSS – are pushing the relevance of class. We will also explore how HTML and CSS architecture can be further simplified, performance can be boosted, and CSS utility sharpened by combining class with the attribute selector. A primer on attribute selectors While attribute selectors were introduced in the CSS 2 spec, they are still considered rather exotic. These well-established and well-supported features give us vastly improved flexibility in targeting elements in CSS, and offer us opportunities for smarter markup. With an attribute selector, you can directly style an element based on any of its unique – or uniquely shared – attributes, without the need for an ID or extra classes. Unlike pseudo-classes, pseudo-elements, and other exciting features of CSS3, attribute selectors do not require any browser-specific syntax or prefix, and are even supported in Internet Explorer 7. For example, say we want to target all anchor tags on a page that link to our homepage. Where otherwise we might need to manually identify and add classes to the HTML for these specific links, we could simply write: [href=index.html] { } This selector reads: target every element that has an href attribute of “index.html”. Attribute selectors are more faceted, though, as they also give us some very simple regular expression-like logic that helps further narrow (or widen) a selector’s scope. In our previous example, what if we wanted to also give indicative styles to any anchor tag linking to an external site? With no way to know what the exact href value would be for every external link, we need to use an expression to match a common aspect of those links. In this case, we know that all external links need to start with “http”, so we can use that as a hook: [href^=http] { } The selector here reads: target every element that has an href attribute that begins with “http” (which will also include “https”). The ^= means “starts with”. There are a few other simple expressions that give us a lot of flexibility in targeting elements, and I have found that a deep understanding of these and other selector types to be very useful. The class-attribute selector By matching classes with the attribute selector, CSS can be pushed to accomplish some exciting new feats. What I call a class-attribute selector combines the advantages of classes with attribute selectors by targeting the class attribute, rather than a specific class. Instead of selecting .urgent, you could select [class*=urgent]. The latter may seem like a more verbose way of accomplishing the former, but each would actually match two subtly different groups of elements. Eric Meyer first explored the possibility of using classes with attribute selectors over a decade ago. While his interest in this technique mostly explored the different facets of the syntax, I have found that using class-attribute selectors can have distinct advantages over either using an attribute selector or a straightforward class selector. First, let’s explore some of the subtleties of why we would target class before other attributes: Classes are ubiquitous. They have been supported since the HTML 4 spec was released in 1999. Newer attributes, such as the custom data attribute, have only recently begun to be adopted by browsers. Classes have multiple ways of being targeted. You can use the class selector or attribute selector (.classname or [class=classname]), allowing more flexible specificity than resorting to an ID or !important. Classes are already widely used, so adding more classes will usually require less markup than adding more attributes. Classes were designed to abstractly group and specify elements, making them the most appropriate attribute for styling using object-oriented methods (as we will learn in a moment). Also, as Meyer pointed out, we can use the class-attribute selector to be more strict about class declarations. Of these two elements: <h2 class="very urgent"> <h2 class="urgent"> …only the second h2 would be selected by [class=urgent], while .urgent would select both. The use of = matches any element with the exact class value of “urgent”. Eric explores these nuances further in his series on attribute selectors, but perhaps more dramatic is the added power that class-attribute selectors can bring to our CSS. More object-oriented, more scalable and modular Nicole Sullivan has been pushing abstracted, object-oriented thinking in CSS development for years now. She has shared stacks of knowledge on how behemoth sites have seen impressive gains in maintenance overhead and CSS file sizes by leaning heavier on classes derived from common patterns. Jonathan Snook also speaks, writes and is genuinely passionate about improving our markup by using more stratified and modular class name conventions. With SMACSS, he shows this to be highly useful across sites – both complex and simple – that exhibit repeated design patterns. Sullivan and Snook both push the use of class for styling over other attributes, and many front-end developers are fast advocating such thinking as best practice. With class-attribute selectors, we can further abstract our CSS, pushing its scalability. In his chapter on modules, Snook gives the example of a .pod class that might represent a certain set of styles. A .pod style set might be used in varying contexts, leading to CSS that might normally look like this: .pod { } form .pod { } aside .pod { } According to Snook, we can make these styles more portable by targeting more verbose classes, rather than context: .pod { } .pod-form { } .pod-sidebar { } …resulting in the following HTML: <div class="pod"> <div class="pod pod-form"> <div class="pod pod-sidebar"> This divorces the <div>’s styles from its context, making it applicable to any situation in which it is needed. The markup is clean and portable, and the classes are imbued with meaning as to what module they belong to. Using class-attribute selectors, we can simplify this further: [class*=pod] { } .pod-form { } .pod-sidebar { } The *= tells the browser to look for any element with a class attribute containing “pod”, so it matches “pod”, “pod-form”, “pod-sidebar”, etc. This allows only one class per element, resulting in simpler HTML: <div class="pod"> <div class="pod-form"> <div class="pod-sidebar"> We could further abstract the concept of “form” and “sidebar” adjustments if we knew that each of those alterations would always need the same treatment. /* Modules */ [class*=pod] { } [class*=btn] { } /* Alterations */ [class*=-form] { } [class*=-sidebar] { } In this case, all elements with classes appended “-form” or “-sidebar” would be altered in the same manner, allowing the markup to stay simple: <form> <h2 class="pod-form"> <a class="btn-form" href="#"> <aside> <h2 class="pod-sidebar"> <a class="btn-sidebar" href="#"> 50+ shades of specificity Classes are just powerful enough to override element selectors and default styling, but still leave room to be trumped by IDs and !important styles. This makes them more suitable for object-oriented patterns and helps avoid messy specificity issues that can not only be a pain for developers to maintain, but can also affect a site’s performance. As Sullivan notes, “In almost every case, classes work well and have fewer unintended consequences than either IDs or element selectors”. Proper use of specificity and cascade is crucial in building straightforward, efficient CSS. One interesting aspect of attribute selectors is that they can be compounded for increasing levels of specificity. Attribute selectors are assigned a specificity level of ten, the same as class selectors, but both class and attribute selectors can be chained together, giving them more and more specificity with each link. Some examples: .box { } /* Specificity of 10 */ .box.promo { } /* Specificity of 20 */ [class*=box] { } /* Specificity of 10 */ [class*=box][class*=promo] { } /* Specificity of 20 */ You can chain both types together, too: .box[class*=promo] { } /* Specificity of 20 */ I was amused to find, though, that you can chain the exact same class and attribute selectors for infinite levels of specificity .box { } /* Specificity of 10 */ .box.box { } /* Specificity of 20 */ .box.box.box { } /* Specificity of 30 */ [class*=box] { } /* Specificity of 10 */ [class*=box][class*=box] { } /* Specificity of 20 */ [class*=box][class*=box][class*=box] { } /* Specificity of 30 */ .box[class*=box].box[class*=box] { } /* Specificity of 40 */ To override .box styles for promo, we wouldn’t need to add an ID, change the order of .promo and .box in the CSS, or resort to an !important style. Granted, any issue that might need this fine level of specificity tweaking could probably be better solved with clever cascades, but having options never hurts. Smarter CSS One of the most powerful aspects of the class-attribute selector is its ability to expand the simple logic found in CSS. When developing Gridset (an online tool for building grids and outputting them as CSS), I realized that with the right class name conventions, class-attribute selectors would allow the CSS to be smart enough to automatically adjust for column offsets without the need for extra classes. This imbued the CSS output with logic that other frameworks lacked, and makes a developer’s job much easier. Say you need an element that spans column five (c5) to column six (c6) on your grid, and is preceded by an element spanning column one (c1) to column three (c3). The CSS can anticipate such a scenario: .c1-c3 + .c5-c6 { margin-left: 25%; /* …or the width of column four plus two gutter widths */ } …but to accommodate all of the margin offsets that could span that same gap, we would need to write a rather protracted list for just a six column grid: .c1-c3 + .c5-c6, .c1-c3 + .c5, .c2-c3 + .c5-c6, .c2-c3 + .c5, .c3 + .c5-c6, .c3 + .c5 { margin-left: 25%; } Now imagine how the verbosity compounds when we repeat this type of declaration for every possible margin in a grid. The more columns added to the grid, the longer this selector list would get, too, making the CSS harder for the developer to maintain and slowing the load time. Using class-attribute selectors, though, this can be much simpler: [class*=c3] + [class*=c5] { margin-left: 25%; } I’ve detailed how we extract as much logic as possible from as little CSS as needed on the Gridset blog. More flexible selectors In a recent project, I was working with Drupal-generated classes to change styles for certain special pages on a site. Without being able to change the code base, I was left trying to find some specific aspect of the generated HTML to target. I noticed that every special page was given a prefixed class, unique to the page, resulting in CSS like this: .specialpage-about, .specialpage-contact, .specialpage-info, … …and the list kept growing with each new special page. Such bloat would lead to problems down the line, and add development overhead to editorial decisions, which was a situation we were trying to avoid. I was easily able to fix this, though, with a concise class-attribute selector: [class*=specialpage-] The CSS was now flexible enough to accommodate both the editorial needs of the client, and the development restrictions of the CMS. Selector performance As Snook tells us in his chapter on Selector Performance, selectors are read by the browser from right to left, matching every element that adheres to each rule (or part of the selector). The more specific we can make the right-most rules – and every other part of your selectors – the more performant your CSS will be. So this selector: .home-page .promo .main-header …would be more performant than: .home-page div header …because there are likely many more header and div elements on the page, but not so many elements with those specific classes. Now, the class-attribute selector could be more general than a class selector, but not by much. I ran numerous tests based on the work of Steve Souders (and a few others) to test a class-attribute selector against a normal class selector. Given that Javascript will freeze during style rendering, I created a script that will add, then remove, a stylesheet on a page 5000 times, and measure only the time that elapses during the rendering freeze. The script runs four tests, essentially: one where a class selector and class-attribute Selector match a single element, and one they match multiple elements on the page. After running the test over 100 times and averaging the results, I have not seen a significant difference in rendering times. (As of this writing, the class-attribute selector has been 0.398% slower on average.) View the results here. Given the sheer amount of bytes potentially saved by reducing selector lists, though, I am confident class-attribute selectors could shorten load times on larger sites and, at the very least, save precious development time. Conclusion With its flexibility and broad remit, class has at times been derided as too lenient, allowing CMSes and lazy developers to fill its values with presentational hacks or verbose gibberish. There have even been calls for an early retirement. Class continues, though, to be one of our most crucial tools. Front-end developers are rightfully eager to expand production abilities through innovations such as Sass or LESS, but this should not preclude us from honing the tools we already know as well. Every technique demonstrated in this article was achievable over a decade ago and most of the same thinking could be applied to IDs, rels, or any other attribute (though the reasons listed above give class an edge). The recent advent of methods such as object-oriented CSS and SMACSS shows there is still much room left to expand what simple HTML and CSS can accomplish. Progress may not always be found in the innovation of our tools, but through sharpening our understanding of them. 2012 Nathan Ford nathanford 2012-12-15T00:00:00+00:00 https://24ways.org/2012/a-harder-working-class/ code
126 Intricate Fluid Layouts in Three Easy Steps The Year of the Script may have drawn attention away from CSS but building fluid, multi-column, cross-browser CSS layouts can still be as unpleasant as a lump of coal. Read on for a worry-free approach in three quick steps. The layout system I developed, YUI Grids CSS, has three components. They can be used together as we’ll see, or independently. The Three Easy Steps Choose fluid or fixed layout, and choose the width (in percents or pixels) of the page. Choose the size, orientation, and source-order of the main and secondary blocks of content. Choose the number of columns and how they distribute (for example 50%-50% or 25%-75%), using stackable and nestable grid structures. The Setup There are two prerequisites: We need to normalize the size of an em and opt into the browser rendering engine’s Strict Mode. Ems are a superior unit of measure for our case because they represent the current font size and grow as the user increases their font size setting. This flexibility—the container growing with the user’s wishes—means larger text doesn’t get crammed into an unresponsive container. We’ll use YUI Fonts CSS to set the base size because it provides consistent-yet-adaptive font-sizes while preserving user control. The second prerequisite is to opt into Strict Mode (more info on rendering modes) by declaring a Doctype complete with URI. You can choose XHTML or HTML, and Transitional or Strict. I prefer HTML 4.01 Strict, which looks like this: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> Including the CSS A single small CSS file powers a nearly-infinite number of layouts thanks to a recursive system and the interplay between the three distinct components. You could prune to a particular layout’s specific needs, but why bother when the complete file weighs scarcely 1.8kb uncompressed? Compressed, YUI Fonts and YUI Grids combine for a miniscule 0.9kb over the wire. You could save an HTTP request by concatenating the two CSS files, or by adding their contents to your own CSS, but I’ll keep them separate for now: <link href="fonts.css" rel="stylesheet" type="text/css"> <link href="grids.css" rel="stylesheet" type="text/css"> Example: The Setup Now we’re ready to build some layouts. Step 1: Choose Fluid or Fixed Layout Choose between preset widths of 750px, 950px, and 100% by giving a document-wrapping div an ID of doc, doc2, or doc3. These options cover most use cases, but it’s easy to define a custom fixed width. The fluid 100% grid (doc3) is what I’ve been using almost exclusively since it was introduced in the last YUI released. <body> <div id="doc3"></div> </body> All pages are centered within the viewport, and grow with font size. The 100% width page (doc3) preserves 10px of breathing room via left and right margins. If you prefer your content flush to the viewport, just add doc3 {margin:auto} to your CSS. Regardless of what you choose in the other two steps, you can always toggle between these widths and behaviors by simply swapping the ID value. It’s really that simple. Example: 100% fluid layout Step 2: Choose a Template Preset This is perhaps the most frequently omitted step (they’re all optional), but I use it nearly every time. In a source-order-independent way (good for accessibility and SEO), “Template Presets” provide commonly used template widths compatible with ad-unit dimension standards defined by the Interactive Advertising Bureau, an industry association. Choose between the six Template Presets (.yui-t1 through .yui-t6) by setting the class value on the document-wrapping div established in Step 1. Most frequently I use yui-t3, which puts the narrow secondary block on the left and makes it 300px wide. <body> <div id="doc3" class="yui-t3"></div> </body> The Template Presets control two “blocks” of content, which are defined by two divs, each with yui-b (“b” for “block”) class values. Template Presets describe the width and orientation of the secondary block; the main block will take up the rest of the space. <body> <div id="doc3" class="yui-t3"> <div class="yui-b"></div> <div class="yui-b"></div> </div> </body> Use a wrapping div with an ID of yui-main to structurally indicate which block is the main block. This wrapper—not the source order—identifies the main block. <body> <div id="doc3" class="yui-t3"> <div id="yui-main"> <div class="yui-b"></div> </div> <div class="yui-b"></div> </div> </body> Example: Main and secondary blocks sized and oriented with .yui-t3 Template Preset Again, regardless of what values you choose in the other steps, you can always toggle between these Template Presets by toggling the class value of your document-wrapping div. It’s really that simple. Step 3: Nest and Stack Grid Structures. The bulk of the power of the system is in this third step. The key is that columns are built by parents telling children how to behave. By default, two children each consume half of their parent’s area. Put two units inside a grid structure, and they will sit side-by-side, and they will each take up half the space. Nest this structure and two columns become four. Stack them for rows of columns. An Even Number of Columns The default behavior creates two evenly-distributed columns. It’s easy. Define one parent grid with .yui-g (“g” for grid) and two child units with .yui-u (“u” for unit). The code looks like this: <div class="yui-g"> <div class="yui-u first"></div> <div class="yui-u"></div> </div> Be sure to indicate the “first“ unit because the :first-child pseudo-class selector isn’t supported across all A-grade browsers. It’s unfortunate we need to add this, but luckily it’s not out of place in the markup layer since it is structural information. Example: Two evenly-distributed columns in the main content block An Odd Number of Columns The default system does not work for an odd number of columns without using the included “Special Grids” classes. To create three evenly distributed columns, use the “yui-gb“ Special Grid: <div class="yui-gb"> <div class="yui-u first"></div> <div class="yui-u"></div> <div class="yui-u"></div> </div> Example: Three evenly distributed columns in the main content block Uneven Column Distribution Special Grids are also used for unevenly distributed column widths. For example, .yui-ge tells the first unit (column) to take up 75% of the parent’s space and the other unit to take just 25%. <div class="yui-ge"> <div class="yui-u first"></div> <div class="yui-u"></div> </div> Example: Two columns in the main content block split 75%-25% Putting It All Together Start with a full-width fluid page (div#doc3). Make the secondary block 180px wide on the right (div.yui-t4). Create three rows of columns: Three evenly distributed columns in the first row (div.yui-gb), two uneven columns (66%-33%) in the second row (div.yui-gc), and two evenly distributed columns in the thrid row. <body> <!-- choose fluid page and Template Preset --> <div id="doc3" class="yui-t4"> <!-- main content block --> <div id="yui-main"> <div class="yui-b"> <!-- stacked grid structure, Special Grid "b" --> <div class="yui-gb"> <div class="yui-u first"></div> <div class="yui-u"></div> <div class="yui-u"></div> </div> <!-- stacked grid structure, Special Grid "c" --> <div class="yui-gc"> <div class="yui-u first"></div> <div class="yui-u"></div> </div> <!-- stacked grid structure --> <div class="yui-g"> <div class="yui-u first"></div> <div class="yui-u"></div> </div> </div> </div> <!-- secondary content block --> <div class="yui-b"></div> </div> </body> Example: A complex layout. Wasn’t that easy? Now that you know the three “levers” of YUI Grids CSS, you’ll be creating headache-free fluid layouts faster than you can say “Peace on Earth”. 2006 Nate Koechley natekoechley 2006-12-20T00:00:00+00:00 https://24ways.org/2006/intricate-fluid-layouts/ code
123 Fast and Simple Usability Testing Everyone knows by now that they should test the usability of their applications, but still hardly anybody actually does it. In this article I’ll share some tips I’ve picked up for doing usability tests quickly and effectively. Relatively recent tools like Django and Ruby on Rails allow us to develop projects faster and to make significant changes later in the project timeline. Usability testing methods should now be adapted to fit this modern approach to development. When to test In an ideal world usability tests would be carried out frequently from an early stage of the project. Time and budget constraints lead this to be impractical; usability is often the first thing to get dropped from the project plan. If you can only test at one stage in the project, whatever the size, the most valuable time is before your first public beta — leaving long enough to fix issues and not so late that you can’t rethink your scope. There are three main categories of usability test: Testing design mockups Testing a new working application Testing established applications Each category requires a slightly different approach. For small modern web projects you are most likely to be testing a new working application. You will of course have already done functional tests so you won’t be worried about the user breaking things. The main differences between the categories apply in how you word The Script. Testing an established application is the most fun in my opinion. Humans are remarkably adaptable and rapidly develop coping strategies to work around usability issues in software they are forced to use. Uncovering these strategies may lead you to understand previously unspoken needs of your users. Often small changes to the application will have a dramatic affect on their everyday lives. Who to test When you have built a project to scratch your own itch, your intended audience will be people just like you. Test subjects in this case should be easy to find – friends, co-workers etc. This is not always the case; your users may not be like you at all. When they are not, it’s all the more important to run usability tests. Testing on friends, family and co-workers is better than not doing usability tests at all, but it can’t be compared to testing on actual samples of your intended audience. People who would use the system will provide more genuine feedback and deeper insight. Never let your test subjects put themselves in the shoes of your ‘actual’ users. For example, you should discourage comments like “Well, I would do this BUT if I was a bus driver I’d do that”. Users are not qualified to put themselves in the position of others. Inaccurate data is often worse than no data. Aim for five or six test subjects: any more and you probably won’t learn anything new; any less and you’re likely to be overwhelmed by issues stemming from people’s individual personalities. The Script The Script is a single side of A4 (or letter) paper, consisting of questions for your testers and reminders for yourself. Have a balance of task-based questions and expectation analysis. This helps maintain consistency across tests. Expectation analysis is more important for testing designs and new applications: “Where would you find X?”, “What would you expect to happen if you clicked on Y?”. In an established system users will probably know where these things are though it can still be illuminating to ask these questions though phrased slightly differently. Task-based questions involve providing a task for the user to complete. If you are testing an established system it is a good idea to ask users to bring in tasks that they would normally perform. This is because the user will be more invested in the outcome of the task and will behave in a more realistic fashion. When designing tasks for new systems and designs ensure you only provide loose task details for the same reason. Don’t tell testers to enter “Chantelle”; have them use their own name instead. Avoid introducing bias with the way questions are phrased. It’s a good idea to ask for users’ first impressions at the beginning of the test, especially when testing design mockups. “What are the main elements on the page?” or “What strikes you first?”. You script should run for a maximum of 45 minutes. 30-35 minutes is better; after this you are likely to lose their attention. Tests on established systems can take longer as there is more to learn from them. When scheduling the test you will need to leave yourself 5 minutes between each one to collate your notes and prepare for the next. Be sure to run through the script beforehand. Your script should be flexible. It is possible that during the test a trend will come to light that opens up whole new avenues of possible questioning. For example, during one initial test of an established system I noticed that the test subject had been printing off items from the application and placing them in a folder in date order (the system ordered alphabetically). I changed the script to ask future participants in that run, if they ever used external tools to help them with tasks within the system. This revealed a number of interesting issues that otherwise would not have been found. Running the tests Treat your test subjects like hedgehogs. Depending on your target audience they probably feel a little nervous and perhaps even scared of you. So make them a little nest out of straw, stroke their prickles and give them some cat food. Alternatively, reassure them that you are testing the system and that they can’t give a wrong answer. Reward them with a doughnut or jam tart at the end. Try to ensure the test environment is relaxed and quiet, but also as close as possible to the situation where they would actually use the system. Have your subjects talk out loud is very important as you can’t read their minds, but it is a very unnatural process. To loosen up your subjects and get them talking in the way you want them to, try the Stapler Trick. Give them a stapler or similar item and ask them to open it, take the staples out, replace them, shut the stapler and staple some paper – talking all the time about what they see, what they expect to happen, what actually happens and how that matches up. Make them laugh at you. Say how long the test will take up front, and tell your subject why you are doing it. After the test has been completed, conclude by thanking them for their time and assuring them that they were very useful. Then give them the sugary treat. What to look for Primarily, you should look out for incidents where the user stops concentrating on her tasks and starts thinking about the tool and how she is going to use it. For example, when you are hammering in a nail you don’t think about how to use a hammer; good software should be the same. Words like ‘it’ and ‘the system’ and are good indications that the test subject has stopped thinking about the task in hand. Note questioning words, especially where testers question their own judgement, “why can’t I find …”, “I expected to see …” etc. as this indicates that the work flow for the task may have broken down. Also keep an eye on occasions where the user completely fails to do a task. They may need some prompting to unstick them, but you should be careful not to bias the test. These should be the highest priority issues for you to fix. If users recover from getting stuck, make a note of how they recovered. Prolonged periods of silence from the test subject may also require prompting as they should be talking all the time. Ask them what they are thinking or looking for but avoid words like ‘try’ (e.g. ‘what are you trying to do?’) as this implies that they are currently failing. Be wary of users’ opinions on aesthetics and be prepared to bring them back to the script if they get side-tracked. Writing it up Even if you are the only developer it’s important to summarise the key issues that emerged during testing: your notes won’t make much sense to you a week or so after the test. If you are writing for other people, include a summary no longer than two pages; this can consist of a list or table of the issues including recommendations and their priorities. Remember to anonymise the users in the report. In team situations, you may be surprised at how many people are interested in the results of the usability test even if it doesn’t relate directly to something that they can fix. To conclude… Some usability testing is better than none at all, even for small projects or those with strict deadlines. Make the most of the time and resources available. Choose your users carefully, make them comfortable, summarise your report and don’t forget to leave a doughnut for yourself! 2006 Natalie Downe nataliedowne 2006-12-16T00:00:00+00:00 https://24ways.org/2006/fast-and-simple-usability-testing/ process
167 Back To The Future of Print 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 (“yarrr… I remember back in the browser wars…”) 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. I am going to briefly cover 8 tips and 4 main gotchas when creating print stylesheets in our more enlightened era. Getting started As with regular stylesheets, print CSS can be included in a number of ways2, for our purposes we are going to be using the link element. <link rel="stylesheet" type="text/css" media="print" href="print.css"> This 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 ‘all’ which means that the styles within then apply to print and screen alike. The media type ‘screen’ only applies to the screen and wont be picked up by print, this is the best way of hiding styles from print. Make 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! Another thing you should be thinking is ‘does it need to be printed’. 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. Context 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. Tips and tricks During these tip’s we are going to build up print styles for a textileRef:11112857385470b854b8411:linkStartMarker:“simple example”:/examples/back-to-the-future-of-print/demo-1.html 1. Remove the cruft First 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;. 2. Linearise your content Content doesn’t 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. 3. Improve your type Once you have removed all the useless cruft and jiggled things about a bit, you can concentrate more on the typography of the page. Typography 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). 4. Go wild on links There 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. When 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’s article on generating footnotes for print6. Using some clever selector trickery and CSS generated content you can have the location of the link generated after the link itself. HTML: <p>I wish <a href="http://www.google.com/">Google</a> could find <a href="/photoOfMyKeys.jpg">my keys</a></p> CSS: a:link:after, a:visited:after, a:hover:after, a:active:after { content: " <" attr(href) "> "; } But this is not perfect, in the above example the content of the href is just naively plonked after the link text: I wish Google <http://www.google.com/> would find my keys </photoOfMyKeys.jpg> As 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. CSS: a:link:after, a:visited:after, a:hover:after, a:active:after { content: " <" attr(href) "> "; color: grey; font-style: italic; font-weight: normal; } a[href^="/"]:after { content: " <http://www.example.com"attr(href)"> "; } The output is now what we were looking for (you will need to replace example.com with your own root URL): I wish Google <http://www.google.com/> would find my keys <http://www.example.com/photoOfMyKeys.jpg> Using 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: HTML: <a href="mailto:me@example.com">me@example.com</a> CSS: a[href^="mailto"]:after { content: ""; } This example shows the above in action. Of course with this clever technique, there are the usual browser support issues. While it won’t 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. 5. Jazz your headers for print This is more of a design consideration, don’t 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’s and styling other headings with graduating colors or font sizes. And here is the example complete with jazzy headers. 6. Build in general hooks If 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 7. For that extra touch of class When 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. Using 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’s window.location.href variable. function addPrintFooter() { var p = document.createElement('p'); p.className = 'print-footer'; p.innerHTML = window.location.href; document.body.appendChild(p); } You 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 8. Tabular data across pages If 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 <thead> 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. Also 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. Gotchas 1. Where did all my content go? Absolutely 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’s content will be printed, the rest will look truncated after this. Floating long columns may still have this affect, as mentioned in Eric Meyer’s article on ‘A List Apart’ 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. A 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. Using position:absolute on long columns also has a very similar effect in truncating the content, but can be overridden in print with position:static; Whilst 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. 2. Damn those background browser settings One of the factors of life you now need to accept is that you can’t control the user’s 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. Naturally 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. Where 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. Check 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. One 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’t translate to print, you will need to disable this background bullet and re-instate your trusty friend the list-style-type. 3. Using JavaScript in your CSS? … beware IE6 Internet 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. 4. De-enhance your Progressive enhancements Quite a classic “doh” moment is when you realise that, of course paper doesn’t 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. If 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. And Finally… I 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. Be careful you don’t get caught out by the common gotchas, keep the design simple, test cross browser and relish in the medium of print. Further Reading 1 For more information constantly updated, please see the CSS discuss wiki on print stylesheets 2 For more information on media types and ways of including CSS please refer to the CSS discuss wiki on Media Stylesheets 3 Eric Meyer talks to ThinkVitamin about the importance of context when designing your print strategy. 4 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 5 Richard Rutter Has a fantastic resource on typography which also applies to print. 6 Aaron Gustafson has a great solution to link problem by creating footnotes at the end of the page. 7 The CSS discuss wiki has more detailed information on printing tables and detailed browser support 8 This ‘A List Apart’ article is dated May 10th 2002 though is still mostly relevant 9 Float clearing technique using ‘overflow:hidden’ 10 Autistic Cuckoo describes the interesting insight with regards to expressions specified for screen in IE6 remaining in print 11 Wikipedia has a good article on the definition of progressive enhancement 12 For a really neat trick involving a dynamically generated column to displaying <abbr> and <dfn> meanings (as well as somewhere for the user to write notes), try print previewing on Brian Suda’s site 2007 Natalie Downe nataliedowne 2007-12-09T00:00:00+00:00 https://24ways.org/2007/back-to-the-future-of-print/ design