\nThis code only worked in Internet Explorer and in some versions of Safari, but that was plenty of people to befriend. However, MySpace was prepared for this: they also filtered the word javascript from
\nSamy discovered that by inserting a line break into his code, MySpace would not filter out the word javascript. The browser would continue to run the code just fine! Samy had now broken past MySpace\u2019s first line of defence and was able to start running code on his profile page. Now he started looking at what he could do with that code.\nalert(document.body.innerHTML)\nSamy wondered if he could inspect the page\u2019s source to find the details of other MySpace users to befriend. To do this, you would normally use document.body.innerHTML, but MySpace had filtered this too.\nalert(eval('document.body.inne' + 'rHTML'))\nThis isn\u2019t a problem if you build up JavaScript code inside a string and execute it using the eval() function. This trick also worked with XMLHttpRequest.onReadyStateChange, which allowed Samy to send friend requests to the MySpace API and install the JavaScript code on his new friends\u2019 pages.\nOne final obstacle stood in his way. The same origin policy is a security mechanism that prevents scripts hosted on one domain interacting with sites hosted on another domain.\nif (location.hostname == 'profile.myspace.com') {\n document.location = 'http://www.myspace.com'\n + location.pathname + location.search\n}\nSamy discovered that only the http://www.myspace.com domain would accept his API requests, and requests from http://profile.myspace.com were being blocked by the browser\u2019s same-origin policy. By redirecting the browser to http://www.myspace.com, he discovered that he could load profile pages and successfully make requests to MySpace\u2019s API. Samy installed this code on his profile page, and he waited.\n\nOver the course of the next day, over a million people unwittingly installed Samy\u2019s code into their MySpace profile pages and invited their friends. The load of friend requests on MySpace was so large that the site buckled and shut down. It took them two hours to remove Samy\u2019s code and patch the security holes he exploited. Samy was raided by the United States secret service and sentenced to do 90 days of community service.\nThis is the power of installing a little bit of JavaScript on someone else\u2019s website. It is called cross site scripting, and its effects can be devastating. It is suspected that cross-site scripting was to blame for the 2018 British Airways breach that leaked the credit card details of 380,000 people.\nSo how can you help protect yourself from cross-site scripting?\nAlways sanitise user input when it comes in, using a library such as sanitize-html. Open source tools like this benefit from hundreds of hours of work from dozens of experienced contributors. Don\u2019t be tempted to roll your own protection. MySpace was prepared, but they were not prepared enough. It makes no sense to turn this kind of help down.\nYou can also use an auto-escaping templating language to make sure nobody else\u2019s HTML can get into your pages. Both Angular and React will do this for you, and they are extremely convenient to use.\nYou should also implement a content security policy to restrict the domains that content like scripts and stylesheets can be loaded from. Loading content from sites not under your control is a significant security risk, and you should use a CSP to lock this down to only the sources you trust. CSP can also block the use of the eval() function.\nFor content not under your control, consider setting up sub-resource integrity protection. This allows you to add hashes to stylesheets and scripts you include on your website. Hashes are like fingerprints for digital files; if the content changes, so does the fingerprint. Adding hashes will allow your browser to keep your site safe if the content changes without you knowing.\nnpm audit: Protecting yourself from code you don\u2019t own\nJavaScript and npm run the modern web. Together, they make it easy to take advantage of the world\u2019s largest public registry of open source software. How do you protect yourself from code written by someone you\u2019ve never met? Enter npm audit.\nnpm audit reviews the security of your website\u2019s dependency tree. You can start using it by upgrading to the latest version of npm:\nnpm install npm -g\nnpm audit\nWhen you run npm audit, npm submits a description of your dependencies to the Registry, which returns a report of known vulnerabilities for the packages you have installed.\n\nIf your website has a known cross-site scripting vulnerability, npm audit will tell you about it. What\u2019s more, if the vulnerability has been patched, running npm audit fix will automatically install the patched package for you!\nSecuring your site like it\u2019s 2019\nThe truth is that since the early days of the web, the stakes of a security breach have become much, much higher. The web is so much more than fandom and mailing DVDs - online banking is now mainstream, social media and dating websites store intimate information about our personal lives, and we are even inviting the internet into our homes.\nHowever, we have powerful new allies helping us stay safe. There are more resources than ever before to teach us how to write secure code. Tools like Angular and React are designed with security features baked-in from the start. We have a new generation of security tools like npm audit to watch over our dependencies.\nAs we roll over into 2019, let\u2019s take the opportunity to reflect on the security of the code we write and be grateful for the everything we\u2019ve learned in the last twenty years.", "year": "2018", "author": "Katie Fenn", "author_slug": "katiefenn", "published": "2018-12-01T00:00:00+00:00", "url": "https://24ways.org/2018/securing-your-site-like-its-1999/", "topic": "code"}
{"rowid": 208, "title": "All That Glisters", "contents": "Tradition has it that at this time of year, families gather together, sit, eat and share stories. It\u2019s an opportunity for the wisdom of the elders to be passed down to the younger members of the tribe. Tradition also has it that we should chase cheese downhill and dunk the nice lady to prove she\u2019s a witch, so maybe let\u2019s not put too much stock in that.\nI\u2019ve been building things on the web professionally for about twenty years, and although the web has changed immeasurably, it\u2019s probably not changed as much as I have. While I can happily say I\u2019m not the young (always right, always arrogant) developer that I once was, unfortunately I\u2019m now an approaching-middle-age developer who thinks he\u2019s always right and on top of it is extremely pompous. What can you do? Nature has devised this system with the distinct advantage of allowing us to always be right, and only ever wrong in the future or in the past. So let\u2019s roll with it.\nIncreasingly, there seems to be a sense of fatigue within our industry. Just when you think you\u2019ve got a handle on whatever the latest tool or technology is, something new comes out to replace it. Suddenly you find that you\u2019ve invested precious time learning something new and it\u2019s already old hat. The pace of change is so rapid, that new developers don\u2019t know where to start, and experienced developers don\u2019t know where it ends. With that in mind, here\u2019s some fireside thoughts from a pompous old developer, that I hope might bring some Christmas comfort.\nReliable and boring beats shiny and new\nThere are so many new tools, frameworks, techniques, styles and libraries to learn. You know what? You don\u2019t have to use them. You\u2019re not a bad developer if you use Grunt even though others have switched to Gulp or Brunch or Webpack or Banana Sandwich. It\u2019s probably misguided to spend lots of project time messing around with build tool fashions when your so last year build tool is already doing what you need.\nJust a little reminder that it\u2019s about 100 times more important what you build than how you build it.\u2014 Chris Coyier (@chriscoyier) December 10, 2017\n\nI think it helps if we understand why so many new solutions exist. Most developers are predisposed to enjoy creating new things more than improving established systems. It\u2019s natural, because it\u2019s actually much easier and more exciting to create something new that works exactly how you think it should be than to improve an existing, imperfect solution. Improving and refactoring a system is hard, and it takes real chops, much more than just building something new.\nThe consequence of this is that new tools appear all the time. A developer will get a fresh new idea of how to tackle a problem \u2013 usually out of dissatisfaction with an existing solution, and figure the best way to implement that idea is to build something new around it. Often, that something new will do the same job as something old that already exists; it will just do it in a different way. Sometimes in a better way. Sometimes, just different.\nxkcd: Standards\nThat\u2019s not to say new tools are bad, and it\u2019s not bad that they exist. We shouldn\u2019t be crushing new ideas, and it\u2019s not wrong to adopt a new solution over an old one, but you know what? There\u2019s no imperative to switch right away. The next time you hit a pain point with your current solution, or have time to re-evaluate, check out what\u2019s new and see how the latest generation of tools and technologies can help. There\u2019s no prize for solving problems you don\u2019t have yet, and heading further into the desert in search of water is a survival tactic, not an aspiration.\nNew is better, but also worse\nSoftware, much like people, is born with a whole lot of potential and not much utility. Newborns \u2014 both digital and meaty \u2014 are exciting and cute but they also lead to sleepless nights and pools of vomit.\nNew technology contains lots of useful new features, but it\u2019s also more likely to contain bugs and be subject to more rapid change. Jumping on a new framework is great, right until there are API changes and you need to refactor your entire project to be able to update. More mature solutions have a higher weight of existing projects on their shoulders, and so the need to maintain backward compatibility is stronger. Things still move forward, but in a more controlled way.\nSo how do we balance the need to move technology forward with the need to provide mature and stable solutions for the projects we work on? I think there\u2019s a couple of good ways to do that.\nGet personal\nUse all the new shiny tools on your side-projects, personal projects, seasonal throw-aways and anywhere where the stakes are low. If you know you can patch around problems without much consequence, go for it. Build your personal blog on a CMS that stores data in the woven bark of a silver birch. Find where it breaks. Find where it excels. Find yourself if you like. When it comes to high-stakes projects, you\u2019ll hopefully have enough experience to know what you\u2019re getting into.\nFocus on the unique problem\nThat\u2019s not to say you should never risk using a new technology for \u2018real\u2019 work. Instead, distinguish the areas of your project where a new technology solves a specifically identified, measurable business objective, verses those where it won\u2019t. \nA brand new web application framework might be fun to use, but are you in the business of solving a web application framework problem? That new web server made of taffeta might increase static file throughput slightly, but are you in the business of serving static assets, or would it be better to just run up nginx and never have to think about that problem again. (Clue: it\u2019s the nginx one.)\nBut when it comes to building that live sports interface for keeping fans up to date with the blow-by-blow of the big game, that\u2019s where it might make sense to take a risk on an amazing-looking new JavaScript realtime interface framework. That\u2019s the time to run up a breakthrough new message queue server that can deliver jobs to workers via extrasensory perception and keep the score updates flowing instantaneously. \nThose are the risks worth taking, as those new technologies have the potential to help you solve your core problems in a markedly improved way. Unproven technology is worth the risk if it solves a specific business objective. If it doesn\u2019t, don\u2019t make work for yourself - use something mature and stable.\nPick the right tools\nOur job as developers is to solve problems using code, and do so in an effective and responsible way. You\u2019ve been hired to use your expertise in picking the right tools for the job, and a big part of that is weighing up the risk verse the reward of each part of the system. The best tools for the job might be something cutting edge, but \u2018best\u2019 can also mean most stable, reliable or easy-to-hire-for.\nGo out and learn (and create!) new tools and experiment with them. Understand what problems they solve and what the pitfalls are. Use them in production for low-stakes projects to get real experience, and then once you really know their character, then think about using them when the stakes are higher.\nThe rest of the time? The tools you\u2019re using now are solid and proven and you know their capabilities and pitfalls well. They might not always be the fashionable candidate, but they often make for a very solid choice.", "year": "2017", "author": "Drew McLellan", "author_slug": "drewmclellan", "published": "2017-12-24T00:00:00+00:00", "url": "https://24ways.org/2017/all-that-glisters/", "topic": "business"}
{"rowid": 212, "title": "Refactoring Your Way to a Design System", "contents": "I love refactoring code. Absolutely love it. There\u2019s something about taking a piece of UI or a bit of code and reworking it in a way that is simpler, modular, and reusable that makes me incredibly happy.\nI also love design systems work. It gives hybrids like me a home. It seems like everyone is talking about design systems right now. Design systems teams are perfect for those who enjoy doing architectural work and who straddle the line between designer and developer. \nUna Kravets recently identified some of the reasons that design systems fail, and chief among them are lack of buy-in, underlying architecture, and communication. While it\u2019s definitely easier to establish these before project work begins, that doesn\u2019t mean it is the only path to success. \nIt\u2019s a privilege to work on a greenfield project, and one that is not afforded to many. Companies with complex and/or legacy codebases may not be able to support a full rewrite of their product. In addition, many people feel overwhelmed at the thought of creating a complete system and are at a loss of how or where to even begin the process. \nThis is where refactoring comes into play.\nAccording to Martin Fowler, \u201crefactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.\u201d It\u2019s largely invisible work, and if you do it right, the end user will never know the difference. What it will do is provide a decent foundation to begin more systematic work.\nBuild a solid foundation\nWhen I was first asked to create Pantsuit, the design system for Hillary for America, I was tasked with changing our codebase to be more modular and scalable, without changing the behavior or visual design of the UI. We needed a system in place that would allow for the rapid creation of new projects while maintaining a consistent visual language. In essence, I was asked to refactor our code into a design system.\nDuring that refactor, I focused the majority of my efforts on creating a scalable architecture based on the UI components in a single workflow. Since I needed to maintain a 1:1 parity with production, the only changes I could create were under-the-hood. I started with writing coding standards and deciding on a CSS architecture that I would then use as I rewrote sections of the codebase. \nIf you already have these in place, great! If not, then this is an excellent place to start. Even if your dream of a design system is never fully realized, having a coding philosophy and architecture in place will still have far-reaching benefits and implications.\nI want to note that if your refactor includes creating new coding standards or a CSS architecture, don\u2019t try to switch everything over right away. Instead, focus on a single new feature and isolate/encapsulate your work from the rest of the codebase.\nFocus on the features\n\nThe key principle to cleaning up a complex codebase is to always refactor in the service of a feature. \n\u2014 Max Kanat-Alexander\n\nRefactoring for the sake of refactoring can easily lead to accusations of misused time and lack of results. Another danger of refactoring is that it can turn into yak-shaving if you aren\u2019t disciplined in your approach. To that end, tying your refactored components to feature work is a great way to limit scope and reduce the rest of unintended changes.\nFor example, the initial work on Pantsuit focused only on components related to the donations flow. Every line of code I wrote was in service to improving the maintainability and modularity of that UI. Because we didn\u2019t have any standards in place, I started with those. From there, I identified all the components present in every step of the donations flow, which included some type styles, buttons, form inputs and error states. Then came the refactor of each individual component. Finally, I reintegrated the newly refactored components into the existing donations flow and tested it against production, checking for visual and behavioral diffs. At the end of this process, I had the beginning of a design system that would grow to serve over 50 applications, and a case study to demonstrate its effectiveness.\nIdeally, you\u2019ll want to get buy-in from your stakeholders and product owners before you begin any design systems work. However, in the absence of buy-in, linking your work to new feature development is a good way to both limit the scope of your refactor and jump start component creation.\nIn addition, if you\u2019re still trying to convince your team of the benefits of a design system, starting small and using the newly refactored, feature-driven work as a case study is one way showcase a design systems\u2019 value. By providing a concrete example of how working towards a design system contributed to the project\u2019s success, you\u2019re gathering the data necessary to secure buy-in for a larger-scale effort. It\u2019s a great way to show value, rather than just talking about it.\nShow, don\u2019t tell\nPerhaps the most important thing you can do for any design system is to document it. The key is to create a frictionless way to keep the documentation up-to-date, otherwise no one will contribute to it, and in turn, it will become obsolete and useless. \nThere are lots of tools out there to help you get started documenting your new system. One of my favorites is KSS, which parses comments in the code and uses them to generate a style guide. For Pantsuit, I used the node version of KSS, along with a template to quickly spin up a documentation site.\nI\u2019ve listed just a few tools below; for even more, check out the tools sections of styleguides.io.\n\nFractal\nPattern Lab\nDrizzle\nFabricator\nAstrum\nCatalog\n\nRegardless of what tool you settle on, it needs to integrate well with your current workflow. \nConclusion: always be refactoring\nIf you\u2019re not lucky enough to be able to start a new design system from scratch, you can start small and work on a single feature or component. With each new project comes a new opportunity to flesh out a new part of the system, and another potential case study to secure buy-in and showcase its value. Make sure to carefully and thoroughly document each new portion of the system as it\u2019s built. After a few projects, you\u2019ll find yourself with a decent start to a design system. \nGood luck, and happy holidays!\nFurther reading:\n\nWhy Design Systems Fail\nCSS Architecture for Design Systems\nRefactoring: Improving the Design of Existing Code\nRefactoring CSS: The Three I\u2019s\nRefactoring is About Features", "year": "2017", "author": "Mina Markham", "author_slug": "minamarkham", "published": "2017-12-23T00:00:00+00:00", "url": "https://24ways.org/2017/refactoring-your-way-to-a-design-system/", "topic": "code"}
{"rowid": 194, "title": "Design Systems and Hybrids", "contents": "The other day on Twitter, I saw a thread started by Dorian Taylor about why design systems are so hot right now. In the thread, he made the case that they\u2019ve been around for ages and some folks were just slow to catch up. It was an interesting thread, and not the first time I\u2019ve seen folks discuss this. \u201cDesign systems are so hot right now\u201d was even used recently\u00a0in this very publication.\nAnd yes it\u2019s true that they\u2019ve been around for ages. Design artefact collectors\u2019 obsession with reprints of old graphic standards manuals of the past\u00a0are a reminder. Sometimes old things become new again, either through a rediscovery or awakening (wow, that sounds really deep). But I think that\u2019s definitely what happened here.\nSome very opinionated answers that come to mind for me are:\n\nThe need for them has increased with the needs of software development. With the increasing number of devices (phones, tablets, watches, etc.), scaling design has required the need to double down on systems thinking and processes.\nInvestments with huge cost-saving returns. The time investment it takes to onboard new people as you staff up large teams (and the time it takes to fix bugs and inconsistencies) could be better spent building up a system that lets you ship at a faster pace. It also gives you more time to focus on the bigger picture instead of what color a button border is.\nIf you do\u00a0have to onboard new designers, the design system is a great educational resource to get up to speed quickly on your organization\u2019s design principles, materials/tools, and methods.\n\n\n\u201cHere\u2019s the simple truth: you can\u2019t innovate on products without first innovating the way you build them.\u201d\n\u2014 Alex Schleifer, The Way We Build\n\nThese are just some of the reasons. But there is another answer, and a personal conclusion that I\u2019ve reached. It relates to the way I work and what I love working on, but I don\u2019t see it talked about much.\nHybrids Have a Home\nI\u2019m a hybrid designer. I code in HTML & CSS (with a preference for Sass). But I don\u2019t call myself a frontend developer. I used to back in the day (I was a UI frontend developer at Apple over a decade ago, but all I wrote was HTML & CSS). I identify with designer because that\u2019s my training and interest, but the ideas of what a frontend developer can do has changed quite a ton over the years. Setting things up in build tools and processes are not my skill. And I know a lot of designers who share this experience with me.\nThere are also hybrid developers who identify as developers, but have excellent design skills. Buddies like my pal Brandon Ferrua\u00a0who was on my team at Salesforce is a great example of this. And we worked fantastically together.\nSometimes, companies don\u2019t know how to deal with hybrids. I\u2019ve been told to choose a side, and have even been made to join a development team simply because I could code my designs (and then when I couldn\u2019t deliver the same type of code my teammates could, and I felt like I wasn\u2019t able to use my talents in the most effective way).\nThere are a lot more folks out there I know of who identify as a hybrid, and many have found ourselves working on design systems. Una Kravets recently had a thread discussing this as well. At Clarity, this came up a lot in hallway conversations, breaks, and the after parties. I think that this job is a haven for folks who often find themselves in the middle.\nFor companies that get it, these people find joy in getting to use a wider variety of skills and being bridges; advocates that can speak to designers and developers, helping bring \u2028unity to an organization. They can wireframe, throw together a prototype, create color systems, architect naming conventions for design tokens. Design systems are their perfect home. I think this has contributed to the uptick in discussions and interest on this subject (in addition to the team- and company-focused reasons).\nKeep Design Systems Teams Cross-Functional\nSpeaking of teams, something some larger companies fall prey to is creating walls and silos where they need not be. If you place all your visual designers in one place, all your coders in another, and so on, you\u2019re not doing yourselves any favors. Meanwhile, your hybrids are caught in the middle not knowing exactly where they belong. Design systems teams should have representatives (whether on a core team, or a virtual/federated team) that bring different skillsets. Design, code, writing, accessibility, product management, and so on. You\u2019ll have a stronger vision on where to take your design system and to make it succeed. Siloing defeats the whole purpose of what design systems are meant for.\nHappy holidays, and may the force be with you.\nFurther Reading\n\nWhy Design Systems Fail\nDesign Systems are for People\nDesign Systems Handbook", "year": "2017", "author": "Jina Anne", "author_slug": "jina", "published": "2017-12-22T00:00:00+00:00", "url": "https://24ways.org/2017/design-systems-and-hybrids/", "topic": "process"}
{"rowid": 199, "title": "Knowing the Future - Tips for a Happy Launch Day", "contents": "You\u2019ve chosen your frameworks and libraries. You\u2019ve learned how to write code which satisfies the buzzword and performance gods. Now you need to serve it to a global audience, and make things easy to preview, to test, to sign-off, and to evolve.\nBut infrastructure design is difficult and boring for most of us. We just want to get our work out into the wild.\nIf only we had tools which would let us go, \u201cOh yeah! It all deploys perfectly every time\u201d and shout, \u201cYou need another release? BAM! What\u2019s next?\u201d\nA truth that can be hard to admit is that very often, the production environment and its associated deployment processes are poorly defined until late into a project. This can be a problem.\nIt makes my palms sweaty just thinking about it.\nIf like me, you have spent time building things for clients, you\u2019ll probably have found yourself working with a variety of technical partners and customers who bring different constraints and opportunities to your projects. Knowing and proving the environments and the deployment processes is often very difficult, but can be a factor which profoundly impacts our ability to deliver what we promised. To say nothing of our ability to sleep at night or leave our fingernails un-chewed.\nLet\u2019s look at this a little, and see if we can\u2019t set you up for a good night\u2019s sleep, with dry palms and tidy fingernails.\nA familiar problem\nYou\u2019ve been here too, right? The project development was tough, but you\u2019re pleased with what you are running in your local development environments. Now you need to get the client to see and approve your build, and hopefully indicate with a cheery thumbs up that it can \u201cgo live\u201d.\n\nChances are that we have a staging environment where the client can see the build. But be honest, is this exactly the same as the production environment? It should be, but often it\u2019s not. Often the staging environment is nothing more than a visible server with none of the optimisations, security, load balancing, caching, and other vital bits of machinery that we\u2019ll need (and need to test) in \u201cprod\u201d.\nOften the production environment is still being \u201cset up\u201d and you\u2019ll have to wait and see.\nIn development, \u201cwait and see\u201d is the enemy.\nInstead of waiting to see, we need to make the provisioning of, and deployment to our different environments one of the very first jobs of our project. I\u2019ve often needed to be the unpopular voice in the room who makes a big fuss when this is delayed. I\u2019ve described it as being a \u201ccritical blocker\u201d during project meetings and suggested that everything should halt until it is fixed. \nIt is that important.\nClients don\u2019t often like hearing a wary, disruptive voice saying \u201cwhoa there Nelly!\u201d, because the development should be able to continue while the production environment gets sorted out, right? \nSure. But if it is not seen as a blocker, it is seen as something that can just happen later. And if it happens later, all the ugly surprises and unknowns surface later too. And later is when we\u2019ll need to be thinking about other things. Not the plumbing. Trust me, it pays to face up to the issue right away rather than press on optimistically. The client will thank you later.\nAttitudes and expectations\nWe should, I think, exhibit these four attitudes towards production deployment:\n\nMake it scripted\nMake it automated\nMake it real\nMake it first\n\nMake it scripted\nLet\u2019s face it, we are going to need to deploy more than once over the course of the project. We are not going to get things perfect on our first shot. Nor should we expect to. And if we are going to repeat something, we want to be able to do it identically and predictably every time without needing to rely on our memories.\nDevelopers are great at scripting things which they would otherwise need to repeat. It makes us faster and it also helps us keep track of the steps we need to take.\nI\u2019m not crazy enough to try suggest the best technology to script your builds or deployments (holy wars lie down that path). A lot will depend on your languages and your tastes. Some will like Fabric, others will prefer Gulp, you might prefer Make or NPM. It doesn\u2019t really matter as long as you can script the process of building, packaging and deploying your project.\nWait. Won\u2019t we need to know everything about the build from the start in order to do this? Aren\u2019t our dependencies likely to change over time?\nYes. That would be ideal. But it\u2019s ok. Like our code, our deployment script will evolve over the life of a project. So evolve it. Start by scripting what is needed to support the first iteration of the project, and then maintain that script. It will become a valuable \u201csource of truth\u201d, providing a form of documentation of what your project needs for a successful deployment. Another bonus.\nMake it automated\nIf we have a scripted deployment which we can run by executing a single command, then we are in great shape to automate that process by triggering the build and deployment via suitable events.\nAgain, I prefer not to offer one single suggestion of when this should occur. That will depend on your approach to the project, how your development team is organised, and how your QA team operate. You can tune this to suit.\nFor one project I worked on, we chose to trigger the build and deployment to our production environment every time we used Git to tag the master branch of our version control repository. There were a few moving parts, and we needed to do some upfront work to get everything working, but that upfront effort was repaid many fold as we deployed time and time again, and exposed some issues with our environment long before we got to \u201claunch day\u201d.\nWith a scripted and automated process, we can make deployments \u201ccheap\u201d. This is our goal. When there are minimal cognitive or time overheads associated with deploying, we\u2019re likely to do it all the more often and become more confident that it will behave as expected.\nMake it real\nAlright, we have written scripts to build and deploy our projects. Anyone tagging our repo will trigger things to happen as if by magic, but where are we pushing things to? We need to target a real environment if this is to have any value.\nA useful pattern is to have all activity on our develop branch trigger deployments to our staging server. Meanwhile tagging master will deploy a version to the production environment. How we organise this will depend on our git branching approach. (I\u2019ve seen as many ways of approaching Git Flow as I have seen ways of approaching \u201cAgile\u201d).\nIt\u2019s vital though, that we ensure that we are deploying to, and testing against, our real infrastructure. We want to see real results. That\u2019s the best way to learn real lessons.\nMake it first\nBuilding our site to run in an environment not yet fully defined or available to test is like climbing without ropes \u2013 it\u2019s possible, but we put ourselves at risk. And the higher we climb the greater the risk. So it is important to do this as early as we possibly can.\nDon\u2019t have a certificate for our HTTPS yet? Fine, but let\u2019s still deploy to this evolving production environment and introduce HTTPS as soon as we can.\nBefore we know it we\u2019ll be proving that this is set up correctly and we\u2019ll not be surprised by mixed security alerts or other nasties further down the line.\n\nMailchimp perfectly capture the anxiety of sending emails to gazillions of people for a campaign. But we\u2019re lucky. Launching a site doesn\u2019t need to be like performing a mailshot. We can do things to banish that sweaty hand.\nDoing preparation work upfront means that by the time we need to launch the site into the wild, we have exercised the deployment mechanics, and tested the production environment so rigorously that this task will be boring.\n(It won\u2019t be boring. Launching should always be exciting because the world will finally get to see our beautiful, painstaking work. But nor should it be terrifying. Especially as a result of not knowing for certain if our processes and environments are going to work or burst into flames on the big day.)\nWhat tools exist?\nWell this all sounds lovely. But how should we tackle this? Where are the tools for us to use? As it happens, there are many service and tools that we can use to work this way.\nHosting\nAll of the big players like Amazon, Azure and Google offer tools which can help us here. Google for example, can host multiple deployed versions of your project in parallel and you can manage them via their App Engine console. Each build receives its own URL which you can use to access any deployed version of your site.\nHaving immutable deployments which stick around in perpetuity (or until you bin them) is a key feature which unlocks the ability to confidently direct your traffic to any version of your site. With that comes the capacity to test any version or feature in its real environment, and then promote a version, or rollback to a previous version whenever you want.\nA liberating power to have.\nContinuous integration\nIn order to create all of those different versions, we\u2019ll need somewhere to run our build and deployment scripts. Jenkins has been a popular Continuous Integration (CI) option for some time, and can be configured to perform all sorts of tasks, giving you extensive control over your deployment pipeline.\nYou need to host Jenkins yourself, but it provides some simple ways to do that.\nThe landscape for CI is getting richer and richer. With many hosted services like Circle CI providing this kind of automation up in the cloud.\nOne stop shop\nNetlify combines both hosting and continuous integration services. It monitors your git repositories and automatically runs your build in a container on its servers when it finds changes. Each branch and pull request in your git repository will result in an immutable version of your site with its own URL.\nNetlify is unlike Google Cloud, AWS or Azure in that it cannot host a dynamic server-side application for you. Instead it specialises in hosting static, or so called JAMstack sites.\nPersonally, I find that its simplicity makes it an approachable option, and a good place to learn and adopt some of these valuable habits.\nFull disclosure: I\u2019m a Netlify employee. But before I was, I was an avid customer, and it was through using Netlify that I first encountered some of these principles in practice.\nConclusion. It\u2019s all about the approach\nNo matter what tools or services you use (and there are many which can support these practices), the most important thing is to adopt an approach which lets you prove your environments as quickly as possible.\nFront-loading this effort will cast light onto the issues that you\u2019ll need to address early and often, leaving no infrastructure surprises to spoil things for you on launch day.\nAutomating the process will mean that when you do find things that you need to fix or to improve later (and you will), issuing another release will be trivial. It is a lovely feeling when you have confidence that releasing v1.0.0 will be no more stressful v0.0.1. In fact it should actually be less stressful, as you\u2019ll have been down this road many times by then. Fixing the potholes and smoothing the way as you went.\nFrom here, it should be a smooth ride.", "year": "2017", "author": "Phil Hawksworth", "author_slug": "philhawksworth", "published": "2017-12-21T00:00:00+00:00", "url": "https://24ways.org/2017/knowing-the-future/", "topic": "process"}
{"rowid": 198, "title": "Is Your Website Accidentally Sexist?", "contents": "Women make up 51% of the world\u2019s population. More importantly, women make 85% of all purchasing decisions about consumer goods, 75% of the decisions about buying new homes, and 81% of decisions about groceries. The chances are, you want your website to be as attractive to women as it is to men. But we are all steeped in a male-dominated culture that subtly influences the design and content decisions we make, and some of those decisions can result in a website that isn\u2019t as welcoming to women as it could be. \nTypography tells a story\nStudies show that we make consistent judgements about whether a typeface is masculine or feminine: Masculine typography has a square or geometric form with hard corners and edges, and is emphatically either blunt or spiky. Serif fonts are also considered masculine, as is bold type and capitals.\nFeminine typography favours slim lines, curling or flowing shapes with a lot of ornamentation and embellishment, and slanted letters. Sans-serif, cursive and script fonts are seen as feminine, as are lower case letters. \nThe effect can be so subtle that even choosing between bold and regular styles within a single font family can be enough to indicate masculinity or femininity.\nIf you want to appeal to both men and women, search for fonts that are gender neutral, or at least not too masculine. When you\u2019re choosing groups of fonts that need to work harmoniously together, consider which fonts you are prioritising in your design. Is the biggest word on the page in a masculine or feminine font? What about the smallest words? Is there an imbalance between the prominence of masculine and feminine fonts, and what does this imply? \nTypography is a language in and of itself, so be careful what you say with it. \nColour me unsurprised\nColour also has an obvious gender bias. We associate pinks and purples, especially in combination, with girls and women, and a soft pink has become especially strongly related to breast cancer awareness campaigns. On the other hand, pale blue is strongly associated with boys and men, despite the fact that pastels are usually thought of as more feminine. \nThese associations are getting stronger and stronger as more and more marketers use them to define products as \u201cfor girls\u201d and \u201cfor boys\u201d, setting expectations from an incredibly young age \u2014 children as young as four understand gender stereotypes. It should be obvious that using these highly gender-associated colours sends an incredibly strong message to your visitors about who you think your target audience is. If you want to appeal to both men and women, then avoid pinks and pale blues.\nBut men and women also have different colour preferences. Men tend to prefer intense primary colours and deeper colours (shades), and tolerate greys better, whilst women prefer pastels (tints). When choosing colours, consider not just the hue itself, but also tint, tone and shade.\nSlightly counterintuitively, everyone likes blue, but no one seems to particularly like brown or orange. \nA picture is worth a thousand words, or none\nStock photos are the quickest and easiest way to add a little humanity to your website, directly illustrating the kind of people you believe are in your audience. But the wrong photo can put a woman off before she\u2019s even read your text. \nA website about a retirement home will, for example, obviously include photos of older people, and a baby clothes retailer will obviously show photos of babies. But, in the latter case, should they also show only photographs of mothers with their children, or should they include fathers too? It\u2019s true that women take on the majority of childcare responsibilities, but that\u2019s a cultural holdover from a previous era, rather than some rule of law. We are seeing increasing number of stay at home dads as well as single dads, so showing only photographs of women both enforces the stereotype that only women can care, as well as marginalising male carers. \nEqually, featuring prominent photographs of women on sites about male-dominated topics such as science, technology or engineering help women feel welcomed and appreciated in those fields. Photos really do speak volumes, so make sure that you also represent other marginalised groups, especially ethnic groups. If people do not see themselves represented on your site, they are not going to engage with it as much as they might. \nAnother form of picture that we often ignore is the icon. When you do use icons, make sure that they are gender neutral. For example, avoid using a icon of a man to denote engineers, or of a woman to denote nurses. Avoid overly masculine or feminine metaphors, such as a hammer to denote DIY or a flower to denote gardens. Not only are these gendered, they\u2019re also trite and unappealing, so come up with more exciting and novel metaphors. \nUse gender-neutral language\nLast, but not least, be very careful in your use of gender in language. \nPronouns are an obvious pitfall. A lot of web content is written in the second person, using the cleary gender neutral \u2018you\u2019, but if you have to write in the third person, which uses \u2018she\u2019, \u2018he\u2019, \u2018it\u2019, and \u2018they\u2019, then be very careful which pronouns you use. The singular \u2018they\u2019 is becoming more widely acceptable, and is a useful gender-neutral option. If you must use generic \u2018he\u2019 and \u2018she\u2019, (as opposed to talking about a specific person), then vary the order that they come in, so don\u2019t always put the male pronoun first. \nWhen you are talking about people, make sure that you use the same level of formality for both men and women. The tendency is to refer to men by their surname and women by their first name so, for example, when people are talking about Ada Lovelace and Charles Babbage, they often talk about \u201cAda and Babbage\u201d, rather than \u201cLovelace and Babbage\u201d or \u201cAda and Charles\u201d. As a rule, it\u2019s best to use people\u2019s surnames in formal and semi-formal writing, and their first names only in very informal writing. \nIt\u2019s also very important to make sure that you respect people\u2019s honorifics, especially academic titles such as Dr or Professor, and that you use titles consistently. Studies show that women and people of colour are the most likely to have their honorifics dropped, which is not only disrespectful, it gives readers the idea that women and people of colour are less qualified than white men.\nIf you mention job titles, avoid old-fashioned gendered titles such as \u2018chairman\u2019, and instead look for a neutral version, like \u2018chair\u2019 or \u2018chairperson\u2019. Where neutral terms have strong gender associations, such as nurse or engineer, take special care that the surrounding text, especially pronouns, is diverse and/or neutral. Do not assume engineers are male and nurses female. \nMore subtle intimations of gender can be found in the descriptors people use. Military metaphors and phrases, out-sized claims, competitive words, and superlatives are masculine, such as \u2018ground-breaking\u2019, \u2018best\u2019, \u2018genius\u2019, \u2018world-beating\u2019, or \u2018killer\u2019. Excessive unnecessary factual detail is also very masculine. \nWomen tend to relate to more cooperative, non-competitive, future-focused, and warmer language, paired with more general information. Women\u2019s language includes word like \u2019global\u2019, \u2018responsive\u2019, \u2018support\u2019, \u2018include\u2019, \u2018engage\u2019 and \u2018imagine\u2019. Focus more on the kind of relationship you can build with your customers, how you can help make their lives easier, and less on your company or product\u2019s status. \nSmash the patriarchy, one assumption at a time\nWe\u2019re all brought up in a cultural stew that prioritises men\u2019s needs, feelings and assumptions over women\u2019s. This is the patriarchy, and it\u2019s been around for thousands of years. But given women\u2019s purchasing power, adhering to the patriarchy\u2019s norms is unlikely to be good for your business. If you want to tap into the female market, pay attention to the details of your design and content, and make sure that you\u2019re not inadvertently putting women off. A gender neutral website that designs away gender stereotypes will attract both men and women, expanding your market and helping your business flourish.", "year": "2017", "author": "Suw Charman-Anderson", "author_slug": "suwcharmananderson", "published": "2017-12-20T00:00:00+00:00", "url": "https://24ways.org/2017/is-your-website-accidentally-sexist/", "topic": "content"}
{"rowid": 207, "title": "Want to Break Out of Comparison Syndrome? Do a Media Detox", "contents": "\u201cComparison is the thief of joy.\u201d\n\u2014Theodore Roosevelt\n\nI grew up in an environment of perpetual creativity and inventiveness. My father Dennis built and flew experimental aircraft as a hobby. During my entire childhood, there was an airplane fuselage in the garage instead of a car. My mother Deloria was a self-taught master artisan who could quickly acquire any skills that it took to work with fabric and weaving. She could sew any garment she desired, and was able to weave intricate wall hangings just by looking at a black and white photos in magazines. My older sister Diane blossomed into a consummate fine artist who drew portraits with uncanny likeness, painted murals, and studied art and architecture. In addition, she loved good food and had a genius for cooking and baking, which converged in her creating remarkable art pieces out of cake that were incredibly delicious to boot. Yes. This was the household in which I grew up.\nWhile there were countless positives to being surrounded by people who were compelled to create, there was also a downside to it. I incessantly compared myself to my parents and older sister and always found myself lacking.\nIt wasn\u2019t a fair comparison, but tell that to a sensitive kid who wanted to fit in to her family by being creative as well. From my early years throughout my teens, I convinced myself that I would never understand how to build an airplane or at least be as proficient with tools as my father, the aeronautical engineer. Even though my sister was six years older than I was, I lamented that I would never be as good a visual artist as she was. And I marveled at my mother\u2019s seemingly magical ability to make and tailor clothes and was certain that I would never attain her level of mastery.\nThis habit of comparing myself to others grew over the years, continuing to subtly and effectively undermine my sense of self. I had almost reached an uneasy truce with my comparison habit when social media happened.\nAs an early adopter of Twitter, I loved staying connected to people I met at tech conferences. However, as I began to realize my aspirations of being an author and a speaker, Twitter became a dreaded hall of mirrors where I only saw distorted reflections of my lack of achievement in other people\u2019s success. Every person announcing a publishing deal caused me to drown under waves of envy over the imagined size of her or his book advance as I struggled to pay my mortgage. Every announcement I read of someone speaking at a conference led to thoughts of, \u201cI wish I were speaking at that conference \u2013 I must not be good enough to be invited.\u201d Twitter was fertile ground for my Inner Critic to run rampant.\nOne day in 2011, my comparisons to people who I didn\u2019t even know rose to a fever pitch. I saw a series of tweets that sparked a wave of self-loathing so profound that I spent the day sobbing and despondent, as I chastised myself for being a failure. I had fallen into the deep pit of Comparison Syndrome, and to return to anything close to being productive took a day or two of painstakingly clawing my way out.\nComparison Syndrome Takes Deficiency Anxiety to Eleven\nDo any of these scenarios ring true?\n\nYou frequently feel like a failure when viewing the success of others.\nYou feel dispirited and paralyzed in moving forward with your own work because it will never measure up to what others have done.\nYou discount your ideas because you fear that they aren\u2019t as good as those of your colleagues or industry peers.\n\nAre you making yourself miserable by thinking thoughts like these?\n\n\u201cI\u2019m surrounded by people who are so good at what they do, how can I possibly measure up?\u201d\n\u201cCompared to my partner, my musical ability is childish \u2013 and music is no longer fun.\u201d\n\u201cWhy haven\u2019t I accomplished more by now? My peers are so much more successful than I am.\u201d\n\nUnenviable Envy\nMany people use the terms envy and jealousy interchangeably, but they are two distinct emotions. Jealousy is the fear of losing someone to a perceived rival: a threat to an important relationship and the parts of the self that are served by that relationship. Jealousy is always about the relationship between three people. Envy is wanting what another has because of a perceived shortcoming on your part. Envy is always based on a social comparison to another.1\nEnvy is a reaction to the feeling of lacking something. Envy always reflects something we feel about ourselves, about how we are somehow deficient in qualities, possessions, or success.2 It\u2019s based on a scarcity mentality: the idea that there is only so much to go around, and another person got something that should rightfully be yours.3\nA syndrome is a condition characterized by a set of associated symptoms. I call it Comparison Syndrome because a perceived deficiency of some sort \u2013 in talent, accomplishments, success, skills, etc. \u2013 is what initially sparks it. While at the beginning you may merely feel inadequate, the onset of the syndrome will bring additional symptoms. Lack of self-trust and feelings of low self-worth will fuel increased thoughts of not-enoughness and blindness to your unique brilliance. If left unchecked, Deficiency Anxieties can escalate to full-blown Comparison Syndrome: a form of the Inner Critic in which we experience despair from envy and define ourselves as failures in light of another\u2019s success.\nThe irony is that when we focus so much on what we lack, we can\u2019t see what we have in abundance that the other person doesn\u2019t have. And in doing so, we block what is our birthright: our creative expression. Envy shackles our creativity, keeps us trapped in place, and prevents forward movement. The Inner Critic in the form of Comparison Syndrome caused by envy blocks us from utilizing our gifts, seeing our path clearly, and reveling in our creative power.\nIn order to keep a grip on reality and not fall into the abyss of Comparison Syndrome, we\u2019ll quell the compulsion to compare before it happens: we will free the mental bandwidth to turn our focus inward so we can start to see ourselves clearly. \nBreak the Compulsion to Compare\n\n\u201cWhy compare yourself with others? No one in the entire world can do a better job of being you than you.\u201d\n\u2014 Krystal Volney, poet and author\n\nAt some point in time, many of us succumb to moments of feeling that we are lacking and comparing ourselves unfavorably to others. As social animals, much of our self-definition comes from comparison with others. This is how our personalities develop. We learn this behavior as children, and we grow up being compared to siblings, peers, and kids in the media. Because of this, the belief that somehow, someway, we aren\u2019t good enough becomes deeply ingrained. The problem is that whenever we deem ourselves to be \u201cless than,\u201d our self-esteem suffers. This creates a negative feedback loop where negative thoughts produce strong emotions that result in self-defeating behaviors that beget more negative thoughts.\nCouple this cycle with the messages we get from society that only \u201cgifted\u201d people are creative, and it\u2019s no wonder that many of us will fall down the rabbit hole of Comparison Syndrome like I did on that fated day while reading tweets. Comparing ourselves to others is worse than a zero-sum game, it\u2019s a negative-sum game. No one wins, our self-esteem deteriorates, and our creative spark dies out.\nWith effort, we can break the compulsion to compare and stop the decline into Comparison Syndrome by turning the focus of comparison inward to ourselves and appreciating who we\u2019ve become. But first, we need to remove some of the instances that trigger our comparisons in the first place.\nArrest: Stop the Triggers\n\n\u201cRight discipline consists, not in external compulsion, but in the habits of mind which lead spontaneously to desirable rather than undesirable activities.\u201d\n\u2014 Bertrand Russell, philosopher\n\nAfter my Twitter post meltdown, I knew had to make a change. While bolstering my sense of self was clearly a priority, I also knew that my ingrained comparison habit was too strong to resist and that I needed to instill discipline. I decided then and there to establish boundaries with social media.\nFirst, to maintain my sanity, I took this on as my mantra:\n\u201cI will not compare myself to strangers on the Internet or acquaintances on Facebook.\u201d\nIf you find yourself sliding down the slippery slope of social media comparison, you can do the same: repeat this mantra to yourself to help put on the brakes.\nSecond, in order to reduce my triggers, I stopped reading the tweets of the people I followed. However, I continued to be active on Twitter through sharing information, responding to mentions, crowdsourcing, and direct messaging people. It worked! The only time I\u2019d start to slip into darkness were the rare instances when I would break my rules and look at my Twitstream.\nBut we can do even more than calm ourselves with helpful mantras. Just like my example of modifying my use of Twitter, and more recently, of separating myself from Facebook, you can get some distance from the media that activates your comparison reflex and start creating the space for other habits that are more supportive to your being to take its place.\nCreative Dose: Trigger-free and Happy\nPurpose: To stop comparison triggers in their tracks\nMindfulness is a wonderful tool, but sometimes you have to get hardcore and do as much as you can to eliminate distractions so that you can first hear your own thoughts in order to know which ones you need to focus on.\nHere are four steps to becoming trigger-free and happier.\nStep 1: Make a List\nPay attention when you get the most triggered and hooked.\nIs it on Twitter, Facebook, Instagram, or Snapchat?\nIs it YouTube, TV shows, or magazines?\nMake list of your top triggers.\nMy primary trigger is:______________________________________\nMy second trigger is:______________________________________\nMy third trigger is:______________________________________\nNow that you have your list, you need to get an idea just how often you\u2019re getting triggered.\nStep 2: Monitor\nIt\u2019s easy to think that we should track our activity on the computer, but these days, it\u2019s no longer our computer use that is the culprit: most of us access social media and news from our phones. Fortunately, there are apps that will track the usage for both.\nSeeing just how much you consume media from either or both will show you how much of an accomplice the use of devices is to your comparison syndrome, and how much you need to modify your behavior accordingly.\nFor tracking both computer use and tablet use, this app works great:\n\nRescueTime.com tracks app usage and sends a productivity report at the end of the week via email.\n\nFor your phone, there are many for either platform.4 Although I recommend fully researching what is available and will work for you best, here are a few recommendations:\n\nFor both platforms: Offtime, Breakfree, Checky\nFor Android only: Flipd, AppDetox, QualityTime, Stay On Task\nFor iOS only: Moment\n\nInstall your app of choice, and see what you find. How much time are you spending on sites or apps that compel you to compare?\nStep 3: Just Say No\nNow that you know what your triggers are and how much you\u2019re exposing yourself to them, it\u2019s time to say No.\nPut yourself on a partial social media and/or media detox for a specified period of time; consider even going for a full media detox.5 I recommend starting with one month.\nTo help you to fully commit, I recommend writing this down and posting it where you can see it.\nI, ___________________, commit to avoiding my comparison triggers \nof ___________________, ___________________, and ___________________ \nfor the period of ___________________, \nstarting on ___________________ and ending on ___________________ .\nTo help you out, I\u2019ve created a social media detox commitment sheet for you.\nStep 4: Block\nWhen I decided to reduce my use of Twitter and Facebook to break my comparison habit, initially I tried to rely solely on self-discipline, which was only moderately successful. Then I realized that I could use the power of technology to help. Don\u2019t think you have to rely upon sheer willpower to block, or at least limit, your exposure to known triggers. If your primary access to the items that cause you to compare yourself to others is via computers and other digitalia, use these devices to help maintain your mental equilibrium.\nHere are some apps and browser extensions that you can use during your media detox to help keep yourself sane and stay away from sites that could throw you into a comparison tailspin.\nThese apps are installed onto your computer:\n\nRescueTime.com works on both computer and mobile devices, and does a lot more than just prevent you from going to sites that will ruin your concentration, it will also track your apps usage and give you a productivity report at the end of the week.\nFocus and SelfControl (Mac-only)\n\nTo go right to the source and prevent you from visiting sites through your browser, there are browser extensions.\nNot only can you put in the list of the URLs that are your points of weakness, but you can also usually set the times of the day you need the self-control the most.\n\nGoogle Chrome: StayFocusd, Strict Workflow, and Website Blocker\nFirefox: Idderall and Leechblock\nSafari: WasteNoTime and MindfulBrowsing\nEdge (or Explorer): Unfortunately, there are currently no website blocking extensions for these browsers.\n\nI currently use a browser extension to block me from using Facebook between 9:00am \u2013 6:00pm. It\u2019s been a boon for my sanity: I compare tons less. A bonus is that it\u2019s been terrific for my productivity as well. \nWhich tool will you use for your media detox time? Explore them all and then settle upon the one(s) that will work the best for you. Install it and put it to work.\nDespite the tool, you will still need to exercise discipline. Resist the urge to browse Instagram or Facebook while waiting for your morning train. You can do it!\nStep 5: Relax\nInstead of panicking from FOMO (Fear of Missing Out), take comfort from this thought: what you don\u2019t know won\u2019t affect you. Start embracing JOMO (Joy of Missing Out), and the process of rebuilding and maintaining your sanity.\nWhat will you do instead of consuming the media that compels you to\ncompare? Here are some ideas:\n\nRead a book \nGo for a walk \nHave dinner with a friend \nGo watch a movie \nLearn how to play the harmonica \nTake an improv class\n\nReally, you could do anything. And depending on how much of your time and attention you\u2019ve devoted to media, you could be recapturing a lot of lost moments, minutes, hours, and days.\nStep 6: Reconnect\nUse your recovered time and attention to focus on your life and reconnect with your true value-driven goals, higher aspirations, and activities that you\u2019ve always wanted to do.\n\nThis article is an excerpt from the book Banish Your Inner Critic by Denise Jacobs, and has been reprinted with permission. If you\u2019d like to read more, you can find the book on Amazon.\n\n\n\n\nShane Parrish, \u201cMental Model: Bias from Envy and Jealousy,\u201d Farnam Street, accessed February 9, 2017.\u00a0\u21a9\n\n\nParrish, \u201cMental Model: Bias from Envy and Jealousy.\u201d\u00a0\u21a9\n\n\nHenrik Edberg, \u201cHow to Overcome Envy: 5 Effective Tips,\u201d Practical Happiness Advice That Works | The Positivity Blog, accessed February 9, 2017.\u00a0\u21a9\n\n\nJeremy Golden, \u201c6 Apps to Stop Your Smartphone Addiction,\u201d Inc.com, accessed February 10, 2017.\u00a0\u21a9\n\n\nEmily Nickerson, \u201cHow to Silence the Voice of Doubt,\u201d The Muse, accessed February 8, 2017.\u00a0\u21a9", "year": "2017", "author": "Denise Jacobs", "author_slug": "denisejacobs", "published": "2017-12-19T00:00:00+00:00", "url": "https://24ways.org/2017/do-a-media-detox/", "topic": "process"}
{"rowid": 197, "title": "Designing for Mobile Performance", "contents": "Last year, some colleagues at Google ran a research study titled \u201cThe Need for Mobile Speed\u201d to find out what the impact of performance and perception of speed had on the way people use the web on their mobile devices. \nThat\u2019s not a trivial distinction; when considering performance, how fast something feels is often more important than how fast it actually is. When dealing with sometimes underpowered mobile devices and slow mobile networks, designing experiences that feel fast is exceptionally important.\nOne of the most startling numbers we found in the study was that 53% of mobile site visits are abandoned if pages take longer than 3 seconds to load.\nWe wanted to find out more, so following on from this study, we conducted research to define what the crucial elements of speed are. We took into consideration the user experience (UX), overall perception of speed, and how differing contexts the user finds themselves in can alter how fast a user thinks something loaded.\nTo understand speed and load times first we must understand that user mobile web behaviour is broken down into three buckets;\n\nIntention\nLocation\nState of mind\n\nLet\u2019s look at each of those in turn.\nIntention\nUsers browse sites on a mobile device for many different reasons. To be able to effectively design a performant user experience for them, it\u2019s important to understand what those reasons might be. When asked to describe their reason for visiting a site, approximately 30% of people asked by the study claimed that they were simply browsing without a particular purpose in mind. Looking deeper, we found that this number increased slightly (34%) for retail sites. 30% said they were just there to find out some information for a future task or action, such as booking a flight.\nInterestingly, the research shows that users are actually window shopping using their mobile browser. Only 29% actually said they had a specific goal or intent in mind, and this number increases significantly for financial services like banking sites (57%). This goes against a traditionally held view of users wanting to perform simple actions efficiently on their mobile device. Sure, some users are absolutely doing that, but many are just browsing around without a goal in mind, just like they would on a desktop browser.\nThis gives great insight into the user\u2019s intentions. It tells us that users are actively using sites on their mobile, but a large majority do not intend to do anything instantly. There\u2019s no goal they\u2019re under pressure to achieve. If a site\u2019s performance is lousy or janky, this will only reaffirm to the user to that they can hold off on completing a task, so they might just give up. \nHowever, if a site is quick to load, sophisticated in expressing its value proposition quickly, and enables the user to perform their actions seamlessly, then turning that \u201cbrowsing user\u201d into a \u201cbuying user\u201d becomes all that much easier. When the user has no goal, there\u2019s more opportunity to convert, and you stand a greater chance of doing that if the performance is good enough so they stick around.\nLocation\nObviously, mobile devices by their nature can be used in many different locations. This is an interesting consideration, because it\u2019s not something we traditionally need to take into account designing experiences for static platforms like desktop computers.\nThe in the study, we found that 82% of users browse the web on their mobile phone while in their home. In contrast, only 7% do the same while at work. This might come across as a bit of a shock, but when you look at mobile usage \u2013 in particular app usage \u2013 most of the apps being used are either a social network or some sort of entertainment or media app. Due to the unreliability of network connections, users will often alternate between these two types of apps.\nThe consequence being that if a site doesn\u2019t work offline, or otherwise compensate for bad network connectivity in some way by providing opportunities to allow users to browse their site, then it becomes a self-fulfilling prophecy as to why users mostly view the mobile web from the comfort of their homes where there is a strong WiFi connection. They\u2019re using mobile devices, but they\u2019re not actually mobile themselves.\nAnother thing to bear in mind is how users alternate between devices, a study by comScore found that 80% of transactions take place on desktop while 69% of the browsing takes place on mobile. Any given user might access from more than one location - they might visit one day from a bus queue on their phone, and then next day from a laptop at home.\nState of mind\nOne more thing we need to take into consideration is the user\u2019s state of mind. Whilst browsing at home, users tend to be more relaxed, and in the research 76% stated they were generally calmer at home. The user\u2019s state of mind can have quite a big impact on how they perceive things. The calmer they are, the quicker a site might appear to load. If the user is anxious and impatiently drumming their fingers on the table, things seem to take longer, and even a small wait can feel like an eternity.\nThis is quite key. Over 40% of sites take longer than 4 seconds to load for users who are are out and about and using a mobile data connection. Coupled with our perception, and amplified by a potentially less-than-calm state of mind, this can seem like an age.\nWhat does this all mean?\nI think we can all agree that users prefer strong, steady connections and comfort when completing transactions. It seems like common sense when we say it out loud. Recreating these feelings and sensations of comfort and predictability under all circumstances therefore becomes paramount. Equally, when asked in the study, users all claimed that speed was the most important factor impacting their mobile web usage. Over 40%, in fact, said it was the most important UX feature of a site, and nobody asked considered it to be of no importance at all.\n\nThe meaning of speed\nWhen it comes to performance, speed is measured in two ways \u2013 real speed; as measured on a clock, and perceived speed; how responsive an interaction feels. We can, of course, improve how quickly a site loads by simply making files smaller. Even then, the study showed that 32% of users felt a site can feel slow even when it loads in less than 4 seconds. This gets even worse when you look at it by age group, with 50% if young people (18-24 year olds) thinking a site was slower than it actually was. When you add to the mix that users think a site loaded faster when they are sitting compared to when they are standing up, then you are in a world of trouble if your site doesn\u2019t have any clear indicators to let the user know the loading state of you website or app.\nSo what can we do about this to improve our designs?\nHow to fix / hack user perception\nThere are some golden rules of speed, the first thing is hacking response time. If a page takes more than 3 seconds to load, you will certainly start to lose your users. However, if that slowness is part of a UX flow such as processing information, the user understands it might take a little time. Under those circumstances, a load time of under 5 seconds is acceptable, but even then, you should take caution. Anything above 8 seconds and you are in very real danger of losing your audience completely. \n\n\n\nLoad time\nUser impression\n\n\n\n\n200 ms\nFeels instant\n\n\n1 s\nFeels it is performing smoothly\n\n\n5 s\nPart of user flow\n\n\n8 s\nLose attention\n\n\n\nRemove the tap delay\nMobile browsers often use a 300-350ms delay between the triggering of the touchend and click events. This delay was added so the browser could determine if there was going to be a double-tap triggered or not, since double-tap is a common gesture used to zoom into text. This delay can have the side effect of making interactions feel laggy, and therefore giving the user the impression that the site is slow, even if it\u2019s their own browser causing the problem.\nFortunately there\u2019s a way to remove the delay. Add following in the of your page, and the delay no longer takes effect:\n
\nYou can also use touch-action: manipulation in newer browsers to eliminate click delay. For old browsers, FastClick by FT Labs uses touch events to trigger clicks faster and remove the double-tap gesture.\nMake use of Skeleton Screens\nA skeleton layout is a wireframe version of your app that displays while content is being loaded. This demonstrates to the user that content is about to be loaded, giving the impression that something is happening more quickly than it really is. Consider also using a preloader UI as well, with a text label informing the user that the app is loading. One example would be to pulsate the wireframe content giving the app the feeling that it is alive and loading. This reassures the user that something is happening and helps prevent resubmissions or refreshes of your app. Razvan Caliman created a Codepen example of how to create this effect in purely CSS. \nOne thing to consider though, if data doesn\u2019t load then you might need to create a fallback 404 or error page to let the user know what happened. \n\nExample by Owen-Campbell Moore\nResponsive Touch Feedback\nCarefully designing the process by which items load is one aspect of increasing the perceived speed of your page, but reassuring the user that an action they have taken is in process is another. At Google we use something called a Ripple, which is is animating dot that expands or ripples in order to confirm to the user that their input has been triggered. This happens immediately, expanding outward from the point of touch. This reaffirms to the user that their input has been received and is being acted on, even before the site has had a chance to process or respond to the action. From the user\u2019s point of view, they\u2019ve tapped and the page has responded immediately, so it feels really quick and satisfying.\nYou can mimic this same behavior using our Material Design Components Web GitHub repo.\n\nProgress bars\nThese UI elements have existed for a very long time, but research conducted by Chris Harrison and published in New Scientist found that the style of a progress bar can alter the perception of speed drastically. As a matter of fact, progress bars with ripples that animate towards the left appear like they are loading faster by at least 11% percent. So when including them in your site, take into consideration that ripples and progress bars that pulsate faster as they get to the end will make your sites seem quicker.\n\n \n \n Faster Progress Bars: Manipulating Perceived Duration with Visual Augmentations\nNavigation\nThe speed with which a user can locate navigational items or call to actions adds to their perceived performance of a site. If the user\u2019s next action is quick to spot on the screen, they don\u2019t spend time hunting around the interface with their eyes and fingers. So no matter how quickly your code runs, hiding items behind a nav bar will make a site feel slower than it actually is. \nFacebook found that switching to using bottom navigation saw an increase in engagement, satisfaction, revenue, speed, and importantly, perception of speed. If the user sees the navigation items they\u2019re looking for quickly, the interaction feels fast. What\u2019s more, end-to-end task completion is quicker too, as the interface not only feels quicker, but actually measures quicker as well. Similar reactions were found with Spotify and Redbooth.\nLuke Wroblewski gave a talk last year in Ireland titled \u201cObvious Always Wins\u201d which he demonstrated through the work he did with Google+. Luke\u2019s message is that by making the core features of your app obvious to your user, you will see engagement go up. This again seems obvious, right? However, it is important to note that adding bottom navigation doesn\u2019t just mean a black bar at the bottom of your screen like some kind of performance magic bullet. The goal is to make the items clear to the user so they know what they need to be doing, and how you achieve that could be different from one interface to the next. Google keeps experimenting with different navigation styles, but finally settled with the below when they conducted user research and testing.\n\nConclusion\nBy utilizing a collection of UI patterns and speed optimisation techniques, you can improve not only the actual speed of a site, but the perception of how quickly a user thinks your site is loading. It is critical to remember that users will not always be using your site in a calm and relaxed manner and that even their age can impact how they will use or not use your site. By improving your site\u2019s stability, you increase the likelihood of positive user engagement and task completion.\nYou can learn more about techniques to hack user perception and improve user speed by taking a look at an E-Book we published with Awwwards.com called Speed Matters: Design for Mobile Performance.", "year": "2017", "author": "Mustafa Kurtuldu", "author_slug": "mustafakurtuldu", "published": "2017-12-18T00:00:00+00:00", "url": "https://24ways.org/2017/designing-for-mobile-performance/", "topic": "ux"}
{"rowid": 209, "title": "Feeding the Audio Graph", "contents": "In 2004, I was given an iPod.\nI count this as one of the most intuitive pieces of technology I\u2019ve ever owned. It wasn\u2019t because of the the snazzy (colour!) menus or circular touchpad. I loved how smoothly it fitted into my life. I could plug in my headphones and listen to music while I was walking around town. Then when I got home, I could plug it into an amplifier and carry on listening there.\nThere was no faff. It didn\u2019t matter if I could find my favourite mix tape, or if my WiFi was flakey - it was all just there.\nNowadays, when I\u2019m trying to pair my phone with some Bluetooth speakers, or can\u2019t find my USB-to-headphone jack, or even access any music because I don\u2019t have cellular reception; I really miss this simplicity.\nThe Web Audio API\nI think the Web Audio API feels kind of like my iPod did.\nIt\u2019s different from most browser APIs - rather than throwing around data, or updating DOM elements - you plug together a graph of audio nodes, which the browser uses to generate, process, and play sounds.\nThe thing I like about it is that you can totally plug it into whatever you want, and it\u2019ll mostly just work.\nSo, let\u2019s get started. First of all we want an audio source.\n
\n\n(Song - Night Owl by Broke For Free)\nThis totally works. However, it\u2019s not using the Web Audio API, so we can\u2019t access or modify the sound it makes.\nTo hook this up to our audio graph, we can use an AudioSourceNode. This captures the sound from the element, and lets us connect to other nodes in a graph.\nconst audioCtx = new AudioContext()\n\nconst audio = document.querySelector('audio')\nconst input = audioCtx.createAudioSourceNode(audio)\n\ninput.connect(audioCtx.destination)\n\nGreat. We\u2019ve made something that looks and sounds exactly the same as it did before. Go us.\nGain\nLet\u2019s plug in a GainNode - this allows you to alter the amplitude (volume) of an an audio stream.\nWe can hook this node up to an
element by setting the gain property of the node. (The syntax for this is kind of weird because it\u2019s an AudioParam which has options to set values at precise intervals).\nconst node = audioCtx.createGain()\n\nconst input = document.querySelector('input')\ninput.oninput = () => node.gain.value = parseFloat(input.value)\n\ninput.connect(node)\nnode.connect(audioCtx.destination)\n\nYou can now see a range input, which can be dragged to update the state of our graph. This input could be any kind of element, so now you\u2019ll be free to build the volume control of your dreams.\nThere\u2019s a number of nodes that let you modify/filter an audio stream in more interesting ways. Head over to the MDN Web Audio page for a list of them.\nAnalysers\nSomething else we can add to our graph is an AnalyserNode. This doesn\u2019t modify the audio at all, but allows us to inspect the sounds that are flowing through it. We can put this into our graph between our AudioSourceNode and the GainNode.\nconst analyser = audioCtx.createAnalyser()\n\ninput.connect(analyser)\nanalyser.connect(gain)\ngain.connect(audioCtx.destination)\nAnd now we have an analyser. We can access it from elsewhere to drive any kind of visuals. For instance, if we wanted to draw lines on a canvas we could totally do that:\nconst waveform = new Uint8Array(analyser.fftSize)\nconst frequencies = new Uint8Array(analyser.frequencyBinCount)\nconst ctx = canvas.getContext('2d')\n\nconst loop = () => {\n requestAnimationFrame(loop)\n analyser.getByteTimeDomainData(waveform)\n analyser.getByteFrequencyData(frequencies)\n\n ctx.beginPath()\n waveform.forEach((f, i) => ctx.lineTo(i, f))\n ctx.lineTo(0,255)\n frequencies.forEach((f, i) => ctx.lineTo(i, 255-f))\n ctx.stroke()\n}\nloop()\n\nYou can see that we have two arrays of data available (I added colours for clarity):\n\nThe waveform - the raw samples of the audio being played.\nThe frequencies - a fourier transform of the audio passing through the node.\n\nWhat\u2019s cool about this is that you\u2019re not tied to any specific functionality of the Web Audio API. If it\u2019s possible for you to update something with an array of numbers, then you can just apply it to the output of the analyser node.\nFor instance, if we wanted to, we could definitely animate a list of emoji in time with our music.\nspans.forEach(\n (s, i) => s.style.transform = `scale(${1 + (frequencies[i]/100)})`\n)\n\n\ud83d\udd08\ud83c\udfa4\ud83c\udfa4\ud83c\udfa4\ud83c\udfba\ud83c\udfb7\ud83d\udcef\ud83c\udfb6\ud83d\udd0a\ud83c\udfb8\ud83c\udfba\ud83c\udfa4\ud83c\udfb8\ud83c\udfbc\ud83c\udfb7\ud83c\udfba\ud83c\udfbb\ud83c\udfb8\ud83c\udfbb\ud83c\udfba\ud83c\udfb8\ud83c\udfb6\ud83e\udd41\ud83c\udfb6\ud83c\udfb5\ud83c\udfb5\ud83c\udfb7\ud83d\udcef\ud83c\udfb8\ud83c\udfb9\ud83c\udfa4\ud83c\udfb7\ud83c\udfbb\ud83c\udfb7\ud83d\udd08\ud83d\udd0a\ud83d\udcef\ud83c\udfbc\ud83c\udfa4\ud83c\udfb5\ud83c\udfbc\ud83d\udcef\ud83e\udd41\ud83c\udfbb\ud83c\udfbb\ud83c\udfa4\ud83d\udd09\ud83c\udfb5\ud83c\udfb9\ud83c\udfb8\ud83c\udfb7\ud83d\udd09\ud83d\udd08\ud83d\udd09\ud83c\udfb7\ud83c\udfb6\ud83d\udd08\ud83c\udfb8\ud83c\udfb8\ud83c\udfbb\ud83c\udfa4\ud83e\udd41\ud83c\udfbc\ud83d\udcef\ud83c\udfb8\ud83c\udfb8\ud83c\udfbc\ud83c\udfb8\ud83e\udd41\ud83c\udfbc\ud83c\udfb6\ud83c\udfb6\ud83e\udd41\ud83c\udfa4\ud83d\udd0a\ud83c\udfb7\ud83d\udd0a\ud83d\udd08\ud83c\udfba\ud83d\udd0a\ud83c\udfbb\ud83c\udfb5\ud83c\udfbb\ud83c\udfb8\ud83c\udfb5\ud83c\udfba\ud83c\udfa4\ud83c\udfb7\ud83c\udfb8\ud83c\udfb6\ud83c\udfbc\ud83d\udcef\ud83d\udd08\ud83c\udfba\ud83c\udfa4\ud83c\udfb5\ud83c\udfb8\ud83c\udfb8\ud83d\udd0a\ud83c\udfb6\ud83c\udfa4\ud83e\udd41\ud83c\udfb5\ud83c\udfb9\ud83c\udfb8\ud83d\udd08\ud83c\udfbb\ud83d\udd09\ud83e\udd41\ud83d\udd09\ud83c\udfba\ud83d\udd0a\ud83c\udfb9\ud83e\udd41\ud83c\udfb7\ud83d\udcef\ud83c\udfb7\ud83c\udfb7\ud83c\udfa4\ud83c\udfb8\ud83d\udd09\ud83c\udfb9\ud83c\udfb7\ud83c\udfb8\ud83c\udfba\ud83c\udfbc\ud83c\udfa4\ud83c\udfbc\ud83c\udfb6\ud83c\udfb7\ud83c\udfa4\ud83c\udfb7\ud83d\udcef\ud83d\udcef\ud83c\udfbb\ud83c\udfa4\ud83c\udfb7\ud83d\udcef\ud83c\udfb9\ud83d\udd08\ud83c\udfb5\ud83c\udfb9\ud83c\udfbc\ud83d\udd0a\ud83d\udd09\ud83d\udd09\ud83d\udd08\ud83c\udfb6\ud83c\udfb8\ud83e\udd41\ud83c\udfba\ud83d\udd08\ud83c\udfb7\ud83c\udfb5\ud83d\udd09\ud83e\udd41\ud83c\udfb7\ud83c\udfb9\ud83c\udfb7\ud83d\udd0a\ud83c\udfa4\ud83c\udfa4\ud83d\udd0a\ud83c\udfa4\ud83c\udfa4\ud83c\udfb9\ud83c\udfb8\ud83c\udfb9\ud83d\udd09\ud83c\udfb7\n\n\nGenerating Audio\nSo far, we\u2019ve been using the
element as a source of sound.\nThere\u2019s a few other sources of audio that we can use. We\u2019ll look at the AudioBufferNode - which allows you to manually generate a sound sample, and then connect it to our graph.\nFirst we have to create an AudioBuffer, which holds our raw data, then we pass that to an AudioBufferNode which we can then treat just like our AudioSource node. This can get a bit boring, so we\u2019ll use a helper method that makes it simpler to generate sounds.\nconst generator = (audioCtx, target) => (seconds, fn) => {\n const { sampleRate } = audioCtx\n\n const buffer = audioCtx.createBuffer(\n 1, sampleRate * seconds, sampleRate\n )\n const data = buffer.getChannelData(0)\n\n for (var i = 0; i < data.length; i++) {\n data[i] = fn(i / sampleRate, seconds)\n }\n\n return () => {\n const source = audioCtx.createBufferSource()\n source.buffer = audioBuffer\n\n source.connect(target || audioCtx.destination)\n source.start() \n }\n}\n\nconst sound = generator(audioCtx, gain)\nOur wrapper will let us provide a function that maps time (in seconds) to a sample (between 1 and -1). This generates a waveform, like we saw before with the analyser node.\nFor example, the following will generate 0.75 seconds of white noise at 20% volume.\nconst noise = sound(0.75, t => Math.random() * 0.2)\n\nbutton.onclick = noise\n\nNoise\n\n\nNow we\u2019ve got a noisy button! Handy.\nRather than having a static set of audio nodes, each time we click the button, we add a new node to our graph. Although this feels inefficient, it\u2019s not actually too bad - the browser can do a good job of cleaning up old nodes once they\u2019ve played.\nAn interesting property of defining sounds as functions is that we can combine multiple function to generate new sounds. So if we wanted to fade our noise in and out, we could write a higher order function that does that.\nconst ease = fn => (t, s) =>\n fn(t) * Math.sin((t / s) * Math.PI)\n\nconst noise = sound(0.75, ease(t => Math.random() * 0.2))\n\nease(noise)\n\n\nAnd we can do more than just white noise - if we use Math.sin, we can generate some nice pure tones.\n// Math.sin with period of 0..1\nconst wave = v => Math.sin(Math.PI * 2 * v)\nconst hz = f => t => wave(t * f)\n\nconst _440hz = sound(0.75, ease(hz(440)))\nconst _880hz = sound(0.75, ease(hz(880)))\n\n440Hz\n880Hz\n\n\nWe can also make our functions more complex. Below we\u2019re combining several frequencies to make a richer sounding tone.\nconst harmony = f => [4, 3, 2, 1].reduce(\n (v, h, i) => (sin(f * h) * (i+1) ) + v\n)\n\nconst a440 = sound(0.75, ease(harmony(440)))\n\n440Hz\n880Hz\n\n\nCool.\nWe\u2019re still not using any audio-specific functionality, so we can repurpose anything that does an operation on data. For example, we can use d3.js - usually used for interactive data visualisations - to generate a triangular waveform.\nconst triangle = d3.scaleLinear()\n .domain([0, .5, 1])\n .range([-1, 1, -1])\n\nconst wave = t => triangle(t % 1)\n\nconst a440 = sound(0.75, ease(harmony(440)))\n\n440Hz\n880Hz\n\n\nIt\u2019s pretty interesting to play around with different functions. I\u2019ve plonked everything in jsbin if you want to have a play yourself.\nA departure from best practice\nWe\u2019ve been generating our audio from scratch, but most of what we\u2019ve looked at can be implemented by a series of native Web Audio nodes. This would be way performant (because it\u2019s not happening on the main thread), and more flexible in some ways (because you can set timings dynamically whilst the note is playing). But we\u2019re going to stay with this approach because it\u2019s fun, and sometimes the fun thing to do might not technically be the best thing to do.\nMaking a keyboard\nHaving a button that makes a sound is totally great, but how about lots of buttons that make lots of sounds? Yup, totally greater-er.\nThe first thing we need to know is the frequency of each note. I thought this would be awkward because pianos were invented more than 250 years before the Hz unit was defined, so surely there wouldn\u2019t be a simple mapping between the two?\nconst freq = note => 27.5 * Math.pow(2, (note - 21) / 12)\nThis equation blows my mind; I\u2019d never really figured how tightly music and maths fit together. When you see a chord or melody, you can directly map it back to a mathematical pattern.\nOur keyboard is actually an SVG picture of a keyboard, so we can traverse the elements of it and map each element to a sound generated by one of the functions that we came up with before.\nArray.from(svg.querySelector('rect'))\n .sort((a, b) => + a.x - b.x)\n .forEach((key, i) =>\n key.addEventListener('touchstart',\n sound(0.75, ease(harmony(freq(i + 48))))\n )\n )\n\nrect {stroke: #ddd;}\nrect:hover {opacity: 0.8; stroke: #000}\n\nEt voil\u00e0. We have a keyboard.\nWhat I like about this is that it\u2019s completely pure - there\u2019s no lookup tables or hardcoded attributes; we\u2019ve just defined a mapping from SVG elements to the sound they should probably make.\nDoing better in the future\nAs I mentioned before, this could be implemented more performantly with Web Audio nodes, or even better - use something like Tone.js to be performant for you.\nWeb Audio has been around for a while, though we\u2019re getting new challenges with immersive WebXR experiences, where spatial audio becomes really important. There\u2019s also always support and API improvements (if you like AudioBufferNode, you\u2019re going to love AudioWorklet)\nConclusion\nAnd that\u2019s about it. Web Audio isn\u2019t some black box, you can easily link it with whatever framework, or UI that you\u2019ve built (whether you should is an entirely different question).\nIf anyone ever asks you \u201ccould you turn this SVG into a musical instrument?\u201d you don\u2019t have to stare blankly at them any more.\n(function(a,c){var b=a.createElement(\"script\");if(!(\"noModule\"in b)&&\"on\"+c in b){var d=!1;a.addEventListener(c,function(a){if(a.target===b)d=!0;else if(!a.target.hasAttribute(\"nomodule\")||!d)return;a.preventDefault()},!0);b.type=\"module\";b.src=\".\";a.head.appendChild(b);b.remove()}})(document,\"beforeload\");", "year": "2017", "author": "Ben Foxall", "author_slug": "benfoxall", "published": "2017-12-17T00:00:00+00:00", "url": "https://24ways.org/2017/feeding-the-audio-graph/", "topic": "code"}
{"rowid": 200, "title": "Care and Feeding of Burnout", "contents": "You\u2019ve been doing too much for too long. And it\u2019s broken you. You\u2019re burned out. You\u2019re done.\nIllustration by Kate Holden\nOccupational burnout is a long-documented effect of stretching yourself further than the limits of your mental and physical health can carry you. And when it finally catches up with you, it can feel like the end of the world. But things can get better. With focused self care, reworking your priorities and lots of time, you can slog through burnout.\nWhat is burnout? The Tl;dr linkdump tour\nIn this article, we\u2019ll be looking at what you can do when you\u2019re burned out. We\u2019ll be skipping past a lot of information on what burnout is, what causes it and how it impacts the tech industry. We\u2019re able to skip past this because many technologists have already created valuable content targeted to our industry. The videos and writing below may be helpful for readers who are less familiar with burnout.\nA Wikipedia article may be a great starting point for learning about occupational burnout.\n\n \n\nUnderstanding burnout: Brandon West\nThis conference talk by Brandon West covers a lot of burnout 101, from the perspective of a developer relations/community professional.\nApril Wensel writes about the need for the tech industry to move from the Valley\u2019s burnout culture to a more sustainable model.\nCatching Burnout [as] early [as possible]\nOne of the most challenging things about burnout is that it develops slowly and gradually. Many impacted don\u2019t notice the water warming around them until it\u2019s been brought to a boil, causing a crisis that can\u2019t be overlooked. Catching burnout and taking steps to deal with it as early as possible can help limit the length and severity of your burnout.\nGetting in the habit of checking in with yourself regularly about your stress and energy levels can be an effective habit for assessing burnout and for general wellness. The Mayo Clinic recommends asking yourself the following questions to determine if you might be suffering from burnout.\n\nHave you become cynical or critical at work?\nDo you drag yourself to work and have trouble getting started once you arrive?\nHave you become irritable or impatient with co-workers, customers or clients?\nDo you lack the energy to be consistently productive?\nDo you lack satisfaction from your achievements?\nDo you feel disillusioned about your job?\nAre you using food, drugs or alcohol to feel better or to simply not feel?\nHave your sleep habits or appetite changed?\nAre you troubled by unexplained headaches, backaches or other physical complaints?\n\nAccording to the Mayo Clinic, answering yes to more than one of these questions can be a sign that you need to take corrective action. We\u2019ll look in more detail about the corrective actions you can take in the rest of this article. \nDo less. Now.\nTo start getting things back on track, you\u2019ll need to start doing less. Less work, less stress, less everything. Many technologists impacted by burnout have written or spoken on taking months or even years off work to give themselves time to recover. This can be a fantastic route back to wellness for those fortunate enough to have the professional and financial security to allow them to take large stretches of time off work. For the much larger group of burned out workers that need to balance earning a paycheck with their wellness, this can be more challenging.\nFor those of us who need to stay in the cycle of work to fund our daily needs, finding ways to do less can feel like adding another daunting task to the pile. To properly assess where and how you can cut back on your commitments, you\u2019ll need to find a short stretch of time clear of stressors and responsibilities to take stock of what can be scaled back. A long weekend, weekend or even a few hours of time dedicated to looking only at how you can cut back on work and stress can be an effective way to take stock of your responsibilities.\nMake a list of stressors and activities to begin to triage. Anything that would damage or seriously disrupt your life if not attended to (doing your taxes, showing up at work, paying rent) should be marked as essential. Grade other activities in your life, marking the ones that aren\u2019t essential and working to temporarily reduce these or remove them from your life. It can feel difficult to let go of things while recovering from burnout. This process can benefit from a second opinion, if you\u2019re working with a coach, therapist or trusted friend to manage your burnout.\nReducing your workload and stressors can let you begin to recover from burnout. You can reintroduce things back into your schedule and life. Reintroduce stressors and activities back into your life slowly, to minimize risk of relapse. Keeping a journal will let you keep tabs on how different activities are impacting your energy levels and state of mind.\nRemove toxicity\nToxic people or settings can drain you faster than overwork alone can. While you work to reduce your workload and stress, coworkers, friends, family or bosses who are toxic influences can act as a multiplier for the stressors that remain. Identifying these people and limiting your interactions with them during your recovery can help you get back on track faster and happier. A journal can be an important tool in tracking how interactions with different people impact your wellness and state of mind. If the toxic presence in your life is someone you can avoid or cut out without penalty, burnout is a great reason to finally replace them with healthier relationships.\nIf you can\u2019t remove them from your life, minimizing the impact toxic people have on your wellness is vital. Work to identify what aspect of the relationship is draining or damaging and create interventions around damaging interactions. While a chronically complaining coworker\u2019s negativity can be stopped short with setting firm conversational boundaries and redirection, a combative boss can be a harder challenge. Seeking allies and advice can make you feel less alone in your battles and provide healthy emotional support. \nAsk for help\nTrying to find your way back to health and wellness after burning out can be a daunting task. Seeking help from health care professionals, trusted peers or both can give you backup on your journey back to feeling better. With symptoms that can mirror those of depression, burnout can be the precursor to a number of mental and physical ailments. Talk to your doctor immediately if you\u2019re experiencing symptoms of depression or any other health concerns.\nBeing open with your trusted friends about burnout can let you access valuable support and help explain why you may need extra care and consideration while you recover. Many suffering from burnout report finding maintaining relationships a challenge. Letting your loved ones know what you\u2019re going through and why you may be less available invites them to be more understanding of cancelled plans or other issues while you\u2019re recovering. Burnout can impact memory and cognitive function. Letting your support network assist in decision making during burnout can help add perspective to counterbalance these deficits.\nTalking to your friends and peers about your health and needs can offer valuable support. But those who are pushed to a mental or physical health crisis by burnout should work with healthcare professionals to plan their recovery. Sufferers of mild to moderate burnout can also benefit from planning their return to wellness with an experienced practitioner. Medical or counseling professionals may prescribe medicines, talk therapy, group sessions or other therapeutic intervention. \nGo easy on yourself\nRecovering from burnout is a process that takes energy, time and compassion for yourself. In the same way that toxic people or workplaces can set you back, negative repetitive thoughts will harm your recovery. Recognizing that burnout\u2019s impact on you is a temporary state that isn\u2019t your fault can help you begin to manage your feelings and expectations for yourself. Sufferers often report feeling stupid, lazy or that they lack the skills to do their job. This is natural, as burnout can severely limit your cognitive function, your energy levels and resilience while dramatically increasing your cognitive load. Working with a counselor may help if you\u2019re finding it difficult to be patient with your progress back to health or are troubled by persistent intrusive thoughts.\nBurnout can seriously limit the amount of energy you have. Spend as little of the energy you have left beating yourself up as possible. You\u2019re going to be ok. It\u2019s all going to be ok.\nThis article doesn\u2019t offer one-size-fits all fixes for burnout or overwork, but aims to provide a framework with points to consider that may help shape your wellness. No article can act as a substitute for professionally administered healthcare or robust self care.", "year": "2017", "author": "Jessica Rose", "author_slug": "jessicarose", "published": "2017-12-16T00:00:00+00:00", "url": "https://24ways.org/2017/care-and-feeding-of-burnout/", "topic": "process"}
{"rowid": 213, "title": "Accessibility Through Semantic HTML", "contents": "Working on Better, a tracker blocker, I spend an awful lot of my time with my nose in other people\u2019s page sources. I\u2019m mostly there looking for harmful tracking scripts, but often notice the HTML on some of the world\u2019s most popular sites is in a sad state of neglect.\nWhat does neglected HTML look like? Here\u2019s an example of the markup I found on a news site just yesterday. There\u2019s a bit of text, a few links, and a few images. But mostly it\u2019s div elements.\n\n
\n
\n
\n
\n
\n
\n Some text
more text \n
\n
\n
\n
\n
\ndivs and spans, why do we use them so much?\nWhile I find tracking scripts completely inexcusable, I do understand why people write HTML like the above. As developers, we like to use divs and spans as they\u2019re generic elements. They come with no associated default browser styles or behaviour except that div displays as a block, and span displays inline. If we make our page up out of divs and spans, we know we\u2019ll have absolute control over styles and behaviour cross-browser, and we won\u2019t need a CSS reset.\nAbsolute control may seem like an advantage, but there\u2019s a greater benefit to less generic, more semantic elements. Browsers render semantic elements with their own distinct styles and behaviours. For example, button looks and behaves differently from a. And ul is different from ol. These defaults are shortcuts to a more usable and accessible web. They provide consistent and well-tested components for common interactions.\nSemantic elements aid usability\nA good example of how browser defaults can benefit the usability of an element is in the option menu. In Safari on the desktop, the browser renders as a popover-style menu. On a touchscreen, Safari overlays the same menu over the lower half of the screen as a \u201cpicker view.\u201d\nOption menu in Safari on macOS.\nOption menu picker in Safari on iOS.\nThe iOS picker is a much better experience than struggling to pick from a complicated interface inside the page. The menu is shown more clearly than in the confined space on the page, which makes the options easier to read. The required swipe and tap gestures are consistent with the rest of the operating system, making the expected interaction easier to understand. The whole menu is scaled up, meaning the gestures don\u2019t need such fine motor control. Good usability is good accessibility.\nWhen we choose to use a div or span over a more semantic HTML element, we\u2019re also doing hard work the browser could be doing for us. We don\u2019t need to tie ourselves in knots making a custom div into a keyboard navigable option menu. Using select passes the bulk of the responsibility over to the browser.\u00a0\nLetting the browser do most of the work is also more future-friendly. More devices, with different expected interactions, will be released in the future. When that happens, the devices\u2019 browsers can adapt our sites according to those interactions. Then we can spend our time doing something more fun than rewriting cross-browser JavaScript for each new device.\nHTML\u2019s impact on accessibility\nAssistive technology also uses semantic HTML to understand how best to convey each element to its user.\nFor screen readers\nSemantic HTML gives context to screen readers. Screen readers are a type of assistive technology that reads the content of the screen to the person using it. All sites have a linear page source. Sighted visitors can use visual cues on the page to navigate to their desired content in a non-linear fashion. As screen readers output audio (and sometimes braille), those visual cues aren\u2019t usable in the same way.\nScreen readers provide alternative means of navigation, enabling people to jump between different types of content, such as links, forms, headings, lists, and paragraphs. If all our content is marked up using divs and spans, we\u2019re not giving screen readers a chance to index the valuable content.\nFor keyboard navigation\nKeyboard-only navigation is also aided by semantic HTML. Forms, option menus, navigation, video, and audio are particularly hard for people relying on a keyboard to access. For instance, option menus and navigation can be very fiddly if you need to use a mouse to hover a menu open and move to select the desired item at the same time.\u00a0\nAgain, we can leave much of the interaction to the browser through semantic HTML. Semantic form elements can convey if a check box has been checked, or which label is associated with which input field. These default behaviours can make the difference between a person being able to use a form or leaving the site out of frustration.\nDid I convince you yet? I hope so. Let\u2019s finish with some easy guidelines to follow.\n1. Use the most semantic HTML element for the job\nWhen you reach for a div, first check if there\u2019s a better element to do the job. What is the role of that element? How should a person be interacting with the element?\nAre you using class names like nav, header, or main? There are HTML5 elements for those sections! Using specific elements can also make writing CSS simpler, and ensure a consistent design with minimal effort.\n2. Separate structure and style\nDon\u2019t choose HTML elements based on how they\u2019re styled in your CSS. Nowadays, common practice is to use class names rather than elements for CSS selectors. You\u2019re unlikely to wrap all your page content in an element because you want all the text to be big and bold. Still, it can be easy to choose an HTML element because it will be the easiest to style. Focusing on content without style will help us choose the most semantic HTML element without that temptation. For example, you could add a class of .btn to a div to make it look like a button. But we all know that only a button will really behave like a button.\n3. Use progressive enhancement for enhanced functionality\nAirbnb and Groupon recently proved we\u2019re not past the laziness of \u201cthis site only works in X browser.\u201d Baffling disregard for the open web aside, making complex interactive experiences work cross-browser and cross-device is not easy. We can use progressive enhancement to layer fancy or unsupported features on top of a baseline \u201cit works\u201d experience.\u00a0\nWe should build the baseline experience on a foundation of accessible, semantic HTML. Then, if you really want to add a specific feature for a proprietary browser, you can layer that on top, without breaking the underlying experience.\n4. Test your work\nValidators are always valuable for checking the browser will be able to correctly interpret your markup. Document outline checkers can be valuable for testing your structure, but be aware that the HTML5 document outline is not actually implemented in browsers.\nOnce you\u2019ve got something resembling a web page, test the experience! Ensure that semantic HTML element you chose looks and behaves in a predictable manner consistent with its use across the web. Test cross-browser, test cross-device, and test with assistive technology. Testing with assistive technology is not as expensive as it used to be, you can even use your smartphone for testing on iOS and Android. Your visitors will thank you!\nFurther reading\n\nAccessibility For Everyone by Laura Kalbag\nHTML5 Doctor\nHTML5 Accessibility\nAn overview of HTML5 Semantics\nHTML reference on MDN\u00a0\nHeydon Pickering\u2019s Inclusive Design Checklist\nThe Paciello Group\u2019s Inclusive Design Principles", "year": "2017", "author": "Laura Kalbag", "author_slug": "laurakalbag", "published": "2017-12-15T00:00:00+00:00", "url": "https://24ways.org/2017/accessibility-through-semantic-html/", "topic": "code"}
{"rowid": 205, "title": "Why Design Systems Fail", "contents": "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.\nA design system is a culmination of several individual components, which can include any or all of the following (and more):\n\nStyle guide or visual pattern library\nDesign tooling (e.g. Sketch Library)\nComponent library (where the components live in code)\nCode usage guidelines and documentation\nDesign usage documentation\nVoice and tone guideline\nAnimation language guideline\n\nDesign 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.\nI\u2019d like to go over a few considerations to ensure design system success and what could hinder that success.\nOrganizational Support\nPut 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. \nWhat I mean by that is that there needs to be top-level support from project managers up through VP\u2019s 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.\nSupport 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\u2019s 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.\nA design system needs support and love to be nurtured and to grow. It also needs investment.\nInvestment\nTo 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.\nYou 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\u2019ll see yourself maintaining your fitness level at a much higher rate than if you stopped completely. \nIf you invest once in a design system (say, 3 months of overhauling it) but neglect to keep it up, you\u2019ll face the same situation. You\u2019ll see immediate impact, but that impact will fade as it gets out of sync with new designs and you\u2019ll 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\u2019ll find yourself in for another round of large investment (while dreading going through the process since its fallen so far out of shape).\n\nWith design systems, small incremental investments over time lead to big gains overall.\n\nWith 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\u2019t want to scale a brittle system that\u2019s not easy to use.\nTake 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.\nResponsibility\nWith 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\nmade of both designers and engineers (the best option), your company is more likely to keep a relevant, up-to-date system that doesn\u2019t break.\nThis team is responsible for a few things:\n\nHelping others get set up on the system (support)\nDesigning and building components (development)\nAdvocating for overall UI consistency and adherence (evangelism)\nCreating a rollout plan and update system (product management)\n\nAs 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\u2019ve 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.\nCommunication\nOnce 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.\nRemember 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.\nThis can be challenging, especially since ultimately, some party needs to be making a final decision on direction and execution. Because it\u2019s a hard balance to strike, having open communication channels and being as transparent as possible as early as possible is a good start.\nBuy-in\nFor all of the reasons we\u2019ve 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.\n\nBuilding and maintaining a design system is surprisingly a lot of people-ops work.\n\nTo get buy-in where you don\u2019t 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.\nGather examples and usage wins, because showing is much more powerful than telling.\nIf 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:\n\nEvangelize for the design system\nSee what people were using the component library for and what they were struggling with (excellent user testing there)\nGet user feedback afterward on how to improve it in future iterations\nLet people experience the benefits of using it themselves\n\nThese 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\u2019t love it \u2014 listen to them on how to improve it so that they do). We don\u2019t always get so lucky as to have this sort of instantaneous user feedback from our direct users.\nArchitecture\nI briefly mentioned the scalable nature of design systems. This is exactly why it\u2019s 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\u2019s room for customization and growth?\nA few things we\u2019ve found helpful include:\nNamespacing\nUse namespacing to ensure that the system doesn\u2019t 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\u2019t 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. \nThis kind of namespacing wouldn\u2019t be necessary per se on new projects, but it is definitely useful when integrating new and old styles.\nSemantic Versioning\nI\u2019ve used Semantic Versioning on all of the design systems I\u2019ve 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\u2019s app won\u2019t break unintentionally when there is an update, if they are anchored to a specific version (which they should be).\nWe 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.\nOur 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. \nSo, semantic versioning for the system I\u2019m currently building is what links our design system node module assets, sketch library assets, and statically built file assets.\nThe reason we have so many ways of consuming our design system is to make adoption easier and to reduce friction.\nFriction\nA while ago, I posed the question of why design systems become outdated and unused, and a major conclusion I drew from the conversation was:\n\n\u201cIf it\u2019s harder for people to use than their current system, people just won\u2019t use it\u201d\n\nYou 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.\nBut 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\u2019re 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.\nWith the DigitalOcean design system, we provide a few options:\nOption 1\nUsers 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.\nBut 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.\nOption 2\nWith 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\u2019t the aim when people are using Option 2.\nReducing friction for adoption should be a major goal of your design system rollout.\nConclusion\nHaving a design system is really beneficial to any product, especially as it grows. In order to have an effective system, it\u2019s 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!", "year": "2017", "author": "Una Kravets", "author_slug": "unakravets", "published": "2017-12-14T00:00:00+00:00", "url": "https://24ways.org/2017/why-design-systems-fail/", "topic": "process"}
{"rowid": 206, "title": "Getting Hardboiled with CSS Custom Properties", "contents": "Custom Properties are a fabulous new feature of CSS and have widespread support in contemporary browsers. But how do we handle browsers without support for CSS Custom Properties? Do we wait until those browsers are lying dead in a ditch before we use them? Do we tool up and prop up our CSS using a post-processor? Or do we get tough? Do we get hardboiled?\nPreviously only pre-processing tools like LESS and Sass enabled developers to use variables in their stylesheets, but now Custom Properties have brought variables natively to CSS.\nHow do you write a custom property? It\u2019s hardly a mystery. Simply add two dashes to the start of a style rule. Like this:\n--color-text-default : black;\nIf you\u2019re more the underscore type, try this:\n--color_text_default : black;\nHyphens or underscores are allowed in property names, but don\u2019t be a chump and try to use spaces. \nCustom property names are also case-sensitive, so --color-text-default and --Color_Text_Default are two distinct properties.\nTo use a custom property in your style rules, var() tells a browser to retrieve the value of a property. In the next example, the browser retrieves the black colour from the color-text-default variable and applies it to the body element:\nbody {\n color : var(--color-text-default); \n}\nLike variables in LESS or Sass, CSS Custom Properties mean you don\u2019t have to be a dumb mug and repeat colour, font, or size values multiple times in your stylesheets. Unlike a preprocessor variable though, CSS Custom Properties use the cascade, can be modified by media queries and other state changes, and can also be manipulated by Javascript.\n(Serg Hospodarets wrote a fabulous primer on CSS Custom Properties where he dives deeper into the code and possible applications.)\nBrowser support\nNow it\u2019s about this time that people normally mention browser support. So what about support for CSS Custom Properties? Current versions of Chrome, Edge, Firefox, Opera, and Safari are all good. Internet Explorer 11 and before? Opera Mini? Nasty.\nSound familiar?\n\n Can I Use css-variables? Data on support for the css-variables feature across the major browsers from caniuse.com.\n\nNot to worry, we can manually check for Custom Property support in a browser by using an @support directive, like this:\n--color-text-default : black;\n\nbody {\n color : black; \n}\n\n@supports ((--foo : bar)) {\n body {\n color : var(--color-text-default); \n }\n}\nIn that example we first set body element text to black and then override that colour with a Custom Property value when the browser supports our fictitious foo bar variable.\nSubstitutions\nIf we reference a variable that hasn\u2019t been defined, that won\u2019t be a problem as browsers are smart enough to ignore the value altogether. If we need a cast iron alibi, use substitutions to specify a fall-back value.\nbody {\n color : var(--color-text-default, black); \n}\nSubstitutions are similar to font stacks in that they contain a comma separated list of values. If there\u2019s no value associated with a property, a browser will ignore it and move onto the next value in the list.\nPost-processing\nOf course we could use a post-processor plugin to turn Custom Properties into plain CSS, but hang on one goddam minute kiddo.\nHaven\u2019t we been down this road before? Didn\u2019t we engineer elaborate workarounds to enable us to use \u2018advanced\u2019 CSS3 properties like border-radius, CSS columns, and Flexbox in the past? We did what we had to do to get the job done, but came away feeling dirty.\nI think there\u2019s a better way, one that allows us to enjoy the benefits of CSS Custom Properties in browsers that support them, while providing an appropriate, but not identical experience, for people who use less capable browsers. Guess what, I\u2019ve been down this road before too. \n2Tone Stuff & Nonsense\nWhen Internet Explorer 6 was the big dumb browser everyone hated, I served two different designs on my website. \nFor the modern browsers of the time, mod arrows and targets were everywhere in glorious red, white, and blue, and I implemented all of them using CSS attribute selectors which were considered advanced at the time:\n[class=\"banner\"] {\n background-colour : red; \n}\nInternet Explorer 6 ignored any selectors it didn\u2019t understand, so people using that browser saw a simpler black and white, 2Tone-based design that I\u2019d implemented for them using class selectors:\n.banner {\n background-colour : black; \n}\n\n[class=\"banner\"] {\n background-colour : red; \n}\n\nYou don\u2019t have to be a detective to find out that most people thought I\u2019d lost my wits, but Microsoft even used my website as a reference when they tested attribute selectors in Internet Explorer 7. They did, as I suggested, \u201cStomp to da betta browser.\u201d\nDumb browsers look the other way\nSo how does this approach relate to tackling any lack of support for CSS Custom Properties? How can we take advantage of them without worrying about browsers with no support and having to implement complex workarounds, or spending hours specifying fallbacks that perfectly match our designs?\nTurns out, the answer is built into CSS, and always has been, because when browsers don\u2019t know what they\u2019re looking at, they look away. \nAll we have to do is first specify values for a simpler design first, and then follow that up with the values in our CSS Custom Properties:\nbody {\n color : black;\n color : var(--color-text-default, black); \n}\nAll browsers understand the first value (black,) and if they\u2018re smart enough to understand the second (var(--color-text-default)), they\u2019ll use it and override the first. If they\u2019re too damn stupid to understand the custom property value, they\u2019ll ignore it. Nobody dies.\nRepeat this for every style that contains a variable, baking an alternative, perhaps simpler design into your stylesheets for people who use less capable browsers, just like I did with Stuff & Nonsense.\nConclusion\nI doubt that anyone agrees with presenting a design that looks broken or unloved\u2014and I\u2019m not advocating for that\u2014but websites need not look the same in every browser. We can use substitutions to present a simpler design to people using less capable browsers.\nThe decision when to start using new CSS properties isn\u2018t always a technical one. Sometimes a change in attitude about browser support is all that\u2019s required. So get tough with dumb browsers and benefit from all the advantages that CSS Custom Properties offer. Get hardboiled.\nResources:\n\nIt\u2019s Time To Start Using CSS Custom Properties\u2014Smashing Magazine\nUsing CSS variables correctly\u2014Mike Riethmuller\nDeveloping Inspired Guides with CSS Custom Properties (variables)\u2014Andy Clarke", "year": "2017", "author": "Andy Clarke", "author_slug": "andyclarke", "published": "2017-12-13T00:00:00+00:00", "url": "https://24ways.org/2017/getting-hardboiled-with-css-custom-properties/", "topic": "code"}
{"rowid": 202, "title": "Design Systems and CSS Grid", "contents": "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\u2019re looking to push this forward into 2018 with some small and possibly some larger changes.\nTo 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.\n\nAs 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.\nThe existing grid system\nWhen the site was rebuilt in 2015 the team decided to make use of Sass and Susy, a \u201clightweight grid-layout engine using Sass\u201d. 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.\nTo 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:\n\nUsing 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.\nAlthough there is this reliance on several 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 \u2018fit\u2019 where needed.\nThe requirements of the new grid system\nMoving forward I set myself some goals for what I\u2019d like to have achieved in this new grid system:\nIt needs to behave like the existing grid systems\nWe 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.\nAllow full-width components\nCurrently 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.\nLess of a tag soup\nIdeally 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.\nI would like to move the layout logic to CSS as much as is possible, potentially creating some utility classes or additional \u2018layout classes\u2019 for the components.\nEasier for people to use and author\nWith 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
s as needed and would require new documentation and examples, and potentially some initial training.\nSeparating layout from style\nThere 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.\nWith these base requirements I took to CodePen and started working on some throwaway code to get started.\nMaking the new grid(s)\nThe Full-Width Grid\nTo 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.\nThankfully, one of Rachel Andrew\u2019s many articles on Grid discussed this exact requirement of the new grid system to break out with Grid.\nI took some of the code in the examples and edited to make grid we needed.\n.container {\n display: grid;\n grid-template-columns:\n [full-start]\n minmax(.75em, 1fr)\n [main-start]\n minmax(0, 1008px)\n [main-end]\n minmax(.75em, 1fr)\n [full-end];\n}\nWe 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.\nBoth 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.\nAt this point I noticed that older versions of Sass cannot parse the brackets in this code. To combat this I used Sass\u2019 unquote method to wrap around the value of the grid-template-column.\n.container {\n display: grid;\n grid-template-columns:\n unquote(\"\n [full-start]\n minmax(.75em, 1fr)\n [main-start]\n minmax(0, 1008px)\n [main-end]\n minmax(.75em, 1fr)\n [full-end]\n \");\n}\nThe 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).\nThe initial full-width grid displays on a webpage as below:\n\nThe 14 column grid\nI 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.\nAlong with the many other resources on Grid, Mozilla\u2019s 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:\n.inner {\n display: grid;\n grid-template-columns: repeat(14, [col-start] 1fr);\n grid-gap: .75em;\n}\nWe, 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.\nThis grid would display on web page as below:\n\nBringing the grids together\nNow 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.\nThe subgrid\nThere 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.\nIn the HTML we nest the 14 column inner grid inside the full-width container.\n
\nSo 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.\n.inner {\n display: grid;\n grid-column: main-start / main-end;\n grid-template-columns: repeat(14, [col-start] 1fr);\n grid-gap: .75em;\n}\nThe CSS for the container remains unchanged.\n\nThis works, but we have added another div to our HTML. One of our requirements is to try and remove the potential for tag soup.\nThe faux subgrid subgrid\nI 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.\n.container {\n display: grid;\n grid-gap: .75em;\n grid-template-columns:\n [full-start]\n minmax(.75em, 1fr)\n [main-start]\n repeat(14, [col-start] 1fr)\n [main-end]\n minmax(.75em, 1fr)\n [full-end];\n}\nWhat 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.\n\nI 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.\nI 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
would be a necessity.\nAt 3 in the morning, when I was failing to get to sleep, my mind happened upon an question: \u201cCould you use calc?\u201d\nAt 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.\ncalc(calc(100% - 1008px) / 2)\nThe CSS above was part of the value that I would need to include in the declaration for the grid.\n.container {\n display: grid;\n grid-gap: .75em;\n grid-template-columns:\n [full-start]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [main-start]\n repeat(14, [col-start] 1fr)\n [main-end]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [full-end];\n}\nWe have created the grid required. A full-width grid, with a central 14 column grid, using fewer
elements.\n\nSee the Pen Design Systems and CSS Grid, 6 by Stuart Robson (@sturobson) on CodePen.\n\nSuccess!\nProgressive enhancement\nNow that we have created the grid system required we need to back-track a little.\nNot 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\u2019t have support. The effort required to make the grid system fall back for these browsers depends on your product or sites browser support.\n\nTo 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.\n@supports (display: grid) {\n /* Styles for browsers that support Grid */\n}\nIf 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.\nA website doesn\u2019t have to look the same in every browser after all.\nA responsive grid\nWe 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.\nAt smaller viewports we have a single column layout where every item of content, every component stacks atop each other. We don\u2019t 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.\n/*\n * to start with there is no 'grid' just a single column\n */\n.container {\n padding: 0 .75em;\n}\n\n/*\n * when we get to 700px we create an 8 column grid with\n * a left and right area to breakout of the grid.\n */\n@media (min-width: 700px) {\n .container {\n display: grid;\n grid-gap: .75em;\n grid-template-columns:\n [full-start]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [main-start]\n repeat(8, [col-start] 1fr)\n [main-end]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [full-end];\n padding: 0;\n }\n}\n\n/*\n * when we get to 1100px we create an 14 column grid with\n * a left and right area to breakout of the grid.\n */\n@media (min-width: 1100px) {\n .container {\n grid-template-columns:\n [full-start]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [main-start]\n repeat(14, [col-start] 1fr)\n [main-end]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [full-end];\n }\n}\nBeing 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).\nLet\u2019s use CSS custom properties. We need to declare the variable first by adding it to our stylesheet.\n:root {\n --inner-grid-columns: 8;\n}\nWe then need to edit a few more lines. First make use of the variable for this line.\nrepeat(8, [col-start] 1fr)\n/* replace with */\nrepeat(var(--inner-grid-columns), [col-start] 1fr)\nThen at the 1100px breakpoint we would only need to change the value of the \u2014inner-grid-columns value.\n@media (min-width: 1100px) {\n .container {\n grid-template-columns:\n [full-start]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [main-start]\n repeat(14, [col-start] 1fr)\n [main-end]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [full-end];\n }\n}\n/* replace with */\n@media (min-width: 1100px) {\n .container {\n --inner-grid-columns: 14;\n }\n}\nSee the Pen Design Systems and CSS Grid, 8 by Stuart Robson (@sturobson) on CodePen.\n\nThe final grid system\nWe 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
that could have been needed for the nested 14 column grid.\nWe can move on to the new component.\nCreating a new component\nBack to the new components we are needing to create.\n\nTo 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.\nTo start with we should write the HTML for the component, something like this:\n
\n \n
\n \n \n \n \nTo 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.\nAs the grid doesn\u2019t get invoked until 700px it is possible to negate the need for a media query.\n.features {\n grid-column: col-start 1 / span 6;\n}\n\n@supports (display: grid) {\n @media (min-width: 1100px) {\n .features {\n grid-column-end: 9;\n }\n }\n}\nWe 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.\n.features:nth-of-type(even) {\n grid-column-start: 4;\n grid-row: 2;\n}\n\n@supports (display: grid) {\n @media (min-width: 1100px) {\n .features:nth-of-type(even) {\n grid-column-start: 9;\n grid-column-end: 16;\n }\n }\n}\nWe 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.\nWe 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.\n.features {\n grid-column: col-start 1 / span 6;\n --features-grid-columns: 5;\n}\n\n@supports (display: grid) {\n @media (min-width: 700px) {\n .features {\n display: grid;\n grid-gap: .75em;\n grid-template-columns: repeat(var(--features-grid-columns), [col-start] 1fr);\n }\n }\n}\n\n@supports (display: grid) {\n @media (min-width: 1100px) {\n .features {\n grid-column-end: 9;\n --features-grid-columns: 7;\n }\n }\n}\nSee the Pen Design Systems and CSS Grid, 10 by Stuart Robson (@sturobson) on CodePen.\n\nLaying out the parts\nLooking 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.\nWe could use the grid-column shorthand that incorporates grid-column-start and grid-column-end or we can make use of grid-template-areas.\ngrid-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.\n\nWithin the .features rule we can add the relevant grid-template-areas value to represent the above.\n.features {\n display: grid;\n grid-template-columns: repeat(var(--features-grid-columns), [col-start] 1fr);\n grid-template-areas:\n \". title title title title title title\"\n \". subtitle subtitle subtitle subtitle subtitle . \"\n \". content content content content . . \"\n \". list list list . . . \"\n \". . . . link link link \";\n}\n\nIn order to make the variant of the component we would have to create the grid-template-areas for that component too.\nWe then need to tell each element of the component in what grid-area it should be placed within the grid.\n.features__title { grid-area: title; }\n.features__subtitle { grid-area: subtitle; }\n.features__content { grid-area: content; }\n.features__list { grid-area: list; }\n.features__link { grid-area: link; }\nSee the Pen Design Systems and CSS Grid, 12 by Stuart Robson (@sturobson) on CodePen.\n\nThe other way would be to use the grid-column shorthand and the grid-column-start and grid-column-end we have used previously.\n.features .features__title {\n grid-column: col-start 2 / span 6;\n}\n.features .features__subtitle {\n grid-column: col-start 2 / span 5;\n}\n.features .features__content {\n grid-column: col-start 2 / span 4;\n}\n.features .features__list {\n grid-column: col-start 2 / span 4;\n}\n.features .features__link {\n grid-column: col-start 5 / span 3;\n}\nFor 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.\n.features:nth-of-type(even) .features__title {\n grid-column-start: col-start 1;\n}\n.features:nth-of-type(even) .features__subtitle {\n grid-column-start: col-start 1;\n}\n.features:nth-of-type(even) .features__content {\n grid-column-start: col-start 3;\n}\n.features:nth-of-type(even) .features__list {\n grid-column-start: col-start 3;\n}\n.features:nth-of-type(even) .features__link {\n grid-column-start: col-start 1;\n}\nSee the Pen Design Systems and CSS Grid, 14 by Stuart Robson (@sturobson) on CodePen.\n\nI 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.\nSome additional decisions\nThe 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\u2019t 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.\nOne 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 *=.\n.features [class*=\"title\"] {\n grid-column: col-start 2 / span 6;\n}\n.features [class*=\"subtitle\"] {\n grid-column: col-start 2 / span 5;\n}\n.features [class*=\"content\"] {\n grid-column: col-start 2 / span 4;\n}\n.features [class*=\"list\"] {\n grid-column: col-start 2 / span 4;\n}\n.features [class*=\"link\"] {\n grid-column: col-start 5 / span 3;\n}\nSee the Pen Design Systems and CSS Grid, 15 by Stuart Robson (@sturobson) on CodePen.\n\nAlthough 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\u2019t 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.\nWe have only looked at columns, as existing components have their own spacing for the vertical rhythm of the page we don\u2019t 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.\nThe grid of the future\nFrom prototyping this new grid and components in CSS Grid, I\u2019ve 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.\nIt allows us to carry on \u2013 if we choose to \u2013 using a
-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 \u2018grid components\u2019 in our design system that we could use to layout various components throughout a page.\nIf 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.\nIt really feels like the possibilities are endless in terms of layout for the web.\nResources\nHere are just a few resources I have pawed over these last few weeks whilst getting acquainted with CSS Grid.\n\nA collection of CodePens from this article\nGrid by Example from Rachel Andrew\nA Complete Guide to CSS Grid on Codrops from Hui Jing Chen\nRachel Andrew\u2019s Blog Archive tagged: cssgrid\nCSS Grid Layout Examples\nMDN\u2019s CSS Grid Layout\nA Complete Guide to Grid from CSS-Tricks\nCSS Grid Layout Module Level 1 Specification", "year": "2017", "author": "Stuart Robson", "author_slug": "stuartrobson", "published": "2017-12-12T00:00:00+00:00", "url": "https://24ways.org/2017/design-systems-and-css-grid/", "topic": "code"}
{"rowid": 215, "title": "Teach the CLI to Talk Back", "contents": "The CLI is a daunting tool. It\u2019s quick, powerful, but it\u2019s also incredibly easy to screw things up in \u2013 either with a mistyped command, or a correctly typed command used at the wrong moment. This puts a lot of people off using it, but it doesn\u2019t have to be this way.\nIf you\u2019ve ever interacted with Slack\u2019s Slackbot to set a reminder or ask a question, you\u2019re basically using a command line interface, but it feels more like having a conversation. (My favourite Slack app is Lunch Train which helps with the thankless task of herding colleagues to a particular lunch venue on time.)\nSame goes with voice-operated assistants like Alexa, Siri and Google Home. There are even games, like Lifeline, where you interact with a stranded astronaut via pseudo SMS, and KOMRAD where you chat with a Soviet AI.\nI\u2019m not aiming to build an AI here \u2013 my aspirations are a little more down to earth. What I\u2019d like is to make the CLI a friendlier, more forgiving, and more intuitive tool for new or reluctant users. I want to teach it to talk back.\nInteractive command lines in the wild\nIf you\u2019ve used dev tools in the command line, you\u2019ve probably already used an interactive prompt \u2013 something that asks you questions and responds based on your answers. Here are some examples:\nYeoman\nIf you have Yeoman globally installed, running yo will start a command prompt.\n\nThe prompt asks you what you\u2019d like to do, and gives you options with how to proceed. Seasoned users will run specific commands for these options rather than go through this prompt, but it\u2019s a nice way to start someone off with using the tool.\nnpm\nIf you\u2019re a Node.js developer, you\u2019re probably familiar with typing npm init to initialise a project. This brings up prompts that will populate a package.json manifest file for that project.\n\nThe alternative would be to expect the user to craft their own package.json, which is more error-prone since it\u2019s in JSON format, so something as trivial as an extraneous comma can throw an error.\nSnyk\nSnyk is a dev tool that checks for known vulnerabilities in your dependencies. Running snyk wizard in the CLI brings up a list of all the known vulnerabilities, and gives you options on how to deal with it \u2013 such as patching the issue, applying a fix by upgrading the problematic dependency, or ignoring the issue (you are then prompted for a reason).\n\nThese decisions get mapped to the manifest and a .snyk file, and committed into the repo so that the settings are the same for everyone who uses that project.\nI work at Snyk, and running the wizard is what made me think about building my own personal assistant in the command line to help me with some boring, repetitive tasks.\nWriting your own\nSomething I do a lot is add bookmarks to styleguides.io \u2013 I pull down the entire repo, copy and paste a template YAML file, and edit to contents. Sometimes I get it wrong and break the site. So I\u2019ve been putting together a tool to help me add bookmarks.\nIt\u2019s called bookmarkbot \u2013 it\u2019s a personal assistant squirrel called Mark who will collect and bury your bookmarks for safekeeping.*\n\n*Fortunately, this metaphor also gives me a charming excuse for any situation where bookmarks sometimes get lost \u2013 it\u2019s not my poorly-written code, honest, it\u2019s just being realistic because sometimes squirrels forget where they buried things!\nWhen you run bookmarkbot, it will ask you for some information, and save that information as a Markdown file in YAML format.\nFor this demo, I\u2019m going to use a Node.js package called inquirer, which is a well supported tool for creating command line prompts. I like it because it has a bunch of different question types; from input, which asks for some text back, confirm which expects a yes/no response, or a list which gives you a set of options to choose from. You can even nest questions, Choose Your Own Adventure style.\nPrerequisites\n\nNode.js\nnpm\nRubyGems (Only if you want to go as far as serving a static site for your bookmarks, and you want to use Jekyll for it)\n\nDisclaimer\nBear in mind that this is a really simplified walkthrough. It doesn\u2019t have any error states, and it doesn\u2019t handle the situation where we save a file with the same name. But it gets you in a good place to start building out your tool.\nLet\u2019s go!\nCreate a new folder wherever you keep your projects, and give it an awesome name (I\u2019ve called mine bookmarks and put it in the Sites directory because I\u2019m unimaginative). Now cd to that directory. \ncd Sites/bookmarks\nLet\u2019s use that example I gave earlier, the trusty npm init.\nnpm init\nPop in the information you\u2019d like to provide, or hit ENTER to skip through and save the defaults. Your directory should now have a package.json file in it. Now let\u2019s install some of the dependencies we\u2019ll need.\nnpm install --save inquirer\nnpm install --save slugify\nNext, add the following snippet to your package.json to tell it to run this file when you run npm start.\n\"scripts\": {\n \u2026\n \"start\": \"node index.js\"\n}\nThat index.js file doesn\u2019t exist yet, so let\u2019s create it in the root of our folder, and add the following:\n// Packages we need\nvar fs = require('fs'); // Creates our file (part of Node.js so doesn't need installing)\nvar inquirer = require('inquirer'); // The engine for our questions prompt\nvar slugify = require('slugify'); // Will turn a string into a usable filename\n\n// The questions\nvar questions = [\n {\n type: 'input',\n name: 'name',\n message: 'What is your name?',\n },\n];\n\n// The questions prompt\nfunction askQuestions() {\n\n // Ask questions\n inquirer.prompt(questions).then(answers => {\n\n // Things we'll need to generate the output\n var name = answers.name;\n\n // Finished asking questions, show the output\n console.log('Hello ' + name + '!');\n\n });\n\n}\n\n// Kick off the questions prompt\naskQuestions();\nThis is just some barebones where we\u2019re including the inquirer package we installed earlier. I\u2019ve stored the questions in a variable, and the askQuestions function will prompt the user for their name, and then print \u201cHello
\u201d in the console.\nEnough setup, let\u2019s see some magic. Save the file, go back to the command line and run npm start.\n\nExtending what we\u2019ve learnt\nAt the moment, we\u2019re just saving a name to a file, which isn\u2019t really achieving our goal of saving bookmarks. We don\u2019t want our tool to forget our information every time we talk to it \u2013 we need to save it somewhere. So I\u2019m going to add a little function to write the output to a file.\nSaving to a file\nCreate a folder in your project\u2019s directory called _bookmarks. This is where the bookmarks will be saved.\nI\u2019ve replaced my questions array, and instead of asking for a name, I\u2019ve extended out the questions, asking to be provided with a link and title (as a regular input type), a list of tags (using inquirer\u2019s checkbox type), and finally a description, again, using the input type.\nSo this is how my code looks now:\n// Packages we need\nvar fs = require('fs'); // Creates our file\nvar inquirer = require('inquirer'); // The engine for our questions prompt\nvar slugify = require('slugify'); // Will turn a string into a usable filename\n\n// The questions\nvar questions = [\n {\n type: 'input',\n name: 'link',\n message: 'What is the url?',\n },\n {\n type: 'input',\n name: 'title',\n message: 'What is the title?',\n },\n {\n type: 'checkbox',\n name: 'tags',\n message: 'Would you like me to add any tags?',\n choices: [\n { name: 'frontend' },\n { name: 'backend' },\n { name: 'security' },\n { name: 'design' },\n { name: 'process' },\n { name: 'business' },\n ],\n },\n {\n type: 'input',\n name: 'description',\n message: 'How about a description?',\n },\n];\n\n// The questions prompt\nfunction askQuestions() {\n\n // Say hello\n console.log('\ud83d\udc3f Oh, hello! Found something you want me to bookmark?\\n');\n\n // Ask questions\n inquirer.prompt(questions).then((answers) => {\n\n // Things we'll need to generate the output\n var title = answers.title;\n var link = answers.link;\n var tags = answers.tags + '';\n var description = answers.description;\n var output = '---\\n' +\n 'title: \"' + title + '\"\\n' +\n 'link: \"' + link + '\"\\n' +\n 'tags: [' + tags + ']\\n' +\n '---\\n' + description + '\\n';\n\n // Finished asking questions, show the output\n console.log('\\n\ud83d\udc3f All done! Here is what I\\'ve written down:\\n');\n console.log(output);\n\n // Things we'll need to generate the filename\n var slug = slugify(title);\n var filename = '_bookmarks/' + slug + '.md';\n\n // Write the file\n fs.writeFile(filename, output, function () {\n console.log('\\n\ud83d\udc3f Great! I have saved your bookmark to ' + filename);\n });\n\n });\n\n}\n\n// Kick off the questions prompt\naskQuestions();\nThe output is formatted into YAML metadata as a Markdown file, which will allow us to turn it into a static HTML file using a build tool later. Run npm start again and have a look at the file it outputs.\n\nGetting confirmation\nBefore the user makes critical changes, it\u2019s good to verify those changes first. We\u2019re going to add a confirmation step to our tool, before writing the file. More seasoned CLI users may favour speed over a \u201chey, can you wait a sec and just check this is all ok\u201d step, but I always think it\u2019s worth adding one so you can occasionally save someone\u2019s butt.\nSo, underneath our questions array, let\u2019s add a confirmation array.\n// Packages we need\n\u2026\n// The questions\n\u2026\n\n// Confirmation questions\nvar confirm = [\n {\n type: 'confirm',\n name: 'confirm',\n message: 'Does this look good?',\n },\n];\n\n// The questions prompt\n\u2026\n\nAs we\u2019re adding the confirm step before the file gets written, we\u2019ll need to add the following inside the askQuestions function:\n// The questions prompt\nfunction askQuestions() {\n // Say hello\n \u2026\n // Ask questions\n inquirer.prompt(questions).then((answers) => {\n \u2026\n // Things we'll need to generate the output\n \u2026\n // Finished asking questions, show the output\n \u2026\n\n // Confirm output is correct\n inquirer.prompt(confirm).then(answers => {\n\n // Things we'll need to generate the filename\n var slug = slugify(title);\n var filename = '_bookmarks/' + slug + '.md';\n\n if (answers.confirm) {\n // Save output into file\n fs.writeFile(filename, output, function () {\n console.log('\\n\ud83d\udc3f Great! I have saved your bookmark to ' +\n filename);\n });\n } else {\n // Ask the questions again\n console.log('\\n\ud83d\udc3f Oops, let\\'s try again!\\n');\n askQuestions();\n }\n\n });\n\n });\n}\n\n// Kick off the questions prompt\naskQuestions();\nNow run npm start and give it a go!\n\nTyping y will write the file, and n will take you back to the start. Ideally, I\u2019d store the answers already given as defaults so the user doesn\u2019t have to start from scratch, but I want to keep this demo simple.\nServing the files\nNow that your bookmarking tool is successfully saving formatted Markdown files to a folder, the next step is to serve those files in a way that lets you share them online. The easiest way to do this is to use a static-site generator to convert your YAML files into HTML, and pop them all on one page. Now, you\u2019ve got a few options here and I don\u2019t want to force you down any particular path, as there are plenty out there \u2013 it\u2019s just a case of using the one you\u2019re most comfortable with.\nI personally favour Jekyll because of its tight integration with GitHub Pages \u2013 I don\u2019t want to mess around with hosting and deployment, so it\u2019s really handy to have my bookmarks publish themselves on my site as soon as I commit and push them using Git.\nI\u2019ll give you a very brief run-through of how I\u2019m doing this with bookmarkbot, but I recommend you read my Get Started With GitHub Pages (Plus Bonus Jekyll) guide if you\u2019re unfamiliar with them, because I\u2019ll be glossing over some bits that are already covered in there.\nSetting up a build tool\nIf you haven\u2019t already, install Jekyll and Bundler globally through RubyGems. Jekyll is our static-site generator, and Bundler is what we use to install Ruby dependencies.\ngem install jekyll bundler\nIn my project folder, I\u2019m going to run the following which will install the Jekyll files we\u2019ll need to build our listing page. I\u2019m using --force, otherwise it will complain that the directory isn\u2019t empty.\njekyll new . --force\nIf you check your project folder, you\u2019ll see a bunch of new files. Now run the following to start the server:\nbundle exec jekyll serve\nThis will build a new directory called _site. This is where your static HTML files have been generated. Don\u2019t touch anything in this folder because it will get overwritten the next time you build.\nNow that serve is running, go to http://127.0.0.1:4000/ and you\u2019ll see the default Jekyll page and know that things are set up right. Now, instead, we want to see our list of bookmarks that are saved in the _bookmarks directory (make sure you\u2019ve got a few saved). So let\u2019s get that set up next.\nOpen up the _config.yml file that Jekyll added earlier. In here, we\u2019re going to tell it about our bookmarks. Replace everything in your _config.yml file with the following:\ntitle: My Bookmarks\ndescription: These are some of my favourite articles about the web.\nmarkdown: kramdown\nbaseurl: /bookmarks # This needs to be the same name as whatever you call your repo on GitHub.\ncollections:\n - bookmarks\nThis will make Jekyll aware of our _bookmarks folder so that we can call it later. Next, create a new directory and file at _layouts/home.html and paste in the following.\n\n\n\n \n {{site.title}} \n \n\n\n\n\n {{site.title}} \n {{site.description}}
\n\n \n {% for bookmark in site.bookmarks %}\n \n \n {{bookmark.title}} \n \n {{bookmark.content}}\n {% if bookmark.tags %}\n \n {% for tags in bookmark.tags %}{{tags}} {% endfor %}\n \n {% endif %}\n \n {% endfor %}\n \n\n\n\n\nRestart Jekyll for your config changes to kick in, and go to the url it provides you (probably http://127.0.0.1:4000/bookmarks, unless you gave something different as your baseurl).\n\nIt\u2019s a decent start \u2013 there\u2019s a lot more we can do in this area but now we\u2019ve got a nice list of all our bookmarks, let\u2019s get it online!\nIf you want to use GitHub Pages to host your files, your first step is to push your project to GitHub. Go to your repository and click \u201csettings\u201d. Scroll down to the section labelled \u201cGitHub Pages\u201d, and from here you can enable it. Select your master branch, and it will provide you with a url to view your published pages.\n\nWhat next?\nNow that you\u2019ve got a framework in place for publishing bookmarks, you can really go to town on your listing page and make it your own. First thing you\u2019ll probably want to do is add some CSS, then when you\u2019ve added a bunch of bookmarks, you\u2019ll probably want to have some filtering in place for the tags, perhaps extend the types of questions that you ask to include an image (if you\u2019re feeling extra-fancy, you could just ask for a url and pull in metadata from the site itself). Maybe you\u2019ve got an idea that doesn\u2019t involve bookmarks at all.\nYou could use what you\u2019ve learnt to build a place where you can share quotes, a list of your favourite restaurants, or even Christmas gift ideas.\nHere\u2019s one I made earlier\n\nMy demo, bookmarkbot, is on GitHub, and I\u2019ve reused a lot of the code from styleguides.io. Feel free to grab bits of code from there, and do share what you end up making!", "year": "2017", "author": "Anna Debenham", "author_slug": "annadebenham", "published": "2017-12-11T00:00:00+00:00", "url": "https://24ways.org/2017/teach-the-cli-to-talk-back/", "topic": "code"}
{"rowid": 214, "title": "Christmas Gifts for Your Future Self: Testing the Web Platform", "contents": "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\u2019m going to share what I\u2019ve learned about testing the web platform. I\u2019m also going to explain why I think you might want to get involved too.\nWhy test?\nAt 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\u2019t 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\u2019ll be glad to know that isn\u2019t 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 \u201cworks in all browsers\u201d, is hard.\nThanks to web-platform-tests, a test from another browser vendor just found genuine bug in our code before we shipped \ud83d\ude3b\u2014 Brian Birtles (@brianskold) February 10, 2017\n\nIn order for W3C Specifications to move on to become W3C Recommendations we need to have interoperable implementations.\n\n6.2.4 Implementation Experience\nImplementation 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):\nis each feature of the current specification implemented, and how is this demonstrated?\nare there independent interoperable implementations of the current specification?\nare there implementations created by people other than the authors of the specification?\nare implementations publicly deployed?\nis there implementation experience at all levels of the specification\u2019s ecosystem (authoring, consuming, publishing\u2026)?\nare there reports of difficulties or problems with implementation?\nhttps://www.w3.org/2017/Process-20170301/#transition-reqs\n\nWe all want interoperability, achieving interoperability is part of the standards process. The next question is, how do we make sure that we get it?\nUnimplemented vs uninteroperable implementations\nBefore looking at how we can try to improve interoperability, I\u2019d like to look at the reasons we don\u2019t always meet that aim. There are a couple of reasons why browser X is not doing the same thing as browser Y.\nThe 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.\nA 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\u2019s all broken when you test in another.\nA 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.\nMany 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.\nYou will know these interop issues as \u201cbrowser bugs\u201d, 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?\nHow do we ensure we have interoperability?\nIf 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.\nUnless 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.\nThe 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.\nWeb Platform Tests\nWeb 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.\nIf 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.\nCurrently, 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\u2019t 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.\nDiscovering the tests\nI\u2019ve 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.\nIf 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\u2019s probably not you!\nA test on the wpt.fyi dashboard\nNote: 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.\nContributing to Web Platform Tests\nYou 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.\nIn 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.\nA local testing setup\nYour 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:\n\nClone the WPT repo, this is where all the tests are stored\nInstall some tools so you can run up a local copy of the tests\n\nThe 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.\nRunning tests locally\nFinding things to test\nIt\u2019s 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!\nTalk to people\nThere 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.\nGathering information\nFirst 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\u2019t 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 \u2013 if any \u2013 browser is doing it correctly.\nAnother 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.\n\nEdge Issue Tracker\nMozilla Issue Tracker\nWebKit Issue Tracker\nChromium Issue Tracker\n\nWriting the test\nIf you\u2019ve 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 \u201cyes this works as per the spec\u201d or \u201cno, this does not\u201d.\nThe main two types of test are:\n\ntestharness.js tests\nreftests\n\nThe 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\u2019m a complete beginner myself at writing these - I\u2019ll refer you to the excellent tutorial Using testharness.js.\nMany 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.\n\n \nCSS Grid Layout Test: Support for gap shorthand property of row-gap and column-gap \n \n \n \n \n\n\nThe test passes if it has the same visual effect as reference.
\n\nI am testing the new gap property (renamed grid-gap). The reference file can be found by looking for the line:\n \nIn that file, I am using absolute positioning to mock up the way the file would look if gap is implemented correctly.\n\n \nCSS Grid Layout Reference: a square with a green cross \n \n\n\n\nThe tests are compared in an automated way by taking screenshots of the test and reference.\nThese 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.\nCommitting a test\nOnce 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\u2019t accept a test with lint errors, so do this locally first to catch anything obvious.\nTests 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.\nYou 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.\nUsually 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.\nChristmas gifts for your future self\nI 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\u2019m working on it I\u2019ll 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.\nResources\nI 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!\n\nWeb Platform Tests\nUsing testharness.js\nIRC Channel irc://irc.w3.org:6667/testing\nEdge Issue Tracker\nMozilla Issue Tracker\nWebKit Issue Tracker\nChromium Issue Tracker\nReducing an Issue - guide to created a reduced test case\nEffectively Using Web Platform Tests: Slides and Video\nAn excellent walkthrough from Lyza Gardner on her working on tests for the HTML specification - Moving Targets: a case study on testing web standards.\nImproving interop with web-platform-tests: Slides and Video", "year": "2017", "author": "Rachel Andrew", "author_slug": "rachelandrew", "published": "2017-12-10T00:00:00+00:00", "url": "https://24ways.org/2017/testing-the-web-platform/", "topic": "code"}
{"rowid": 216, "title": "Styling Components - Typed CSS With Stylable", "contents": "There\u2019s been a lot of debate recently about how best to style components for web apps so that styles don\u2019t accidentally \u2018leak\u2019 out of the component they\u2019re meant for, or clash with other styles on the page.\nElaborate CSS conventions have sprung up, such as OOCSS, SMACSS, BEM, ITCSS, and ECSS. These work well, but they are methodologies, and require everyone in the team to know them and follow them, which can be a difficult undertaking across large or distributed teams.\nOthers just give up on CSS and put all their styles in JavaScript. Now, I\u2019m not bashing JS, especially so close to its 22nd birthday, but CSS-in-JS has problems of its own. Browsers have 20 years experience in optimising their CSS engines, so JavaScript won\u2019t be as fast as using real CSS, and in any case, this requires waiting for JS to download, parse, execute then render the styles.\nThere\u2019s another problem with CSS-in-JS, too. Since Responsive Web Design hit the streets, most designers no longer make comps in Photoshop or its equivalents; instead, they write CSS. Why hire an expensive design professional and require them to learn a new way of doing their job? \nA recent thread on Twitter asked \u201cWhat\u2019s your biggest gripe with CSS-in-JS?\u201d, and the replies were illuminating: \u201cAlways having to remember to camelCase properties then spending 10min pulling hair out when you do forget\u201d, \u201cthe cryptic domain-specific languages that each of the frameworks do just ever so slightly differently\u201d, \u201cWhen I test look and feel in browser, then I copy paste from inspector, only to have to re-write it as a JSON object\u201d, \u201cLack of linting, autocomplete, and css plug-ins for colors/ incrementing/ etc\u201d. \nIf you\u2019re a developer, and you\u2019re still unconvinced, I challenge you to let designers change the font in your IDE to Zapf Chancery and choose a new colour scheme, simply because they like it better. Does that sound like fun? Will that boost your productivity? Thought not.\nSome chums at Wix Engineering and I wanted to see if we could square this circle. Wix-hosted sites have always used CSS-in-JS (the concept isn\u2019t new; it was in Netscape 4!) but that was causing performance problems. Could we somehow devise a method of extending CSS (like SASS and LESS do) that gives us styles that are guaranteed not to leak or clash, that is compatible with code editors\u2019 autocompletion, and which could be pre-processed at build time to valid, cross-browser, static CSS?\nAfter a few months and a few proofs of concept later (drumroll), yes \u2013 we could! We call it Stylable.\nIntroducing Stylable\nStylable is a CSS pre-processor, like SASS or LESS. It uses CSS syntax so all your development tools will work. At build time, the Stylable CSS extensions are transpiled to flat, valid, cross-browser vanilla CSS for maximum performance. There\u2019s quite a bit to it, and this is a short article, so let\u2019s look at the basic concepts.\nComponents all the way down\nStylable is designed for component-based systems. Imagine you have a Gallery component. Within that, there is a Navigation component (for example, containing a \u2018next\u2019, \u2018previous\u2019, \u2018show all thumbnails\u2019, and \u2018show all albums\u2019 controls), and within that there are NavButton components. Each component is discrete, used elsewhere in the system in different contexts, perhaps maintained by different team members or even different organisations \u2014 you can use Stylable to add a typed interface to non-Stylable component libraries, as well as using it to build an app from scratch.\nFirstly, Stylable will automatically namespace styles so they only apply inside that component, by rewriting them at build time with a unique (but human-readable) prefix. So, for example,\n
might be re-written as . \nSo far, so BEM-like (albeit without the headache of remembering a convention). But what else can it do?\nCustom pseudo-elements\nAn important feature of Stylable is the ability to reach into a component and style it from the outside, without having to know about its internal structure. Let\u2019s see the guts of a simple JSX button component in the file button.jsx:\nrender () {\n return (\n \n \n Submit \n \n );\n}\n(Note:className is the JSX way of setting a class on an element; this example uses React, but Stylable itself is framework-agnostic.)\nI style it using a Stylable stylesheet (the .st.css suffix tells the preprocessor to process this file):\n/* button.st.css */\n\n/* note that the root class is automatically placed on the root HTML \nelement by Stylable React integration */\n.root {\n background: #b0e0e6;\n}\n\n.icon {\n display: block; \n height: 2em;\n background-image: url('./assets/btnIcon.svg');\n}\n\n.label {\n font-size: 1.2em;\n color: rgba(81, 12, 68, 1.0);\n}\nNote that Stylable allows all the CSS that you know and love to be included. As Drew Powers wrote in his review:\n\nwith Stylable, you get CSS, and every part of CSS. This seems like a \u201cduh\u201d observation, but this is significant if you\u2019ve ever battled with a CSS-in-JS framework over a lost or \u201chacky\u201d implementation of a basic CSS feature.\n\nI can import my Button component into another component - this time, panel.jsx:\n/* panel.jsx */\nimport * as React from 'react';\nimport {properties, stylable} from 'wix-react-tools';\nimport {Button} from '../button';\nimport style from './panel.st.css';\n\nexport const Panel = stylable(style)(() => (\n \n \n
\n));\nIn panel.st.css: \n/* panel.st.css */\n:import {\n -st-from: './button.st.css';\n -st-default: Button;\n}\n\n/* cancelBtn is of type Button */\n.cancelBtn {\n -st-extends: Button;\n background: cornflowerblue;\n}\n\n/* targets the label of */\n.cancelBtn::label {\n color: honeydew;\n font-weight: bold;\n}\nHere, we\u2019re reaching into the Button component from the Panel component. Buttons that are not inside a Panel won\u2019t be affected.\nWe do this by extending the CSS concept of pseudo-elements. As MDN says \u201cA CSS pseudo-element is a keyword added to a selector that lets you style a specific part of the selected element(s)\u201d. We don\u2019t use a descendant selector because the label isn\u2019t part of the Panel component, it\u2019s part of the Button component. \nThis syntax allows us three important features: \nPiercing the Shadow Boundary\nBecause, like a Matroshka doll of code, you can have components inside components inside components, you can chain pseudo-elements. In Stylable, Gallery::NavigationPanel::Button::Icon is a legitimate selector. We were worried by this (even though all Stylable CSS is transpiled to flat, valid CSS) because it\u2019s not allowed in CSS, albeit with the note \u201cA future version of this specification may allow multiple pseudo-elements per selector\u201d. So I asked the CSS Working Group and was told \u201cwe intend to only allow specific combinations\u201d, so we feel this extension to CSS is in the spirit of the language.\nWhile we\u2019re on the subject of those pesky Web Standards, note that the proposed ::part and ::theme pseudo-elements are meant to fulfil the same function. However, those are coming in two years (YouTube link) and, when they do, Stylable will support them.\nStructure-agnostic\nThe second totez-groovy\u2122 feature of Stylable\u2019s pseudo-element syntax is that you don\u2019t have to care about the internal structure of the component whose boundary you\u2019re piercing. Any element with a class attribute is exposed as a pseudo-element to any component that imports it. It acts as an interface on any component, whether written in-house or by a third party.\nCode completion\nWhen we started writing Stylable, our objective was to do for CSS what TypeScript does for JavaScript. Wikipedia says\n\nChallenges with dealing with complex JavaScript code led to demand for custom tooling to ease developing of components in the language. TypeScript developers sought a solution that would not break compatibility with the standard and its cross-platform support \u2026 [with] static typing that enables static language analysis, which facilitates tooling and IDE support.\n\nSimilarly, because Stylable knows about components, their stylable parts and states, and how they inter-relate, we can develop language services like code completion and validation. That means we can see our errors at build time or even while working in our IDE. Wave goodbye to silent run-time breakage misery, with the Stylable Intelligence VS Code extension !\nAn action replay of Visual Studio Code offering code completion etc, filmed in super StyloVision.\nPseudo-classes for state\nStylable makes it easy to apply styles to custom states (as well as the usual :active, :checked, :visited etc) by extending the CSS pseudo-class syntax. \nWe do this by declaring the possible custom states on the component:\n/* Gallery.st.css */\n.root {\n -st-states: toggled, loading;\n}\n\n.root:toggled {\n color: red;\n}\n\n.root:loading {\n color: green;\n}\n\n.root:loading:toggled {\n color: blue;\n}\nThe -st-states \u201cproperty\u201d is actually a directive for the transpiler, so Stylable knows about possible pseudo-elements and can offer code completion etc. It looks like a vendor prefix by design, because it\u2019s therefore valid CSS syntax and IDEs won\u2019t flag it as an error, but is removed at build time. Remember, Stylable resolves to flat, valid, cross-browser CSS.\nAs with plain CSS, it can\u2019t set a state, but can only react to states set externally. In the case of custom pseudo-classes, your JavaScript logic is responsible for maintaining state \u2014 by default, by setting a data-* attribute.\nAnd there\u2019s more!\nHopefully, I\u2019ve shown you how Stylable extends CSS to allow you to style components and sub-components without worrying about that styles will leak, or knowing too much about internal structure. There isn\u2019t time to tell you about mixins (CSS macros in JavaScript), variables or our theming capabilities, because I have wine to wrap and presents to mull.\nWe made Stylable because we \u2665 CSS. But there\u2019s a practical reason, too. As James Kyle, a core team member of Yarn, Babel and TC39 (the JavaScript Standards Technical Committee), said of Styable \u201cpretty sure all the CSS-in-JS libraries just died for me\u201d,\nexplaining\n\nCSS could be perfectly static if given the right tools, that\u2019s exactly what stylable does. It gives you the tools you need in CSS so that you don\u2019t need to do a bunch of dynamic shit in JS.\nMaking it static is a huge performance win.\n\nWix is currently battle-testing Stylable in its back-office systems, before rolling it out to power Wix-hosted sites to make them more performant. There are 110 million Wix-hosted sites, so there will be a lot of Stylable on the web in a few months. And it\u2019s open-sourced so you, dear Reader, can try it out and use it too. There\u2019s a Stylable boilerplate based on create-react-app to get you started (more integrations are in the pipeline).\nHappy Hols \u2018n\u2019 Hugz from the Stylable team: Bruce, Arnon, Tom, Ido.\n\nRead more\n\nStylable documentation centre\nStylable on Twitter\nA nice picture of a hedgehog", "year": "2017", "author": "Bruce Lawson", "author_slug": "brucelawson", "published": "2017-12-09T00:00:00+00:00", "url": "https://24ways.org/2017/styling-components-typed-css-with-stylable/", "topic": "code"}
{"rowid": 210, "title": "Stop Leaving Animation to the Last Minute", "contents": "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\u2019s not always enough to really evaluate or invest in animated design solutions. \nBy 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 \u201crunning out of time to add in the animation\u201d 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. \nMotion comps - an animation deliverable\nMotion 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\u2019re most often made with timeline-based tools like Adobe After Effects, Adobe Animate, or Tumult Hype. \nThe 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\u2019re 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\u2019re 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. \n\nOn the surface that seems pretty straight forward, but even with this relatively simple transition there\u2019s a lot that those two artboards don\u2019t address. There are seven things that change between the closed state and the open state. That\u2019s 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. \nBy 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\u2019s making an awful lot of assumptions.\nInstead, 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. \n\nThe 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\u2019re backed up again the deadline will lead to happier teammates and better design solutions. \nWhen to use motion comps\nI\u2019m 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\u2019m trying answer before choosing which sort of deliverable to make to investigate. \nMotion comps can be most helpful for answering questions like: \n\nExactly how should this animation look? \nWhich items should move? Where? And when? \nDo the animation qualities reflect our brand or our voice and tone?\nOne of the added bonuses of creating motion comps to answer these questions is that you\u2019ll have a concrete thing to bring to design critiques or reviews to get others\u2019 input on them as well.\n\nUsing motion comps as handoff\nMotion comps are often used to handoff animation ideas from design to development. They can be super useful for this, but they\u2019re even more useful when you include the details of the motion specs with them. (It\u2019s difficult, if not impossible, to glean these details from playing back a video.)\nMore specifically, you\u2019ll want to include:\n\nDurations and the properties animated for each animation\nEasing curve values or spring values used\nDelay values and repeat counts\n\nIn many cases you\u2019ll have to collect these details up manually. But this isn\u2019t necessarily something that that will take a lot of time. If you take note of them as you\u2019re 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.)\nAnimated prototypes - an interactive deliverable\nMaking prototypes isn\u2019t a new idea for web work by any stretch, but creating prototypes that include animation \u2013 or even creating prototypes specifically to investigate potential animation solutions \u2013 can go a long way towards having higher quality animations in your final product.\nInteractive prototypes are web or app-based, or displayed in a particular tool\u2019s preview window to create a useable version of interactions that might end up in the end product. They\u2019re often made with prototyping apps like Principle, Framer, or coded up in HTML, CSS and JS directly like the example below.\nSee the Pen Prototype example by Val Head (@valhead) on CodePen.\n\nThe 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. \nWhen to use prototypes\nWhen it comes to testing out animation ideas, animated prototypes can be especially helpful in answering questions like these: \n\nHow will this interaction feel to use? (Interactive animations often have different timing needs than animations that are passively viewed.)\nWhat will the animation be like with real data or real content? \nDoes this animation fit the context of the task at hand? \n\nPrototypes can be used to investigate the same questions that motion comps do if you\u2019re 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\u2019re sure to be able to find one that fits your needs. \nAs a quick side note: If you\u2019re worried that your coding skills might not be up to par to prototype in code, know that prototype code doesn\u2019t have to be production quality code. Animated prototypes\u2019 main concern is working out the animation details. Once you\u2019ve arrived at a combination of animations that works, the animation specifics can be extracted or the prototype can be refactored for production.\nMotion comp or prototype?\nBoth 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\u2019s 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\u2019re talking about the same thing and discuss its pros and cons more easily than just describing the idea verbally. \nMotion 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. \nPrototypes 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\u2019s a specific concern.\nGive them a try\nWhichever 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?", "year": "2017", "author": "Val Head", "author_slug": "valhead", "published": "2017-12-08T00:00:00+00:00", "url": "https://24ways.org/2017/stop-leaving-animation-to-the-last-minute/", "topic": "design"}
{"rowid": 211, "title": "Automating Your Accessibility Tests", "contents": "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?\nThis 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.\nAutomated tests can\u2019t cover everything however; only 20 to 50% of accessibility issues can be detected automatically. For example, we can\u2019t yet automate the comparison of an alt attribute with an image\u2019s 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.\nFirst, I\u2019m going to explain how I implemented automated accessibility tests on Elsevier\u2019s ecommerce pages, and share some of the lessons I learnt along the way.\nPicking the right tool\nOne of the hardest, but most important parts of creating our automated accessibility tests was choosing the right tool.\nWe began by investigating aXe CLI, but soon realised it wouldn\u2019t fit our requirements. It couldn\u2019t check pages that required a visitor to log in, so while we could test our product pages, we couldn\u2019t 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. \nThe example below shows the how the beforeScript step completes a login form and then waits for the login to complete before testing the page:\nbeforeScript: function(page, options, next) {\n // An example function that can be used to make sure changes have been confirmed before continuing to run Pa11y\n function waitUntil(condition, retries, waitOver) {\n page.evaluate(condition, function(err, result) {\n if (result || retries < 1) {\n // Once the changes have taken place continue with Pa11y testing\n waitOver();\n } else {\n retries -= 1;\n setTimeout(function() {\n waitUntil(condition, retries, waitOver);\n }, 200);\n }\n });\n }\n\n // The script to manipulate the page must be run with page.evaluate to be run within the context of the page\n page.evaluate(function() {\n const user = document.querySelector('#login-form input[name=\"email\"]');\n const password = document.querySelector('#login-form input[name=\"password\"]');\n const submit = document.querySelector('#login-form input[name=\"submit\"]');\n user.value = 'user@example.com';\n password.value = 'password';\n submit.click();\n }, function() {\n // Use the waitUntil function to set the condition, number of retries and the callback\n waitUntil(function() {\n return window.location.href === 'https://example.com';\n }, 20, next);\n });\n}\nThe waitUntil callback allows the test to be delayed until our test user is successfully logged in.\nAnother 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\u2019s easier to identify the most commons problems. For example, here are some elements that have insufficient colour contrast:\nViolation of \"color-contrast\" with 8 occurrences!\nEnsures the contrast between foreground and background colors meets\nWCAG 2 AA contrast ratio thresholds. Correct invalid elements at:\n - #maincontent > .make_your_mark > div:nth-child(2) > p > span > span\n - #maincontent > .make_your_mark > div:nth-child(4) > p > span > span\n - #maincontent > .inform_your_decisions > div:nth-child(2) > p > span > span\n - #maincontent > .inform_your_decisions > div:nth-child(4) > p > span > span\n - #maincontent > .inform_your_decisions > div:nth-child(6) > p > span > span\n - #maincontent > .inform_your_decisions > div:nth-child(8) > p > span > span\n - #maincontent > .inform_your_decisions > div:nth-child(10) > p > span > span\n - #maincontent > .inform_your_decisions > div:nth-child(12) > p > span > span\nFor details, see: https://dequeuniversity.com/rules/axe/2.5/color-contrast\naXe also provides links to their site where they discuss the best way to fix the problem.\nIn 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:\n\u2022 Error: This element has insufficient contrast at this conformance level.\n Expected a contrast ratio of at least 4.5:1, but text in this element has a contrast ratio of 2.96:1.\n Recommendation: change text colour to #767676.\n \u23a3 WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail\n \u23a3 #maincontent > div:nth-child(10) > div:nth-child(8) > p > span > span\n \u23a3 Featured products: \nIntegrating into our build pipeline\nWe 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.\nOnce Jenkins has cloned the repository, it installs any dependencies and executes the tests via:\nnpm install && npm test\nBundling the URLs to be tested into our test script means we don\u2019t have a command line style test where we list each URL we wish to test in the Jenkins CLI. It\u2019s an effective method but can also be cluttered, and obscure which URLs are being tested.\nIn 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.\nFixing the issues\nAs 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.\nAnother 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.\nManual testing\nAdding 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.\nOne 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. \nIt\u2019s tempting to add alt text and aria-labels to make errors go away, but if they don\u2019t 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\u2019s important to remember that not all screen readers are the same and some may interact with our site differently to others. \nConsider 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\u2019t even thought about, so this is a good way to broaden your knowledge and awareness.\nTips and tricks\nOne of our main issues with Pa11y is that it may find issues we don\u2019t 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.\nconst test = pa11y({\n ....\n hideElements: '#ratings, #js-bigsearch',\n ...\n});\n\nconst ignoreErrors: string[] = [\n ' ',\n '',\n ' '\n ];\n const filterResult = result => {\n if (ignoreErrors.indexOf(result.context) > -1) {\n return false;\n }\n return true;\n };\nInitially 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. \nconst test = pa11y({\n ignore: [\n 'notice',\n 'warning'\n ],\n...\n});\nJenkins gotchas\nWhile 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\u2019t 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. \nWe 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)). \nfor (const url of urls) {\n try {\n console.log(url);\n let urlResult = await run(url);\n urlResult = urlResult.filter(filterResult);\n urlResult.forEach(result => console.log(result));\n }\n catch (e) {\n console.log('Error:', e);\n process.exit(1);\n }\n}\nWe 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:\nprocess.on('unhandledRejection', (reason, p) => {\n console.log('Unhandled Rejection at:', p, 'reason:', reason);\n process.exit(1);\n});\nprocess.on('uncaughtException', (err) => {\n console.log('Caught exception: ${err}n');\n process.exit(1);\n});\nNow it\u2019s your turn\nThat\u2019s it! That\u2019s 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.", "year": "2017", "author": "Seren Davies", "author_slug": "serendavies", "published": "2017-12-07T00:00:00+00:00", "url": "https://24ways.org/2017/automating-your-accessibility-tests/", "topic": "code"}
{"rowid": 196, "title": "Designing a Remote Project", "contents": "I came across an article recently, which I have to admit made my blood boil a little. Yes, I know it\u2019s the season of goodwill and all that, and I\u2019m going to risk sounding a little Scrooge-like, but I couldn\u2019t help it. It was written by someone who\u2019d tried out \u2018telecommuting\u2019 (big sigh) a.k.a. remote or distributed working. They\u2019d tested it in their company and decided it didn\u2019t work. \nWhy did it enrage me so much? Well, this person sounded like they\u2019d almost set it up to fail. To them, it was the latest buzzword, and they wanted to offer their employees a \u2018perk\u2019. But it was going to be risky, because, well, they just couldn\u2019t trust their employees not to be lazy and sit around in their pyjamas at home, watching TV, occasionally flicking their mousepad to \u2018appear online\u2019. Sounds about right, doesn\u2019t it?\nWell, no. This attitude towards remote working is baked in the past, where working from one office and people all sitting around together in a cosy circle singing kum-by-yah* was a necessity not an option. We all know the reasons remote working and flexibility can happen more easily now: fast internet, numerous communication channels, and so on. But why are companies like Yahoo! and IBM backtracking on this? Why is there still such a negative perception of this way of working when it has so much real potential for the future?\n*this might not have ever really happened in an office.\nSo what is remote working? It can come in various formats. It\u2019s actually not just the typical office worker, working from home on a specific day. The nature of digital projects has been changing over a number of years. In this era where organisations are squeezing budgets and trying to find the best value wherever they can, it seems that the days of whole projects being tackled by one team, in the same place, is fast becoming the past. What I\u2019ve noticed more recently is a much more fragmented way of putting together a project \u2013 a mixture of in-house and agency, or multiple agencies or organisations, or working with an offshore team. In the past we might have done the full integrated project from beginning to end, now, it\u2019s a piece of the pie. \nWhich means that everyone is having to work with people who aren\u2019t sat next to them even more than before. Whether that\u2019s a freelancer you\u2019re working with who\u2019s not in the office, an offshore agency doing development or a partner company in another city tackling UX\u2026 the future is looking more and more like a distributed workplace.\nSo why the negativity, man?\nAs I\u2019ve seen from this article, and from examples of large corporations changing their entire philosophy away from remote working, there\u2019s a lot of negativity towards this way of working. Of course if you decide to let everyone work from home when they want, set them off and then expect them all to check in at the right time or be available 24/7 it\u2019s going to be a bit of a mess. Equally if you just jump into work with a team on the other side of the world without any setup, should you expect anything less than a problematic project?\nOkay, okay so what about these people who are going to sit on Facebook all day if we let them work from home? It\u2019s the age old response to the idea of working from home. I can\u2019t see the person, so how do I know what they are doing?\nThis comes up regularly as one of the biggest fears of letting people work remotely. There\u2019s also the perceived lack of productivity and distractions at home. The limited collaboration and communication with distributed workers. The lack of availability. The lower response times. \nHang on a second, can\u2019t these all still be problems even if you\u2019ve got your whole team sat in the same place? \u201cThey won\u2019t focus on work.\u201d How many people will go on Facebook or Twitter whilst sat in an office? \u201cThey won\u2019t collaborate as much.\u201d How many people sit in the office with headphones on to block out distractions? I think we have to move away from the idea that being sat next to people automatically makes them work harder. If the work is satisfying, challenging, and relevant to a person \u2013 surely we should trust them to do it, wherever they are sat?\nThere\u2019s actually a lot of benefits to remote working, and having distributed teams. Offering this as a way of working can attract and retain employees, due to the improved flexibility. There can actually be fewer distractions and disruptions at home, which leads to increased productivity. To paraphrase Jason Fried in his talk \u2018Why work doesn\u2019t happen at work\u2019, at home there are voluntary distractions where you have to choose to distract yourself with something. At the office these distractions become involuntary. Impromptu meetings and people coming to talk to you all the time are actually a lot more disruptive. Often, people find it easier to focus away from the office environment. \nThere\u2019s also the big benefit for a lot of people of the time saved commuting. The employee can actually do a lot that\u2019s beneficial to them in this time, rather than standing squeezed into people\u2019s armpits on public transport. Hence increased job satisfaction. With a distributed team, say if you\u2019re working with an off-shore team, there could be a wider range of talent to pick from and it also encourages diversity. There can be a wider range of cultural differences and opinions brought to a project, which encourages more diverse ways of thinking.\nTackling the issues - or, how to set up a project with a remote team\nBut that isn\u2019t to say running projects with a distributed team or being a remote worker is easy, and can just happen, like that. It needs work \u2013 and good groundwork \u2013 to ensure you don\u2019t set it up to fail. So how do you help create a smoother remote project?\nStart with trust\nFirst of all, the basis of the team needs to be trust. Yes I\u2019m going to sound a little like a cheesy, self-help guru here (perhaps in an attempt to seem less Scrooge-like and inject some Christmas cheer) but you do need to trust the people working remotely as well as them trusting you. This extends to a distributed team. You can\u2019t just tell the offshore team what to do, and micromanage them, scared they won\u2019t do what you want, how you want it because you can\u2019t see them. You need to give them ownership and let them manage the tasks. Remember, people are less likely to criticise their own work. Make them own the work and they are more likely to be engaged and productive.\nSet a structure\nDistributed teams and remote workers can fail when there is no structure \u2013 just as much as teams sitting together fail without it too. It\u2019s not so much setting rules, as having a framework to work within. Eliminate blockers before they happen. Think about what could cause issues for the team, and think of ways to solve this. For example, what do you do if you won\u2019t be able to get hold of someone for a few hours because of a time difference? Put together a contingency, e.g. is there someone else on your time zone you could go to with queries after assessing the priority? Would it be put aside until that person is back in? Define team roles and responsibilities clearly. Sit down at the beginning of the project and clearly set out expectations. Also ask the team, what are their expectations of you?\nThere won\u2019t be a one size fits all framework either. Think about your team, the people in it, the type of project you\u2019re working with, the type of client and stakeholder. This should give you an idea of what sort of communications you\u2019ll need on the project. Daily calls, video calls, Slack channels, the choice is yours.\nDecide on the tools\nTo be honest, I could spend hours talking about the different tools you can use for communication. But you know them, right? And in the end it\u2019s not the tool that\u2019s important here - it\u2019s the communication that\u2019s being done on the tool. Tools need to match the type of communications needed for your team. One caveat here though, never rely solely on email! Emails are silos, and can become beasts to manage communications on.\nTransparency in communication\nGood communication is key. Make sure there are clear objectives for communication. Set up one time during the week where those people meet together, discuss all the work during that week that they\u2019ve done. If decisions are made between team members who are together, make sure everyone knows what these are. But try to make collective decisions where you can, when it doesn\u2019t impact on people\u2019s time.\nHave a face-to-face kick off\nYes, I know this might seem to counter my argument, but face-to-face comms are still really important. If it\u2019s feasible, have an in-person meeting to kick off your project, and to kick off your team working together. An initial meeting, to break the ice, discuss ways of working, set the goals, can go a long way to making working with distributed teams successful. If this is really not viable, then hold a video call with the team. Try to make this a little more informal. I know, I know, not the dreaded cringey icebreakers\u2026 but something to make everyone relax and get to know each other is really important. Bring everybody together physically on a regular basis if you can, for example with quarterly meetings. You\u2019ve got to really make sure people still feel part of a team, and it often takes a little more work with a remote team. Connect with new team members, one-on-one first, then you can have more of a \u2018remote\u2019 relationship. \nGet visual\nVisual communication is often a lot better tool to use than just a written sentence, and can help bring ideas to life. Encourage people to sketch things, take a photo and add this to your written communications. Or use a mockup tool to sketch ideas.\nBut what about Agile projects?\nThe whole premise of Agile projects is to have face-to-face contact I hear you cry. The Agile Manifesto itself states \u201cThe most efficient and effective method of conveying information to and within a development team is face-to-face conversation\u201d. However, this doesn\u2019t mean the death of remote working. In fact loads of successful companies still run Agile projects, whilst having a distributed team. With all the collaborative tools you can use for centralising code, tracking tasks, visualising products, it\u2019s not difficult to still communicate in a way that works. Just think about how to replicate the principles of Agile remotely - working together daily, a supportive environment, trust, and simplicity. How can you translate these to your remote or distributed team? \nOne last thought to leave you with before you run off to eat your mince pies (in your pyjamas, whilst working). A common mistake in working with a remote project team or working remotely yourself, is replacing distance with time. If you\u2019re away from the office you think you need to always be \u2018on\u2019 \u2013 messaging, being online, replying to requests. If you have a distributed team, you might think a lot of meetings, calls, and messages will be good to foster communication. But don\u2019t overload these meetings, calls, and communication. This can be disruptive in itself. Give people the gift of some uninterrupted time to actually do some work, and not feel like they have to check in every second.", "year": "2017", "author": "Suzanna Haworth", "author_slug": "suzannahaworth", "published": "2017-12-06T00:00:00+00:00", "url": "https://24ways.org/2017/designing-a-remote-project/", "topic": "business"}
{"rowid": 195, "title": "Levelling Up for Junior Developers", "contents": "If you are a junior developer starting out in the web industry, things can often seem a little daunting. There are so many things to learn, and as soon as you\u2019ve learnt one framework or tool, there seems to be something new out there.\nI am lucky enough to lead a team of developers building applications for the web. During a recent One to One meeting with one of our junior developers, he asked me about a learning path and the basic fundamentals that every developer should know. After a bit of digging around, I managed to come up with a (not so exhaustive) list of principles that was shared with him.\n\nIn this article, I will share the list with you, and hopefully help you level up from junior developer and become a better developer all round. This list doesn\u2019t focus on an particular programming language, but rather coding concepts as a whole. The idea behind this list is that whether you are a front-end developer, back-end developer, full stack developer or just a curious one, these principles apply to everyone that writes code. \nI have tried to be technology agnostic, so that you can use these tips to guide you, whatever your tech stack might be.\nWithout any further ado and in no particular order, let\u2019s get started.\nRefactoring code like a boss\nThe Boy Scouts have a rule that goes \u201calways leave the campground cleaner than you found it.\u201d This rule can be applied to code too and ensures that you leave code cleaner than you found it. As a junior developer, it\u2019s almost certain that you will either create or come across older code that could be improved. The resources below are a guide that will help point you in the right direction.\n\nMy favourite book on this subject has to be Clean Code by Robert C. Martin. It\u2019s a must read for anyone writing code as it helps you identify bad code and shows you techniques that you can use to improve existing code.\nIf you find that in your day to day work you deal with a lot of legacy code, Improving Existing Technology through Refactoring is another useful read.\nDesign Patterns are a general repeatable solution to a commonly occurring problem in software design. My friend and colleague Ranj Abass likes to refer to them as a \u201ccommon language\u201d that helps developers discuss the way that we write code as a pattern. My favourite book on this subject is Head First Design Patterns which goes right back to the basics. Another great read on this topic is Refactoring to Patterns.\nWorking Effectively With Legacy Code is another one that I found really valuable.\n\nImproving your debugging skills\nA solid understanding of how to debug code is a must for any developer. Whether you write code for the web or purely back-end code, the ability to debug will save you time and help you really understand what is going on under the hood.\n\nIf you write front-end code for the web, one of my favourite resources to help you understand how to debug code in Chrome can be found on the Chrome Dev Tools website. While some of the tips are specific to Chrome, these techniques apply to any modern browser of your choice.\nAt Settled, we use Node.js for much of our server side code. Without a doubt, our most trusted IDE has to be Visual Studio Code and the built-in debuggers are amazing. Regardless of whether you use Node.js or not, there are a number of plugins and debuggers that you can use in the IDE. I recommend reading the website of your favourite IDE for more information. \nAs a side note, it is worth mentioning that Chrome Developer Tools actually has functionality that allows you to debug Node.js code too. This makes it a seamless transition from front-end code to server-side code debugging.\nThe Debugging Mindset is an informative online article by Devon H. O\u2019Dell and discusses the the psychology of learning strategies that lead to effective problem-solving skills. \n\nA good understanding of relational databases and NoSQL databases\nAlmost all developers will need to persist data at some point in their career. Even if you don\u2019t write SQL queries in your day to day job, a solid understanding of how they work will help you become a better developer.\n\nIf you are a complete newbie when it comes to databases, I recommend checking out Code Academy. They offer a free online course that can help you get your head around how relational databases work. The course is quite basic, but is a useful hands-on approach to learning this topic.\nThis article provides a great explainer for the difference between the SQL and NoSQL databases, and this Stackoverflow answer goes a little deeper into the subject of the two database types.\nIf you\u2019d like to learn more about NoSQL queries, I would recommend starting with this article on MongoDB queries. Unfortunately, there isn\u2019t one overall course as most NoSQL databases have their own syntax. \n\nYou may also have noticed that I haven\u2019t included other types of databases such as Graph or In-memory; it\u2019s worth focussing on the basics before going any deeper.\nPerformance on the web\nIf you build for the web today, it is important to understand how the browser receives and renders the content that you send it. I am pretty passionate about Web Performance, and hope that everyone can learn how to make websites faster and more efficient. It can be fun at the same time!\n\nSteve Souders High Performance Websites is the godfather of web performance books. While it was created a few years ago and many of the techniques might have changed slightly, it is the original book on the subject and set up many of the ground rules that we know about web performance today.\nA free online resource on this topic is the Google Developers website. The site is an up to date guide on the best web performance techniques for your site. It is definitely worth a read.\nThe network plays a key role in delivering data to your users, and it plays a big role in performance on the web. A fantastic book on this topic is Ilya Grigorik\u2019s High Performance Browser Networking. It is also available to read online at hpbn.co.\n\nUnderstand the end to end architecture of your software project\nI find that one of the best ways to improve my knowledge is to learn about the architecture of the software at the company I work at. It gives you a good understanding as to why things are designed the way they are, why certain decisions were made, and gives you an understanding of how you might do things differently with hindsight.\nTry and find someone more senior, such as a Technical Lead or Software Architect, at your company and ask them to explain the overall architecture and draw a few high-level diagrams for you. Not to mention that they will be impressed with your willingness to learn.\n\nI recommend reading Clean Architecture: A Craftsman\u2019s Guide to Software Structure and Design for more detail on this subject.\nFar too often, software projects can be over-engineered and over-architected, it is worth reading Just Enough Software Architecture. The book helps developers understand how the smallest of changes can affect the outcome of your software architecture.\n\nHow are things deployed\nA big part of creating software is actually shipping it! How is the software at your company released into the wild? Does your company do Continuous Integration? Continuous Deployment?\n\nEven if you answered no to any of these questions, it is worth finding someone with the knowledge in your company to explain these things to you. If it is not already documented, perhaps you could start a wiki to document everything you\u2019re learning about the system - this is a great way to level up and be appreciated and invaluable.\nA streamlined deployment process is a beautiful thing, and understanding how they work can help you grow your knowledge as a developer. \nContinuous Integration is a practical read on the ins and outs of implementing this deployment technique.\nDocker is another great tool to use when it comes to software deployment. It can be tricky at first to wrap your head around, but it is definitely worth learning about this great technology. The documentation on the website will teach and guide you on how to get started using Docker.\n\nWriting Tests\nTesting is an essential tool in the developer bag of skills. They help you to make big refactoring changes to your code, and feel a lot more confident knowing that your changes haven\u2019t broken anything. There are so many benefits to testing, which make it so important for developers at every level to become acquainted with it/them.\n\nThe book that started it all for me was Roy Osherove\u2019s The Art of Unit Testing. The code in the book is written in C#, but the principles apply to every language. It\u2019s a great, easy-to-understand read.\nAnother great read is How Google Tests Software and covers exactly what it says on the tin. It covers many different testing techniques such as exploratory, black box, white box, and acceptance testing and really helps you understand how large organisations test their code.\n\nSoft skills\nWhilst reading through this article, you\u2019ve probably noticed that a large chunk of it focusses on code and technical ability. Without a doubt, I\u2019d say that it is even more important to be a good teammate. If you look up the definition of soft skills in the dictionary, it is defined as \u201cpersonal attributes that enable someone to interact effectively and harmoniously with other people\u201d and I think that it sums this up perfectly. Working on your \u201csoft skills\u201d is something that can truly help you level up in your career. You may be the world\u2019s greatest coder, but if you colleagues can\u2019t get along with you, your coding skills won\u2019t matter!\nWhile you may not learn how to become the perfect co-worker overnight, I really try and live by the motto \u201cdon\u2019t be an arsehole\u201d. Think about how you like to be treated and then try and treat your co-workers with the same courtesy and respect. The next time you need to make a decision at work, ask yourself \u201cis this something an arsehole would do\u201d? If you answered yes to that question, you probably shouldn\u2019t do it!\nSummary\nLevelling up as a junior developer doesn\u2019t have to be scary. Focus on the fundamentals and they should hold you in good stead, regardless of the new things that come along. Software engineering is built on these great principles that have stood the test of time.\nWhilst researching for this article, I came across a useful Github repo that is worth mentioning. Things Every Programmer Should Know is packed with useful information. I have to admit, I didn\u2019t know everything on there!\nI hope that you have found this list helpful. Some of the topics I have mentioned might not be relevant for you at this stage in your career, but should give a nudge in the right direction. After all, knowledge is power!\nIf you are a junior developer reading this article, what would you add to it?", "year": "2017", "author": "Dean Hume", "author_slug": "deanhume", "published": "2017-12-05T00:00:00+00:00", "url": "https://24ways.org/2017/levelling-up-for-junior-developers/", "topic": "code"}
{"rowid": 203, "title": "Jobs-to-Be-Done in Your UX Toolbox", "contents": "Part 1: What is JTBD?\nThe concept of a \u201cjob\u201d in \u201cJobs-To-Be-Done\u201d is neatly encapsulated by a oft-quoted line from Theodore Levitt:\n\n\u201cPeople want a quarter-inch hole, not a quarter inch drill\u201d.\n\nEven so, Don Norman pointed out that perhaps Levitt \u201cstopped too soon\u201d at what the real customer goal might be. In the \u201cThe Design of Everyday Things\u201d, he wrote:\n\n\u201cLevitt\u2019s 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\u2019t really want the drill, you realize that perhaps they don\u2019t really want the hole, either: they want to install their bookshelves. Why not develop methods that don\u2019t require holes? Or perhaps books that don\u2019t require bookshelves.\u201d\n\nIn other words, a \u201cjob\u201d in JTBD lingo is a way to express a user need or provide a customer-centric problem frame that\u2019s independent of a solution. As Tony Ulwick says:\n\n\u201cA job is stable, it doesn\u2019t change over time.\u201d\n\nAn example of a job is \u201ctiding you over from breakfast to lunch.\u201d You could hire a donut, a flapjack or a banana for that mid-morning snack\u2014whatever 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.\nThe 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: \n\n\u201cEconomy 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\u2019re looking for significantly different salaries. Video conferencing isn\u2019t as capable, but is willing to work for a far smaller salary. I\u2019ve a hiring choice to make.\u201d\n\nSo far so good: it\u2019s relatively simple to understand what a job is, once you understand how it\u2019s different from a \u201ctask\u201d. Business consultant and Harvard professor Clay Christensen talks about the concept of \u201chiring\u201d a product to do a \u201cjob\u201d, and firing it when something better comes along. If you\u2019re a company that focuses solutions on the customer job, you\u2019re more likely to succeed. You\u2019ll find these concepts often referred to as \u201cJobs-to-be-Done theory\u201d. But the application of Jobs-to-Be-Done theory is a little more complicated; it comprises several related approaches.\nI particularly like Jim Kalbach\u2019s description of how JTBD is a \u201clens through which to understand value creation\u201d. But it is also more. In my view, it\u2019s a family of frameworks and methods\u2014and perhaps even a philosophy.\nDifferent facets in a family of frameworks\nJTBD 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\u2014we have our roots in human-computer interaction and ergonomics. I\u2019ve found it helpful to keep in mind is that the application of JTBD theory is an evolving beast, so it\u2019s 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.\nOutcome Driven Innovation\nTony Ulwick\u2019s 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 \u201cJobs to Be Done: Theory to Practice\u201d, I actually found it beneficial to read his approach in the original 2002 article for a clearer reference point.\nIn the earlier article, Ulwick presented a rigorous approach that combines interviews, surveys and an \u201copportunity\u201d algorithm\u2014a sequence of steps to determine the business opportunity. ODI centres around working with \u201cdesired outcome statements\u201d 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. \nSince 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 \u201cto 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.\u201d\nA 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\u2014and as our research team at Clearleft have found, how we use model can depend on the nature of the jobs we\u2019ve uncovered in interviews and the characteristics of the problem we\u2019re attempting to solve.\nFigure 1. Universal job map\nUlwick\u2019s 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.\nThe Jobs-To-Be-Done Interview\nBack 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\u2019d done before and for the first time in years, I felt that I was genuinely adding something new to my research toolbox.\nA 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.\nThis framework centres around the JTBD interview method, which harnesses the power of a narrative framework to elicit the real reasons why someone \u201chired\u201d something to do a job\u2014be 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.\nFigure 2. JTBD Timeline\nFigure 3. The Four Forces\nThe 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.\nThe 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\u2019s a powerful way to facilitate recall. Having done many such interviews, I\u2019ve 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.\nStrengths aside, it\u2019s 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\u2019s self-reported perspective. For example, a stronger research methodology combines JTBD interviews with contextual research and quantitative methods. \nJob Stories\nAlan Klement is credited for coming up with the term \u201cjob story\u201d to describe the framing of jobs for product design by the team at Intercom:\n\n\u201cWhen \u2026 I want to \u2026 so I can \u2026.\u201d\n\nFigure 4. Anatomy of a Job Story\nUnlike 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:\n\n\u201cWe frame every design problem in a Job, focusing on the triggering event or situation, the motivation and goal, and the intended outcome. [\u2026] 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.\u201d\n\nSystems of Progress\nApart from advocating using job stories, Klement believes that a core tenet of applying JTBD revolves around our desire for \u201cself-betterment\u201d\u2014and that focusing on everyone\u2019s desire for self-betterment is core to a successful strategy.\nIn 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.\nCoincidentally, I applied similar thinking on mapping systemic change when we were looking to improve users\u2019 trust with a local government forum earlier this year. It\u2019s not just about capturing and satisfying the immediate job-to-be-done, it\u2019s 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.\nThis is really the point where JTBD becomes a philosophy of practice.\nPart 2: Mixing It Up\nThere has been some misunderstanding about how adopting JTBD means ditching personas or some of our existing design tools or research techniques. This couldn\u2019t have been more wrong.\nFigure 5: Jim Kalbach\u2019s JTBD model\nJim 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\u2019s theories and the structure of the job story.\nMore interestingly, Kalbach has also combined the use of mental models with JTBD.\nClaire 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\u2019 perspective. Claire highlights an especially interesting point in her article as she described her challenges:\n\u201cAfter much trial and error, I arrived at a foundational research framework to suit every team\u2019s needs \u2014 allowing everyone to share the same holistic understanding, but extract the type of information most applicable to their work.\u201d\nIn other words, the organisational context you are in likely can dictate what works best\u2014after 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.\nJTBD is an immensely powerful approach on many fronts\u2014you\u2019ll 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.\nJTBD in the UX ecosystem\nFigure 6. The Elements of User Experience (source)\nThere are many ways we have tried to explain the UX discipline but I think Jesse James Garrett\u2019s Elements of User Experience is a good place to begin.\nI 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.\nFigure 7. Which level of product focus?\nWe could, of course, also think about where it fits best within the double diamond.\nAgain, 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 \u2014all 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.\nThe clue lies in JTBD\u2019s raison d\u2019\u00eatre: a job statement is solution independent. Hence, once we get to designing solutions, we potentially fall into a existential black hole.\nThat 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\u2019ll notice that the available language of \u201cjobs\u201d drops off at around that point.\nJob statements and outcome statements provide excellent \u201cmini north-stars\u201d as customer-oriented focal points, but purely satisfying these statements would not necessarily guarantee that you have created a seamless and painless user experience.\nPlaying well with others\nYou 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.\nWhen 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\u2019t 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. \nThe application of Jobs-to-be-Done is still evolving. I\u2019ve found it to be very powerful and I struggle to remember what my UX professional life was like before I encountered it\u2014it has completely changed my approach to research and design.\nThe fact JTBD is still evolving as a practice means we need to be watchful of dogma\u2014there\u2019s no right way to get a UX job done after all, it nearly always depends. At the end of the day, isn\u2019t it about having the right tool for the right job?", "year": "2017", "author": "Steph Troeth", "author_slug": "stephtroeth", "published": "2017-12-04T00:00:00+00:00", "url": "https://24ways.org/2017/jobs-to-be-done-in-your-ux-toolbox/", "topic": "ux"}
{"rowid": 193, "title": "Web Content Accessibility Guidelines\u2014for People Who Haven't Read Them", "contents": "I\u2019ve been a huge fan of the Web Content Accessibility Guidelines 2.0 since the World Wide Web Consortium (W3C) published them, nine years ago. I\u2019ve found them practical and future-proof, and I\u2019ve found that they can save a huge amount of time for designers and developers. You can apply them to anything that you can open in a browser. My favourite part is when I use the guidelines to make a website accessible, and then attend user-testing and see someone with a disability easily using that website.\nToday, the United Nations International Day of Persons with Disabilities, seems like a good time to re-read Laura Kalbag\u2019s explanation of why we should bother with accessibility. That should motivate you to devour this article.\nIf you haven\u2019t read the Web Content Accessibility Guidelines 2.0, you might find them a bit off-putting at first. The editors needed to create a single standard that countries around the world could refer to in legislation, and so some of the language in the guidelines reads like legalese. The editors also needed to future-proof the guidelines, and so some terminology\u2014such as \u201ctime-based media\u201d and \u201cprogrammatically determined\u201d\u2014can sound ambiguous. The guidelines can seem lengthy, too: printing the guidelines, the Understanding WCAG 2.0 document, and the Techniques for WCAG 2.0 document would take 1,200 printed pages.\nThis festive season, let\u2019s rip off that legalese and ambiguous terminology like wrapping paper, and see\u2014in a single article\u2014what gifts the Web Content Accessibility Guidelines 2.0 editors have bestowed upon us.\nCan your users perceive the information on your website?\nThe first guideline has criteria that help you prevent your users from asking \u201cWhat the **** is this thing here supposed to be?\u201d\n1.1.1 Text is the most accessible format for information. Screen readers\u2014such as the \u201cVoiceOver\u201d setting on your iPhone or the \u201cTalkBack\u201d app on your Android phone\u2014understand text better than any other format. The same applies for other assistive technology, such as translation apps and Braille displays. So, if you have anything on your webpage that\u2019s not text, you must add some text that gives your user the same information. You probably know how to do this already; for example:\n\nfor images in webpages, put some alternative text in an alt attribute to tell your user what the image conveys to the user;\nfor photos in tweets, add a description to make the images accessible;\nfor Instagram posts, write a caption that conveys the photo\u2019s information.\n\nThe alternative text should allow the user to get the same information as someone who can see the image. For websites that have too many images for someone to add alternative text to, consider how machine learning and Dynamically Generated Alt Text might\u2014might\u2014be appropriate.\nYou can probably think of a few exceptions where providing text to describe an image might not make sense. Remember I described these guidelines as \u201cpractical\u201d? They cover all those exceptions:\n\nUser interface controls such as buttons and text inputs must have names or labels to tell your user what they do.\nIf your webpage has video or audio (more about these later on!), you must\u2014at least\u2014have text to tell the user what they are.\nMaybe your webpage has a test where your user has to answer a question about an image or some audio, and alternative text would give away the answer. In that case, just describe the test in text so your users know what it is.\nIf your webpage features a work of art, tell your user the experience it evokes.\nIf you have to include a Captcha on your webpage\u2014and please avoid Captchas if at all possible, because some users cannot get past them\u2014you must include text to tell your user what it is, and make sure that it doesn\u2019t rely on only one sense, such as vision.\nIf you\u2019ve included something just as decoration, you must make sure that your user\u2019s assistive technology can ignore it. Again, you probably know how to do this. For example, you could use CSS instead of HTML to include decorative images, or you could add an empty alt attribute to the img element. (Please avoid that recent trend where developers add empty alt attributes to all images in a webpage just to make the HTML validate. You\u2019re better than that.)\n\n(Notice that the guidelines allow you to choose how to conform to them, with whatever technology you choose. To make your website conform to a guideline, you can either choose one of the techniques for WCAG 2.0 for that guideline or come up with your own. Choosing a tried-and-tested technique usually saves time!)\n1.2.1 If your website includes a podcast episode, speech, lecture, or any other recorded audio without video, you must include a transcription or some other text to give your user the same information. In a lot of cases, you might find this easier than you expect: professional transcription services can prove relatively inexpensive and fast, and sometimes a speaker or lecturer can provide the speech or lecture notes that they read out word-for-word. Just make sure that all your users can get the same information and the same results, whether they can hear the audio or not. For example, David Smith and Marco Arment always publish episode transcripts for their Under the Radar podcast. \nSimilarly, if your website includes recorded video without audio\u2014such as an animation or a promotional video\u2014you must either use text to detail what happens in the video or include an audio version. Again, this might work out easier then you perhaps fear: for example, you could check to see whether the animation started life as a list of instructions, or whether the promotional video conveys the same information as the \u201cAbout Us\u201d webpage. You want to make sure that all your users can get the same information and the same results, whether they can see that video or not.\n1.2.2 If your website includes recorded videos with audio, you must add captions to those videos for users who can\u2019t hear the audio. Professional transcription services can provide you with time-stamped text in caption formats that YouTube supports, such as .srt and .sbv. You can upload those to YouTube, so captions appear on your videos there. YouTube can auto-generate captions, but the quality varies from impressively accurate to comically inaccurate. If you have a text version of what the people in the video said\u2014such as the speech that a politician read or the bedtime story that an actor read\u2014you can create a transcript file in .txt format, without timestamps. YouTube then creates captions for your video by synchronising that text to the audio in the video. If you host your own videos, you can ask a professional transcription service to give you .vtt files that you can add to a video element\u2019s track element\u2014or you can handcraft your own. (A quick aside: if your website has more videos than you can caption in a reasonable amount of time, prioritise the most popular videos, the most important videos, and the videos most relevant to people with disabilities. Then make sure your users know how to ask you to caption other videos as they encounter them.)\n1.2.3 If your website has recorded videos that have audio, you must add an \u201caudio description\u201d narration to the video to describe important visual details, or add text to the webpage to detail what happens in the video for users who cannot see the videos. (I like to add audio files from videos to my Huffduffer account so that I can listen to them while commuting.) Maybe your home page has a video where someone says, \u201cI\u2019d like to explain our new TPS reports\u201d while \u201cBill Lumbergh, division Vice President of Initech\u201d appears on the bottom of the screen. In that case, you should add an audio description to the video that announces \u201cBill Lumbergh, division Vice President of Initech\u201d, just before Bill starts speaking. As always, you can make life easier for yourself by considering all of your users, before the event: in this example, you could ask the speaker to begin by saying, \u201cI\u2019m Bill Lumbergh, division Vice President of Initech, and I\u2019d like to explain our new TPS reports\u201d\u2014so you won\u2019t need to spend time adding an audio description afterwards. \n1.2.4 If your website has live videos that have some audio, you should get a stenographer to provide real-time captions that you can include with the video. I\u2019ll be honest: this can prove tricky nowadays. The Web Content Accessibility Guidelines 2.0 predate YouTube Live, Instagram live Stories, Periscope, and other such services. If your organisation creates a lot of live videos, you might not have enough resources to provide real-time captions for each one. In that case, if you know the contents of the audio beforehand, publish the contents during the live video\u2014or failing that, publish a transcription as soon as possible.\n1.2.5 Remember what I said about the recorded videos that have audio? If you can choose to either add an audio description or add text to the webpage to detail what happens in the video, you should go with the audio description.\n1.2.6 If your website has recorded videos that include audio information, you could provide a sign language version of the audio information; some people understand sign language better than written language. (You don\u2019t need to caption a video of a sign language version of audio information.)\n1.2.7 If your website has recorded videos that have audio, and you need to add an audio description, but the audio doesn\u2019t have enough pauses for you to add an \u201caudio description\u201d narration, you could provide a separate version of that video where you have added pauses to fit the audio description into.\n1.2.8 Let\u2019s go back to the recorded videos that have audio once more! You could add text to the webpage to detail what happens in the video, so that people who can neither read captions nor hear dialogue and audio description can use braille displays to understand your video.\n1.2.9 If your website has live audio, you could get a stenographer to provide real-time captions. Again, if you know the contents of the audio beforehand, publish the contents during the live audio or publish a transcription as soon as possible.\n(Congratulations on making it this far! I know that seems like a lot to remember, but keep in mind that we\u2019ve covered a complex area: helping your users to understand multimedia information that they can\u2019t see and/or hear. Grab a mince pie to celebrate, and let\u2019s keep going.)\n1.3.1 You must mark up your website\u2019s content so that your user\u2019s browser, and any assistive technology they use, can understand the hierarchy of the information and how each piece of information relates to the rest. Once again, you probably know how to do this: use the most appropriate HTML element for each piece of information. Mark up headings, lists, buttons, radio buttons, checkboxes, and links with the most appropriate HTML element. If you\u2019re looking for something to do to keep you busy this Christmas, scroll through the list of the elements of HTML. Do you notice any elements that you didn\u2019t know, or that you\u2019ve never used? Do you notice any elements that you could use on your current projects, to mark up the content more accurately? Also, revise HTML table advanced features and accessibility, how to structure an HTML form, and how to use the native form widgets\u2014you might be surprised at how much you can do with just HTML! Once you\u2019ve mastered those, you can make your website much more usable for your all of your users.\n1.3.2 If your webpage includes information that your user has to read in a certain order, you must make sure that their browser and assistive technology can present the information in that order. Don\u2019t rely on CSS or whitespace to create that order visually. Check that the order of the information makes sense when CSS and whitespace aren\u2019t formatting it. Also, try using the Tab key to move the focus through the links and form widgets on your webpage. Does the focus go where you expect it to? Keep this in mind when using order in CSS Grid or Flexbox.\n1.3.3 You must not presume that your users can identify sensory characteristics of things on your webpage. Some users can\u2019t tell what you\u2019ve positioned where on the screen. For example, instead of asking your users to \u201cChoose one of the options on the left\u201d, you could ask them to \u201cChoose one of our new products\u201d and link to that section of the webpage.\n1.4.1 You must not rely on colour as the only way to convey something to your users. Some of your users can\u2019t see, and some of your users can\u2019t distinguish between colours. For example, if your webpage uses green to highlight the products that your shop has in stock, you could add some text to identify those products, or you could group them under a sub-heading.\n1.4.2 If your webpage automatically plays a sound for more than 3 seconds, you must make sure your users can stop the sound or change its volume. Don\u2019t rely on your user turning down the volume on their computer; some users need to hear the screen reader on their computer, and some users just want to keep listening to whatever they were listening before your webpage interrupted them!\n1.4.3 You should make sure that your text contrasts enough with its background, so that your users can read it. Bookmark Lea Verou\u2019s Contrast Ratio calculator now. You can enter the text colour and background colour as named colours, or as RGB, RGBa, HSL, or HSLa values. You should make sure that:\n\nnormal text that set at 24px or larger has a ratio of at least 3:1;\nbold text that set at 18.75px or larger has a ratio of at least 3:1;\nall other text has a ratio of at least 4\u00bd:1.\n\nYou don\u2019t have to do this for disabled form controls, decorative stuff, or logos\u2014but you could!\n1.4.4 You should make sure your users can resize the text on your website up to 200% without using their assistive technology\u2014and still access all your content and functionality. You don\u2019t have to do this for subtitles or images of text.\n1.4.5 You should avoid using images of text and just use text instead. In 1998, Jeffrey Veen\u2019s first Hot Design Tip said, \u201cText is text. Graphics are graphics. Don\u2019t confuse them.\u201d Now that you can apply powerful CSS text-styling properties, use CSS Grid to precisely position text, and choose from thousands of web fonts (Jeffrey co-founded Typekit to help with this), you pretty much never need to use images of text. The guidelines say you can use images of text if you let your users specify the font, size, colour, and background of the text in the image of text\u2014but I\u2019ve never seen that on a real website. Also, this doesn\u2019t apply to logos.\n1.4.6 Let\u2019s go back to colour contrast for a second. You could make your text contrast even more with its background, so that even more of your users can read it. To do that, use Lea Verou\u2019s Contrast Ratio calculator to make sure that:\n\nnormal text that is 24px or larger has a ratio of at least 4\u00bd:1;\nbold text that 18.75px or larger has a ratio of at least 4\u00bd:1;\nall other text has a ratio of at least 7:1.\n\n1.4.7 If your website has recorded speech, you could make sure there are no background sounds, or that your users can turn off any background sounds. If that\u2019s not possible, you could make sure that any background sounds that last longer than a couple of seconds are at least four times quieter than the speech. This doesn\u2019t apply to audio Captchas, audio logos, singing, or rapping. (Yes, these guidelines mention rapping!)\n1.4.8 You could make sure that your users can reformat blocks of text on your website so they can read them better. To do this, make sure that your users can:\n\nspecify the colours of the text and the background, and\nmake the blocks of text less than 80-characters wide, and \nalign text to the left (or right for right-to-left languages), and \nset the line height to 150%, and \nset the vertical distance between paragraphs to 1\u00bd times the line height of the text, and \nresize the text (without using their assistive technology) up to 200% and still not have to scroll horizontally to read it.\n\nBy the way, when you specify a colour for text, always specify a colour for its background too. Don\u2019t rely on default background colours!\n1.4.9 Let\u2019s return to images of text for a second. You could make sure that you use them only for decoration and logos.\nCan users operate the controls and links on your website?\nThe second guideline has criteria that help you prevent your users from asking, \u201cHow the **** does this thing work?\u201d\n2.1.1 You must make sure that you users can carry out all of your website\u2019s activities with just their keyboard, without time limits for pressing keys. (This doesn\u2019t apply to drawing or anything else that requires a pointing device such as a mouse.) Again, if you use the most appropriate HTML element for each piece of information and for each form element, this should prove easy.\n2.1.2 You must make sure that when the user uses the keyboard to focus on some part of your website, they can then move the focus to some other part of your webpage without needing to use a mouse or touch the screen. If your website needs them to do something complex before they can move the focus elsewhere, explain that to your user. These \u201ckeyboard traps\u201d have become rare, but beware of forms that move focus from one text box to another as soon as they receive the correct number of characters.\n2.1.3 Let\u2019s revisit making sure that you users can carry out all of your website\u2019s activities with just their keyboard, without time limits for pressing keys. You could make sure that your user can do absolutely everything on your website with just the keyboard.\n2.2.1 Sometimes people need more time than you might expect to complete a task on your website. If any part of your website imposes a time limit on a task, you must do at least one of these: \n\nlet your users turn off the time limit before they encounter it; or\nlet your users increase the time limit to at least 10 times the default time limit before they encounter it; or\nwarn your users before the time limit expires and give them at least 20 seconds to extend it, and let them extend it at least 10 times.\n\nRemember: these guidelines are practical. They allow you to enforce time limits for real-time events such as auctions and ticket sales, where increasing or extending time limits wouldn\u2019t make sense. Also, the guidelines allow you to enforce a maximum time limit of 20 hours. The editors chose 20 hours because people need to go to sleep at some stage. See? Practical!\n2.2.2 In my experience, this criterion remains the least well-known\u2014even though some users can only use websites that conform to it. If your website presents content alongside other content that can distract users by automatically moving, blinking, scrolling, or updating, you must make sure that your users can:\n\npause, stop, or hide the other content if it\u2019s not essential and lasts more than 5 seconds; and\npause, stop, hide, or control the frequency of the other content if it automatically updates.\n\nIt\u2019s OK if your users miss live information such as stock price updates or football scores; you can\u2019t do anything about that! Also, this doesn\u2019t apply to animations such as progress bars that you put on a website to let all users know that the webpage isn\u2019t frozen.\n(If this one sounds complex, just add a pause button to anything that might distract your users.)\n2.2.3 Let\u2019s go back to time limits on tasks on your website. You could make your website even easier to use by removing all time limits except those on real-time events such as auctions and ticket sales. That would mean your user wouldn\u2019t need to interact with a timer at all.\n2.2.4 You could let your users turn off all interruptions\u2014server updates, promotions, and so on\u2014apart from any emergency information.\n2.2.5 This is possibly my favourite of these criteria! After your website logs your user out, you could make sure that when they log in again, they can continue from where they were without having lost any information. Do that, and you\u2019ll be on everyone\u2019s Nice List this Christmas.\n2.3.1 You must make sure that nothing flashes more than three times a second on your website, unless you can make sure that the flashes remain below the acceptable general flash and red flash thresholds\u2026\n2.3.2 \u2026or you could just make sure that nothing flashes more than three times per second on your website. This is usually an easier goal.\n2.4.1 You must make sure that your users can jump past any blocks of content, such as navigation menus, that are repeated throughout your website. You know the drill here: using HTML\u2019s sectioning elements such as header, nav, main, aside, and footer allows users with assistive technology to go straight to the content they need, and adding \u201cSkip Navigation\u201d links allows everyone to get to your main content faster.\n2.4.2 You must add a proper title to describe each webpage\u2019s topic. Your webpage won\u2019t even validate without a title element, so make it a useful one.\n2.4.3 If your users can focus on links and native form widgets, you must make sure that they can focus on elements in an order that makes sense.\n2.4.4 You must make sure that your users can understand the purpose of a link when they read:\n\nthe text of the link; or\nthe text of the paragraph, list item, table cell, or table header for the cell that contains the link; or\nthe heading above the link.\n\nYou don\u2019t have to do that for games and quizzes.\n2.4.5 You should give your users multiple ways to find any webpage within a set of webpages. Add site-wide search and a site map and you\u2019re done!\nThis doesn\u2019t apply for a webpage that is part of a series of actions (like a shopping cart and checkout flow) or to a webpage that is a result of a series of actions (like a webpage confirming that the user has bought what was in the shopping cart).\n2.4.6 You should help your users to understand your content by providing:\n\nheadings that describe the topics of you content;\nlabels that describe the purpose of the native form widgets on the webpage.\n\n2.4.7 You should make sure that users can see which element they have focussed on. Next time you use your website, try hitting the Tab key repeatedly. Does it visually highlight each item as it moves focus to it? If it doesn\u2019t, search your CSS to see whether you\u2019ve applied outline: 0; to all elements\u2014that\u2019s usually the culprit. Use the :focus pseudo-element to define how elements should appear when they have focus.\n2.4.8 You could help your user to understand where the current webpage is located within your website. Add \u201cbreadcrumb navigation\u201d and/or a site map and you\u2019re done.\n2.4.9 You could make links even easier to understand, by making sure that your users can understand the purpose of a link when they read the text of the link. Again, you don\u2019t have to do that for games and quizzes.\n2.4.10 You could use headings to organise your content by topic. \nCan users understand your content?\nThe third guideline has criteria that help you prevent your users from asking, \u201cWhat the **** does this mean?\u201d\n3.1.1 Let\u2019s start this section with the criterion that possibly takes the least time to implement; you must make sure that the user\u2019s browser can identify the main language that your webpage\u2019s content is written in. For a webpage that has mainly English content, use . \n3.1.2 You must specify when content in another language appears in your webpage, like so: I wish you a Joyeux No\u00ebl . . You don\u2019t have to do this for proper names, technical terms, or words that you can\u2019t identify a language for. You also don\u2019t have to do it for words from a different language that people consider part of the language around those words; for example, Come to our Christmas rendezvous! is OK.\n3.1.3 You could make sure that your users can find out the meaning of any unusual words or phrases, including idioms like \u201cstocking filler\u201d or \u201cBah! Humbug!\u201d and jargon such as \u201cVoiceOver\u201d and \u201cTalkBack\u201d. Provide a glossary or link to a dictionary.\n3.1.4 You could make sure that your users can find out the meaning of any abbreviation. For example, VoiceOver pronounces \u201cXmas\u201d as \u201cSmas\u201d instead of \u201cChristmas\u201d. Using the abbr element and linking to a glossary can help. (Interestingly, VoiceOver pronounces \u201cabbr\u201d as \u201cabbreviation\u201d!)\n3.1.5 Do your users need to be able to read better than a typically educated nine-year-old, to read your content (apart from proper names and titles)? If so, you could provide a version that doesn\u2019t require that level of reading ability, or you could provide images, videos, or audio to explain your content. (You don\u2019t have to add captions or audio description to those videos.)\n3.1.6 You could make sure that your users can access the pronunciation of any word in your content if that word\u2019s meaning depends on its pronunciation. For example, the word \u201cclose\u201d could have one of two meanings, depending on pronunciation, in a phrase such as, \u201cReady for Christmas? Close now!\u201d\n3.2.1 Some users need to focus on elements to access information about them. You must make sure that focusing on an element doesn\u2019t trigger any major changes, such as opening a new window, focusing on another element, or submitting a form.\n3.2.2 Webpages are easier for users when the controls do what they\u2019re supposed to do. Unless you have warned your users about it, you must make sure that changing the value of a control such as a text box, checkbox, or drop-down list doesn\u2019t trigger any major changes, such as opening a new window, focusing on another element, or submitting a form.\n3.2.3 To help your users to find the content they want on each webpage, you should put your navigation elements in the same place on each webpage. (This doesn\u2019t apply when your user has changed their preferences or when they use assistive technology to change how your content appears.) \n3.2.4 When a set of webpages includes things that have the same functionality on different webpages, you should name those things consistently. For example, don\u2019t use the word \u201cSearch\u201d for the search box on one webpage and \u201cFind\u201d for the search box on another webpage within that set of webpages.\n3.2.5 Let\u2019s go back to major changes, such as a new window opening, another element taking focus, or a form being submitted. You could make sure that they only happen when users deliberately make them happen, or when you have warned users about them first. For example, you could give the user a button for updating some content instead of automatically updating that content. Also, if a link will open in a new window, you could add the words \u201copens in new window\u201d to the link text.\n3.3.1 Users make mistakes when filling in forms. Your website must identify each mistake to your user, and must describe the mistake to your users in text so that the user can fix it. One way to identify mistakes reliably to your users is to set the aria-invalid attribute to true in the element that has a mistake. That makes sure that users with assistive technology will be alerted about the mistake. Of course, you can then use the [aria-invalid=\"true\"] attribute selector in your CSS to visually highlight any such mistakes. Also, look into how certain attributes of the input element such as required, type, and list can help prevent and highlight mistakes.\n3.3.2 You must include labels or instructions (and possibly examples) in your website\u2019s forms, to help your users to avoid making mistakes. \n3.3.3 When your user makes a mistake when filling in a form, your webpage should suggest ways to fix that mistake, if possible. This doesn\u2019t apply in scenarios where those suggestions could affect the security of the content.\n3.3.4 Whenever your user submits information that:\n\nhas legal or financial consequences; or\naffects information that they have previously saved in your website; or\nis part of a test\n\n\u2026you should make sure that they can:\n\nundo it; or\ncorrect any mistakes, after your webpage checks their information; or\nreview, confirm, and correct the information before they finally submit it.\n\n3.3.5 You could help prevent your users from making mistakes by providing obvious, specific help, such as examples, animations, spell-checking, or extra instructions.\n3.3.6 Whenever your user submits any information, you could make sure that they can:\n\nundo it; or\ncorrect any mistakes, after your webpage checks their information; or\nreview, confirm, and correct the information before they finally submit it.\n\nHave you made your website robust enough to work on your users\u2019 browsers and assistive technologies?\nThe fourth and final guideline has criteria that help you prevent your users from asking, \u201cWhy the **** doesn\u2019t this work on my device?\u201d\n4.1.1 You must make sure that your website works as well as possible with current and future browsers and assistive technology. Prioritise complying with web standards instead of relying on the capabilities of currently popular devices and browsers. Web developers didn\u2019t expect their users to be unwrapping the Wii U Browser five years ago\u2014who knows what browsers and assistive technologies our users will be unwrapping in five years\u2019 time? Avoid hacks, and use the W3C Markup Validation Service to make sure that your HTML has no errors.\n4.1.2 If you develop your own user interface components, you must make their name, role, state, properties, and values available to your user\u2019s browsers and assistive technologies. That should make them almost as accessible as standard HTML elements such as links, buttons, and checkboxes.\n\u201c\u2026and a partridge in a pear tree!\u201d\n\u2026as that very long Christmas song goes. We\u2019ve covered a lot in this article\u2014because your users have a lot of different levels of ability. Hopefully this has demystified the Web Content Accessibility Guidelines 2.0 for you. Hopefully you spotted a few situations that could arise for users on your website, and you now know how to tackle them. \nTo start applying what we\u2019ve covered, you might like to look at Sarah Horton and Whitney Quesenbery\u2019s personas for Accessible UX. Discuss the personas, get into their heads, and think about which aspects of your website might cause problems for them. See if you can apply what we\u2019ve covered today, to help users like them to do what they need to do on your website.\nHow to know when your website is perfectly accessible for everyone\nLOL! There will never be a time when your website becomes perfectly accessible for everyone. Don\u2019t aim for that. Instead, aim for regularly testing and making your website more accessible.\nWeb Content Accessibility Guidelines (WCAG) 2.1\nThe W3C hope to release the Web Content Accessibility Guidelines (WCAG) 2.1 as a \u201crecommendation\u201d (that\u2019s what the W3C call something that we should start using) by the middle of next year. Ten years may seem like a long time to move from version 2.0 to version 2.1, but consider the scale of the task: the editors have to update the guidelines to cover all the new ways that people interact with new technologies, while keeping the guidelines backwards-compatible. Keep an eye out for 2.1!\nYou\u2019ll go down in history\nOne last point: I\u2019ve met a surprising number of web designers and developers who do great work to make their websites more accessible without ever telling their users about it. Some of your potential customers have possibly tried and failed to use your website in the past. They probably won\u2019t try again unless you let them know that things have improved. A quick Twitter search for your website\u2019s name alongside phrases like \u201cassistive technology\u201d, \u201cdoesn\u2019t work\u201d, or \u201c#fail\u201d can let you find frustrated users\u2014so you can tell them about how you\u2019re making your website more accessible. Start making your websites work better for everyone\u2014and please, let everyone know.", "year": "2017", "author": "Alan Dalton", "author_slug": "alandalton", "published": "2017-12-03T00:00:00+00:00", "url": "https://24ways.org/2017/wcag-for-people-who-havent-read-them/", "topic": "code"}
{"rowid": 201, "title": "Lint the Web Forward With Sonarwhal", "contents": "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\u00e9sum\u00e9 and portfolio. \nThat 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. \nSonarwhal 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. \nIntroducing sonarwhal\u2019s mascot Nellie\nGood 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\u2019s a lot to keep track of.\n\u00a0\nWeb development is hard \nStaying 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. \nCurrently sonarwhal checks for best practices in five categories: Accessibility, Interoperability, Performance, PWAs, and Security. Each check is called a \u201crule\u201d. 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.). \nYou can use sonarwhal in two ways:\n\nAn online version, that provides a quick and easy way to scan any public website.\nA command line tool, if you want more control over the configuration, or want to integrate it into your development flow.\n\nThe Online Scanner\nThe 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.\nThe online version of sonarwal\nWhen 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\u2019s 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\u2019ll 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\u2019t, and useful links to even more in-depth documentation if you are interested in the subject.\nWe 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\u2019t 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!\nA results report\nThe 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! \nSonarwhal\u2019s CLI\u00a0\nThe 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:\nnpm install -g sonarwhal\nYou can now run sonarwhal from anywhere via:\nsonarwhal https://example.com\nUsing the CLI\nThe 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:\n\nWhat 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.\nWhat 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.\nDo you want to use the recommended rules configuration? Rules are the things we are validating. Unless you\u2019ve read the documentation and know what you are doing, first timers should probably use the recommended configuration.\nWhat 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 \u201cHighest Document Mode\u201d will tell you to add the \u201cX-UA-Compatible\u201d header if IE10 or lower is targeted or remove if the opposite is true. \n\nsonarwhal configuration generator questions\nOnce you answer all these questions the scan will start and you will have a .sonarwhalrc file similar to the following:\n{\n \"connector\": {\n \"name\": \"jsdom\",\n \"options\": {\n \"waitFor\": 1000\n }\n },\n \"formatters\": \"stylish\",\n \"rulesTimeout\": 120000,\n \"rules\": {\n \"apple-touch-icons\": \"error\",\n \"axe\": \"error\",\n \"content-type\": \"error\",\n \"disown-opener\": \"error\",\n \"highest-available-document-mode\": \"error\",\n \"validate-set-cookie-header\": \"warning\",\n // ...\n }\n}\nYou 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. \nsonarwhal results on my website and hurting my feelings \ud83d\udc94\nNow 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\u2019ve 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.\nThe documentation should give enough guidance on how to fix the errors, but if it\u2019s 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.\nWhen 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\u2019t 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. \nThe information at the top of the search results isn\u2019t always the correct answer to an issue and we don\u2019t want you to have to search through outdated documentation. As sonarwhal\u2019s capabilities expand, the goal is for it to be the one stop shop for helping preflight your website. \nThe journey up until now and looking forward\n\nOn the Microsoft Edge team, we\u2019re 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 \u2018best practices\u2019 that could be avoided, so we built this tool to help everyone help make the web a better place.\nWhen 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\u2019ve used along the way:\n\nCommunity Driven. We build for the community\u2019s best interests. The web belongs to everyone and this project should too. Not only is it open source, we\u2019ve also donated it to the JS Foundation and have an inclusive governance model that welcomes the collaboration of anyone, individual or company.\nUser 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.\nCollaborative. We didn\u2019t 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.\n\nThis is just the beginning and we still have lots to do. We\u2019re hard at work on a backlog of exciting features for future releases, such as:\n\nNew rules for a variety of areas like\u00a0performance,\u00a0accessibility,\u00a0security,\u00a0progressive web apps, and more.\nA 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.\nConfiguration 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.\n\nThis 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\u00a0few issues where you might be able to help. Also, don\u2019t forget to check the rest of the\u00a0sonarwhal GitHub organization. PRs are always welcome and appreciated! \nLet us know what you think about the scanner at @NarwhalNellie on Twitter and we hope you\u2019ll help us lint the web forward!", "year": "2017", "author": "Stephanie Drescher", "author_slug": "stephaniedrescher", "published": "2017-12-02T00:00:00+00:00", "url": "https://24ways.org/2017/lint-the-web-forward-with-sonarwhal/", "topic": "code"}
{"rowid": 204, "title": "Cascading Web Design with Feature Queries", "contents": "Feature queries, also known as the @supports rule, were introduced as an extension to the CSS2 as part of the CSS Conditional Rules Module Level 3, which was first published as a working draft in 2011. It is a conditional group rule that tests if the browser\u2019s user agent supports CSS property:value pairs, and arbitrary conjunctions (and), disjunctions (or), and negations (not) of them.\nThe motivation behind this feature was to allow authors to write styles using new features when they were supported but degrade gracefully in browsers where they are not. Even though the nature of CSS already allows for graceful degradation, for example, by ignoring unsupported properties or values without disrupting other styles in the stylesheet, sometimes we need a bit more than that.\nCSS is ultimately a holistic technology, in that, even though you can use properties in isolation, the full power of CSS shines through when used in combination. This is especially evident when it comes to building web layouts. Having native feature detection in CSS makes it much more convenient to build with cutting-edge CSS for the latest browsers while supporting older browsers at the same time.\nBrowser support\nOpera first implemented feature queries in November 2012, both Chrome and Firefox had it since May 2013. There have been several articles about feature queries written over the years, however, it seems that awareness of its broad support isn\u2019t that well-known. Much of the earlier coverage on feature queries was not written in English, and perhaps that was a limiting factor.\n\n@supports \u2015 CSS\u306eFeature Queries by Masataka Yakura, August 8 2012\nNative CSS Feature Detection via the @supports Rule by Chris Mills, December 21 2012\nCSS @supports by David Walsh, April 3 2013\nResponsive typography with CSS Feature Queries by Aral Balkan, April 9 2013\nHow to use the @supports rule in your CSS by Lea Verou, January 31 2014\nCSS Feature Queries by Amit Tal, June 2 2014\nComing Soon: CSS Feature Queries by Adobe Web Platform Team, August 21 2014\nCSS feature queries mittels @supports by Daniel Erlinger, November 27 2014\n\nAs of December 2017, all current major browsers and their previous 2 versions support feature queries. Feature queries are also supported on Opera Mini, UC Browser and Samsung Internet. The only browsers that do not support feature queries are Internet Explorer and Blackberry Mobile, but that may be less of an issue than you might think.\n\n Can I Use css-featurequeries? Data on support for the css-featurequeries feature across the major browsers from caniuse.com.\n\nGranted, there is still a significant number of organisations that require support of Internet Explorer. Microsoft still continues to support IE11 for the life-cycle of Windows 7, 8 and 10. They have, however, stopped supporting older versions since January 12, 2016. It is inevitable that there will be organisations that, for some reason or another, make it mandatory to support IE, but as time goes on, this number will continue to shrink.\nJen Simmons wrote an extensive article called Using Feature Queries in CSS which discussed a matrix of potential situations when it comes to the usage of feature queries. The following image is a summary of the aforementioned matrix.\n\nThe most tricky situation we have to deal with is the box in the top-left corner, which are \u201cbrowsers that don\u2019t support feature queries, yet do support the feature in question\u201d. For cases like those, it really depends on the specific CSS feature you want to use and a subsequent evaluation of the pros and cons of not including that feature in spite of the fact the browser (most likely Internet Explorer) supports it.\nThe basics of feature queries\nAs with any conditional, feature queries operate on boolean logic, in other words, if the query resolves to true, apply the CSS properties within the block, or else just ignore the entire block altogether. The syntax of a simple feature query is as follows:\n.selector {\n /* Styles that are supported in old browsers */\n}\n\n@supports (property:value) {\n .selector {\n /* Styles for browsers that support the specified property */\n }\n}\nNote that the parentheses around the property:value pair are mandatory and the rule is invalid without them. Styles that apply to older browsers, i.e. fallback styles, should come first, followed by the newer properties, which are contained within the @supports conditional. Because of the cascade, fallback styles will be overridden by the newer properties in the modern browsers that support them.\nmain {\n background-color: red;\n}\n\n@supports (display:grid) {\n main {\n background-color: green;\n }\n}\nIn this example, browsers that support CSS grid will have a main element with a green background colour because the conditional resolves to true, while browsers that do not support grid will have a main element with a red background colour.\nThe implication of such behaviour means that we can layer on enhanced styles based on the features we want to use and these styles will show up in browsers that support them. But for those that do not, they will get a more basic look that still works anyway. And that will be our approach moving forward.\nBoolean operators for feature queries\nThe and operator allows us to test for support of multiple properties within a single conditional. This would be useful for cases where the desired output requires multiple cutting-edge features to be supported at the same time to work. All the property:value pairs listed in the conditional must resolve to true for the styles within the rule to be applied.\n@supports (transform: rotate(45deg)) and\n (writing-mode: vertical-rl) {\n /* Some CSS styles */\n}\nThe or operator allows us to list multiple property:value pairs in the conditional and as long as one of them resolves to true, the styles within the block will be applied. A relevant use-case would be for properties with vendor-prefixes.\n@supports (background: -webkit-gradient(linear, left top, left bottom, from(white), to(black))) or\n (background: -o-linear-gradient(top, white, black)) or\n (background: linear-gradient(to bottom, white, black)) {\n /* Some CSS styles */\n}\nThe not operator negates the resolution of the property:value pair in the conditional, resolving to false when the property is supported and vice versa. This is useful when there are two distinct sets of styles to be applied depending on the support of a specific feature. However, we do need to keep in mind the case where a browser does not support feature queries, and handle the styles for those browsers accordingly.\n@supports not (shape-outside: polygon(100% 80%,20% 0,100% 0)) {\n /* Some CSS styles */\n}\nTo avoid confusion between and and or, these operators must be explicitly declared as opposed to using commas or spaces. To prevent confusion caused by precedence rules, and, or and not operators cannot be mixed without a layer of parentheses.\nThis rule is not valid and the styles within the block will be ignored.\n@supports (transition-property: background-color) or\n (animation-name: fade) and\n (transform: scale(1.5)) {\n /* Some CSS styles */\n}\nTo make it work, parentheses must be added either around the two properties adjacent to the or or the and operator like so:\n@supports ((transition-property: background-color) or\n (animation-name: fade)) and\n (transform: scale(1.5)) {\n /* Some CSS styles */\n}\n@supports (transition-property: background-color) or\n ((animation-name: fade) and\n (transform: scale(1.5))) {\n /* Some CSS styles */\n}\nThe current specification states that whitespace is required after a not and on both sides of an and or or, but this may change in a future version of the specification. It is acceptable to add extra parentheses even when they are not needed, but omission of parentheses is considered invalid.\nCascading web design\nI\u2019d like to introduce the concept of cascading web design, an approach made possible with feature queries. Browser update cycles are much shorter these days, so new features and bug fixes are being pushed out a lot more frequently as compared to the early days of the web.\nWith the maturation of web standards, browser behaviour is less unpredictable than before, but each browser will still have their respective quirks. Chances are, the latest features will not ship across all browsers at the same time. But you know what? That\u2019s perfectly fine. If we accept this as a feature of the web, instead of a bug, we\u2019ve just opened up a lot more web design possibilities.\nThe following example is a basic, responsive grid layout of items laid out with flexbox, as viewed on IE11.\n\nWe can add a block of styles within an @supports rule to apply CSS grid properties for browsers that support them to enhance this layout, like so:\n\nThe web is not a static medium. It is dynamic and interactive and we manipulate this medium by writing code to tell the browser what we want it to do. Rather than micromanaging the pixels in our designs, maybe it\u2019s time we cede control of our designs to the browsers that render them. This means being okay with your designs looking different across browsers and devices.\nAs mentioned earlier, CSS works best when various properties are combined. It\u2019s one of those things whose whole is greater than the sum of its parts. So feature queries, when combined with media queries, allow us to design layouts that are most effective in the environment they have to perform in.\nSuch an approach requires interpolative thinking, on multiple levels. As web designers and developers, we don\u2019t just think in one fixed dimension, we get to think about how our design will morph on a narrow screen, or on an older browser, in addition to how it will appear on a browser with the latest features.\nIn the following example, the layout on the left is what IE11 users will see, the one in the middle is what Firefox users will see, because Firefox doesn\u2019t support CSS shapes yet, but once it does, it will then look like the layout on the right, which is what Chrome users see now.\n\nWith the release of CSS Grid this year, we\u2019ve hit another milestone in the evolution of the web as a medium. The beauty of the web is its backwards compatibility and generous fault tolerance. Browser features are largely additive, holding onto the good parts and building on top of them, while deprecating the bits that didn\u2019t work well.\nFeature queries allow us to progressively enhance our CSS, establishing a basic level of user experience across the widest range of browsers, while building in more advanced functionality for browsers who can use them. And hopefully, this will allow more of us to create designs that truly embrace the nature of the web.", "year": "2017", "author": "Chen Hui Jing", "author_slug": "chenhuijing", "published": "2017-12-01T00:00:00+00:00", "url": "https://24ways.org/2017/cascading-web-design/", "topic": "code"}
{"rowid": 300, "title": "Taking Device Orientation for a Spin", "contents": "When The Police sang \u201cDon\u2019t Stand So Close To Me\u201d they weren\u2019t talking about using a smartphone to view a panoramic image on Facebook, but they could have been. For years, technology has driven relentlessly towards devices we can carry around in our pockets, and now that we\u2019re there, we\u2019re expected to take the thing out of our pocket and wave it around in front of our faces like a psychotic donkey in search of its own dangly carrot.\nBut if you can\u2019t beat them, join them.\nA brave new world\nA couple of years back all sorts of specs for new HTML5 APIs sprang up much to our collective glee. Emboldened, we ran a few tests and found they basically didn\u2019t work in anything and went off disheartened into the corner for a bit of a sob.\nTurns out, while we were all busy boohooing, those browser boffins have actually being doing some work, and lo and behold, some of these APIs are even half usable. Mostly literally half usable\u2014we\u2019re still talking about browsers, after all.\nNow, of course they\u2019re all a bit JavaScripty and are going to involve complex methods and maths and science and probably about a thousand dependancies from Github that will fall out of fashion while we\u2019re still trying to locate the documentation, right? Well, no! \nSo what if we actually wanted to use one of these APIs, say to impress our friends with our ability to make them wave their phones in front of their faces (because no one enjoys looking hapless more than the easily-technologically-impressed), how could we do something like that? Let\u2019s find out.\nThe Device Orientation API\nThe phone-wavy API is more formally known as the DeviceOrientation Event Specification. It does a bunch of stuff that basically doesn\u2019t work, but also gives us three values that represent orientation of a device (a phone, a tablet, probably not a desktop computer) around its x, y and z axes. You might think of it as pitch, roll and yaw if you like to spend your weekends wearing goggles and a leather hat.\nThe main way we access these values is through an event listener, which can inform our code every time the value changes. Which is constantly, because you try and hold a phone still and then try and hold the Earth still too.\nThe API calls those pitch, roll and yaw values alpha, beta and gamma. Chocks away:\nwindow.addEventListener('deviceorientation', function(e) {\n console.log(e.alpha);\n console.log(e.beta);\n console.log(e.gamma);\n});\nIf you look at this test page on your phone, you should be able to see the numbers change as you twirl the thing around your body like the dance partner you never had. Wrist strap recommended.\nOne important note\nLike may of these newfangled APIs, Device Orientation is only available over HTTPS. We\u2019re not allowed to have too much fun without protection, so make sure that you\u2019re working on a secure line. I\u2019ve found a quick and easy way to share my local dev environment over TLS with my devices is to use an ngrok tunnel.\nngrok http -host-header=rewrite mylocaldevsite.dev:80\nngrok will then set up a tunnel to your dev site with both HTTP and HTTPS URL options. You, of course, want the HTTPS option.\nRight, where were we?\nMake something to look at\nIt\u2019s all well and good having a bunch of numbers, but they\u2019re no use unless we do something with them. Something creative. Something to inspire the generations. Or we could just build that Facebook panoramic image viewer thing (because most of us are familiar with it and we\u2019re not trying to be too clever here). Yeah, let\u2019s just build one of those.\nOur basic framework is going to be similar to that used for an image carousel. We have a container, constrained in size, and CSS overflow property set to hidden. Into this we place our wide content and use positioning to move the content back and forth behind the \u2018window\u2019 so that the part we want to show is visible.\nHere it is mocked up with a slider to set the position. When you release the slider, the position updates. (This actually tests best on desktop with your window slightly narrowed.)\nThe details of the slider aren\u2019t important (we\u2019re about to replace it with phone-wavy goodness) but the crucial part is that moving the slider results in a function call to position the image. This takes a percentage value (0-100) with 0 being far left and 100 being far right (or \u2018alt-nazi\u2019 or whatever).\nvar position_image = function(percent) {\n var pos = (img_W / 100)*percent;\n img.style.transform = 'translate(-'+pos+'px)'; \n};\nAll this does is figure out what that percentage means in terms of the image width, and set the transform: translate(\u2026); CSS property to move the image. (We use translate because it might be a bit faster to animate than left/right positioning.)\nOk. We can now read the orientation values from our device, and we can programatically position the image. What we need to do is figure out how to convert those raw orientation values into a nice tidy percentage to pass to our function and we\u2019re done. (We\u2019re so not done.)\nThe maths bit\nIf we go back to our raw values test page and make-believe that we have a fascinating panoramic image of some far-off beach or historic monument to look at, you\u2019ll note that the main value that is changing as we swing back and forth is the \u2018alpha\u2019 value. That\u2019s the one we want to track.\nAs our goal here is hey, these APIs are interesting and fun and not let\u2019s build the world\u2019s best panoramic image viewer, we\u2019ll start by making a few assumptions and simplifications:\n\nWhen the image loads, we\u2019ll centre the image and take the current nose-forward orientation reading as the middle.\nMoving left, we\u2019ll track to the left of the image (lower percentage).\nMoving right, we\u2019ll track to the right (higher percentage).\nIf the user spins round, does cartwheels or loads the page then hops on a plane and switches earthly hemispheres, they\u2019re on their own.\n\nNose-forward\nWhen the page loads, the initial value of alpha gives us our nose-forward position. In Safari on iOS, this is normalised to always be 0, whereas most everywhere else it tends to be bound to pointy-uppy north. That doesn\u2019t really matter to us, as we don\u2019t know which direction the user might be facing in anyway \u2014 we just need to record that initial state and then use it to compare any new readings.\nvar initial_position = null;\n\nwindow.addEventListener('deviceorientation', function(e) {\n if (initial_position === null) {\n initial_position = Math.floor(e.alpha);\n };\n\n var current_position = initial_position - Math.floor(e.alpha);\n});\n(I\u2019m rounding down the values with Math.floor() to make debugging easier - we\u2019ll take out the rounding later.)\nWe get our initial position if it\u2019s not yet been set, and then calculate the current position as a difference between the new value and the stored one.\nThese values are weird\nOne thing you need to know about these values, is that they range from 0 to 360 but then you also get weird left-of-zero values like -2 and whatever. And they wrap past 360 back to zero as you\u2019d expect if you do a forward roll.\nWhat I\u2019m interested in is working out my rotation. If 0 is my nose-forward position, I want a positive value as I turn right, and a negative value as I turn left. That puts the awkward 360-tipping point right behind the user where they can\u2019t see it.\nvar rotation = current_position;\nif (current_position > 180) rotation = current_position-360;\nWhich way up?\nSince we\u2019re talking about orientation, we need to remember that the values are going to be different if the device is held in portrait on landscape mode. See for yourself - wiggle it like a steering wheel and you get different values. That\u2019s easy to account for when you know which way up the device is, but in true browser style, the API for that bit isn\u2019t well supported. The best I can come up with is:\nvar screen_portrait = false;\nif (window.innerWidth < window.innerHeight) {\n screen_portrait = true;\n}\nIt works. Then we can use screen_portrait to branch our code:\nif (screen_portrait) {\n if (current_position > 180) rotation = current_position-360;\n} else {\n if (current_position < -180) rotation = 360+current_position;\n}\nHere\u2019s the code in action so you can see the values for yourself. If you change screen orientation you\u2019ll need to refresh the page (it\u2019s a demo!).\nLimiting rotation\nNow, while the youth of today are rarely seen without a phone in their hands, it would still be unreasonable to ask them to spin through 360\u00b0 to view a photo. Instead, we need to limit the range of movement to something like 60\u00b0-from-nose in either direction and normalise our values to pan the entire image across that 120\u00b0 range. -60 would be full-left (0%) and 60 would be full-right (100%).\nIf we set max_rotation = 60, that code ends up looking like this:\nif (rotation > max_rotation) rotation = max_rotation;\nif (rotation < (0-max_rotation)) rotation = 0-max_rotation;\n\nvar percent = Math.floor(((rotation + max_rotation)/(max_rotation*2))*100);\nWe should now be able to get a rotation from -60\u00b0 to +60\u00b0 expressed as a percentage. Try it for yourself.\nThe big reveal\nAll that\u2019s left to do is pass that percentage to our image positioning function and would you believe it, it might actually work.\nposition_image(percent);\nYou can see the final result and take it for a spin. Literally.\nSo what have we made here? Have we built some highly technical panoramic image viewer to aid surgeons during life-saving operations using only JavaScript and some slightly questionable mathematics? No, my friends, we have not. Far from it. \nWhat we have made is progress. We\u2019ve taken a relatively newly available hardware API and a bit of simple JavaScript and paired it with existing CSS knowledge and made something that we didn\u2019t have this morning. Something we probably didn\u2019t even want this morning. Something that if you take a couple of steps back and squint a bit might be a prototype for something vaguely interesting. But more importantly, we\u2019ve learned that our browsers are just a little bit more capable than we thought.\nThe web platform is maturing rapidly. There are new, relatively unexplored APIs for doing all sorts of crazy thing that are often dismissed as the preserve of native apps. Like some sort of app marmalade. Poppycock. \nThe web is an amazing, exciting place to create things. All it takes is some base knowledge of the fundamentals, a creative mind and a willingness to learn. We have those! So let\u2019s create things.", "year": "2016", "author": "Drew McLellan", "author_slug": "drewmclellan", "published": "2016-12-24T00:00:00+00:00", "url": "https://24ways.org/2016/taking-device-orientation-for-a-spin/", "topic": "code"}
{"rowid": 305, "title": "CSS Writing Modes", "contents": "Since you may not have a lot of time, I\u2019m going to start at the end, with the dessert.\nYou can use a little-known, yet important and powerful CSS property to make text run vertically. Like this.\n\nOr instead of running text vertically, you can layout a set of icons or interface buttons in this way. Or, of course, with anything on your page. \nThe CSS I\u2019ve applied makes the browser rethink the orientation of the world, and flow the layout of this element at a 90\u00b0 angle to \u201cnormal\u201d. Check out the live demo, highlight the headline, and see how the cursor is now sideways.\nSee the Pen Writing Mode Demo \u2014 Headline by Jen Simmons (@jensimmons) on CodePen.\n\nThe code for accomplishing this is pretty simple. \nh1 { \n writing-mode: vertical-rl;\n}\nThat\u2019s all it takes to switch the writing mode from the web\u2019s default horizontal top-to-bottom mode to a vertical right-to-left mode. If you apply such code to the html element, the entire page is switched, affecting the scroll direction, too. \nIn my example above, I\u2019m telling the browser that only the h1 will be in this vertical-rl mode, while the rest of my page stays in the default of horizontal-tb.\nSo now the dessert course is over. Let me serve up this whole meal, and explain the the CSS Writing Mode Specification.\nWhy learn about writing modes?\nThere are three reasons I\u2019m teaching writing modes to everyone\u2014including western audiences\u2014and explaining the whole system, instead of quickly showing you a simple trick.\n\n\nWe live in a big, diverse world, and learning about other languages is fascinating. Many of you lay out pages in languages like Chinese, Japanese and Korean. Or you might be inspired to in the future.\n\n\nUsing writing-mode to turn bits sideways is cool. This CSS can be used in all kinds of creative ways, even if you are working only in English.\n\nMost importantly, I\u2019ve found understanding Writing Modes incredibly helpful when understanding Flexbox and CSS Grid. Before I learned Writing Mode, I felt like there was still a big hole in my knowledge, something I just didn\u2019t get about why Grid and Flexbox work the way they do. Once I wrapped my head around Writing Modes, Grid and Flexbox got a lot easier. Suddenly the Alignment properties, align-* and justify-*, made sense.\n\nWhether you know about it or not, the writing mode is the first building block of every layout we create. You can do what we\u2019ve been doing for 25 years \u2013 and leave your page set to the default left-to-right direction, horizontal top-to-bottom writing mode. Or you can enter a world of new possibilities where content flows in other directions.\nCSS properties\nI\u2019m going to focus on the CSS writing-mode property in this article. It has five possible options:\n writing-mode: horizontal-tb;\n writing-mode: vertical-rl;\n writing-mode: vertical-lr;\n writing-mode: sideways-rl;\n writing-mode: sideways-lr;\nThe CSS Writing Modes Specification is designed to support a wide range of written languages in all our human and linguistic complexity. Which\u2014spoiler alert\u2014is pretty insanely complex. The global evolution of written languages has been anything but simple. \nSo I\u2019ve got to start with explaining some basic concepts of web page layout and writing systems. Then I can show you what these CSS properties do. \nInline Direction, Block Direction, and Character Direction\nIn the world of the web, there\u2019s a concept of \u2018block\u2019 and \u2018inline\u2019 layout. If you\u2019ve ever written display: block or display: inline, you\u2019ve leaned on these concepts. \nIn the default writing mode, blocks stack vertically starting at the top of the page and working their way down. Think of how a bunch of block-levels elements stack\u2014like a bunch of a paragraphs\u2014that\u2019s the block direction. \n\nInline is how each line of text flows. The default on the web is from left to right, in horizontal lines. Imagine this text that you are reading right now, being typed out one character at a time on a typewriter. That\u2019s the inline direction. \n\nThe character direction is which way the characters point. If you type a capital \u201cA\u201d for instance, on which side is the top of the letter? Different languages can point in different directions. Most languages have their characters pointing towards the top of the page, but not all.\n\nPut all three together, and you start to see how they work as a system. \nThe default settings for the web work like this.\nNow that we know what block, inline, and character directions mean, let\u2019s see how they are used in different writing systems from around the world.\nThe four writing systems of CSS Writing Modes\nThe CSS Writing Modes Specification handles all the use cases for four major writing systems; Latin, Arabic, Han and Mongolian. \nLatin-based systems\nOne writing system dominates the world more than any other, reportedly covering about 70% of the world\u2019s population. \n\nThe text is horizontal, running from left to right, or LTR. The block direction runs from top to bottom. \nIt\u2019s called the Latin-based system because it includes all languages that use the Latin alphabet, including English, Spanish, German, French, and many others. But there are many non-Latin-alphabet languages that also use this system, including Greek, Cyrillic (Russian, Ukrainian, Bulgarian, Serbian, etc.), and Brahmic scripts (Devanagari, Thai, Tibetan), and many more.\nYou don\u2019t need to do anything in your CSS to trigger this mode. This is the default. \nBest practices, however, dictate that you declare in your opening element which language and which direction (LTR or RTL) you are using. This website, for instance, uses to let the browser know this content is published in Great Britian\u2019s version of English, in a left to right direction. \nArabic-based systems\nArabic, Hebrew and a few other languages run the inline direction from right to left. This is commonly known as RTL. \nNote that the inline direction still runs horizontally. The block direction runs from top to bottom. And the characters are upright.\n\nIt\u2019s not just the flow of text that runs from right to left, but everything about the layout of the website. The upper right-hand corner is the starting position. Important things are on the right. The eyes travel from right to left. So, typically RTL websites use layouts that are just like LTR websites, only flipped.\nOn websites that support both LTR and RTL, like the United Nations\u2019 site at un.org, the two layouts are mirror images of each other.\nFor many web developers, our experiences with internationalization have focused solely on supporting Arabic and Hebrew script. \nCSS layout hacks for internationalization & RTL\nTo prepare an LTR project to support RTL, developers have had to create all sorts of hacks. For example, the Drupal community started a convention of marking every margin-left and -right, every padding-left and -right, every float: left and float: right with the comment /* LTR */. Then later developers could search for each instance of that exact comment, and create stylesheets to override each left with right, and vice versa. It\u2019s a tedious and error prone way to work. CSS itself needed a better way to let web developers write their layout code once, and easily switch language directions with a single command.\nOur new CSS layout system does exactly that. Flexbox, Grid and Alignment use start and end instead of left and right. This lets us define everything in relationship to the writing system, and switch directions easily. By writing justify-content: flex-start, justify-items: end, and eventually margin-inline-start: 1rem we have code that doesn\u2019t need to be changed. \nThis is a much better way to work. I know it can be confusing to think through start and end as replacements for left and right. But it\u2019s better for any multiligual project, and it\u2019s better for the web as a whole.\nSadly, I\u2019ve seen CSS preprocessor tools that claim to \u201cfix\u201d the new CSS layout system by getting rid of start and end and bringing back left and right. They want you to use their tool, write justify-content: left, and feel self-righteous. It seems some folks think the new way of working is broken and should be discarded. It was created, however, to fulfill real needs. And to reflect a global internet. As Bruce Lawson says, WWW stands for the World Wide Web, not the Wealthy Western Web. Please don\u2019t try to convince the industry that there\u2019s something wrong with no longer being biased towards western culture. Instead, spread the word about why this new system is here. \nSpend a bit of time drilling the concept of inline and block into your head, and getting used to start and end. It will be second nature soon enough. \nI\u2019ve also seen CSS preprocessors that let us use this new way of thinking today, even as all the parts aren\u2019t fully supported by browsers yet. Some tools let you write text-align: start instead of text-align: left, and let the preprocessor handle things for you. That is terrific, in my opinion. A great use of the power of a preprocessor to help us switch over now. \nBut let\u2019s get back to RTL. \nHow to declare your direction\nYou don\u2019t want to use CSS to tell the browser to switch from an LTR language to RTL. You want to do this in your HTML. That way the browser has the information it needs to display the document even if the CSS doesn\u2019t load.\nThis is accomplished mainly on the html element. You should also declare your main language. As I mentioned above, the 24 ways website is using to declare the LTR direction and the use of British English. The UN Arabic website uses to declare the site as an Arabic site, using a RTL layout. \nThings get more complicated when you\u2019ve got a page with a mix of languages. But I\u2019m not going to get into all of that, since this article is focused on CSS and layouts, not explaining everything about internationalization. \nLet me just leave direction here by noting that much of the heavy work of laying out the characters which make up each word is handled by Unicode. If you are interested in learning more about LTR, RTL and bidirectional text, watch this video: Introduction to Bidirectional Text, a presentation by Elika Etemad. \nMeanwhile, let\u2019s get back to CSS.\nThe writing mode CSS for Latin-based and Arabic-based systems\nFor both of these systems\u2014Latin-based and Arabic-based, whether LTR or RTL\u2014the same CSS property applies for specifying the writing mode: writing-mode: horizontal-tb. That\u2019s because in both systems, the inline text flow is horizontal, while the block direction is top-to-bottom. This is expressed as horizontal-tb.\nhorizontal-tb is the default writing mode for the web, so you don\u2019t need to specify it unless you are overriding something else higher up in the cascade. You can just imagine that every site you\u2019ve ever built came with:\nhtml {\n writing-mode: horizontal-tb;\n}\nNow let\u2019s turn our attention to the vertical writing systems. \nHan-based systems\nThis is where things start to get interesting. \nHan-based writing systems include CJK languages, Chinese, Japanese, Korean and others. There are two options for laying out a page, and sometimes both are used at the same time.\nMuch of CJK text is laid out like Latin-based languages, with a horizontal top-to-bottom block direction, and a left-to-right inline direction. This is the more modern way to doing things, started in the 20th century in many places, and further pushed into domination by the computer and later the web. \nThe CSS to do this bit of the layouts is the same as above:\nsection {\n writing-mode: horizontal-tb;\n}\nOr, you know, do nothing, and get that result as a default. \nAlternatively Han-based languages can be laid out in a vertical writing mode, where the inline direction runs vertically, and the block direction goes from right to left. \nSee both options in this diagram:\n\nNote that the horizontal text flows from left to right, while the vertical text flows from right to left. Wild, eh? \nThis Japanese issue of Vogue magazine is using a mix of writing modes. The cover opens on the left spine, opposite of what an English magazine does. \n\nThis page mixes English and Japanese, and typesets the Japanese text in both horizontal and vertical modes. Under the title \u201cRichard Stark\u201d in red, you can see a passage that\u2019s horizontal-tb and LTR, while the longer passage of text at the bottom of the page is typeset vertical-rl. The red enlarged cap marks the beginning of that passage. The long headline above the vertical text is typeset LTR, horizontal-tb.\n\nThe details of how to set the default of the whole page will depend on your use case. But each element, each headline, each section, each article can be marked to flow the opposite of the default however you\u2019d like.\nFor example, perhaps you leave the default as horizontal-tb, and specify your vertical elements like this:\ndiv.articletext {\n writing-mode: vertical-rl;\n}\nOr alternatively you could change the default for the page to a vertical orientation, and then set specific elements to horizontal-tb, like this:\nhtml { \n writing-mode: vertical-rl;\n}\nh2, .photocaptions, section {\n writing-mode: horizontal-tb;\n}\nIf your page has a sideways scroll, then the writing mode will determine whether the page loads with upper left corner as the starting point, and scroll to the right (horizontal-tb as we are used to), or if the page loads with the upper right corner as the starting point, scrolling to the left to display overflow. Here\u2019s an example of that change in scrolling direction, in a CSS Writing Mode demo by Chen Hui Jing. Check out her demo \u2014 you can switch from horizontal to vertical writing modes with a checkbox and see the difference. \n\nMongolian-based systems\nNow, hopefully so far all of this kind of makes sense. It might be a bit more complicated than expected, but it\u2019s not so hard. Well, enter the Mongolian-based systems.\nMongolian is also a vertical script language. Text runs vertically down the page. Just like Han-based systems. There are two major differences. First, the block direction runs the other way. In Mongolian, block-level elements stack from left to right. \nHere\u2019s a drawing of how Wikipedia would look in Mongolian if it were laid out correctly.\nPerhaps the Mongolian version of Wikipedia will be redone with this layout.\nNow you might think, that doesn\u2019t look so weird. Tilt your head to the left, and it\u2019s very familiar. The block direction starts on the left side of the screen and goes to the right. The inline direction starts on the top of the page and moves to the bottom (similar to RTL text, just turned 90\u00b0 counter-clockwise). But here comes the other huge difference. The character direction is \u201cupside down\u201d. The top of the Mongolian characters are not pointing to the left, towards the start edge of the block direction. They point to the right. Like this:\n\nNow you might be tempted to ignore all this. Perhaps you don\u2019t expect to be typesetting Mongolian content anytime soon. But here\u2019s why this is important for everyone \u2014 the way Mongolian works defines the results writing-mode: vertical-lr. And it means we cannot use vertical-lr for typesetting content in other languages in the way we might otherwise expect. \nIf we took what we know about vertical-rl and guessed how vertical-lr works, we might imagine this:\n\nBut that\u2019s wrong. Here\u2019s how they actually compare:\n\nSee the unexpected situation? In both writing-mode: vertical-rl and writing-mode: vertical-lr latin text is rotated clockwise. Neither writing mode let\u2019s us rotate text counter-clockwise. \nIf you are typesetting Mongolian content, apply this CSS in the same way you would apply writing-mode to Han-based writing systems. To the whole page on the html element, or to specific pages of the page like this:\nsection {\n writing-mode: vertical-lr;\n}\nNow, if you are using writing-mode for a graphic design effect on a language that is otherwise typesets horizontally, I don\u2019t think writing-mode: vertical-lr is useful. If the text wraps onto two lines, it stacks in a very unexpected way. So I\u2019ve sort of obliterated it from my toolkit. I find myself using writing-mode: vertical-rl a lot. And never using -lr. Hm.\nWriting modes for graphic design\nSo how do we use writing-mode to turn English headlines sideways? We could rely on transform: rotate()\nHere are two examples, one for each direction. (By the way, each of these demos use CSS Grid for their overall layout, so be sure to test them in a browser that supports CSS Grid, like Firefox Nightly.)\n\nIn this demo 4A, the text is rotated clockwise using this code: \nh1 {\n writing-mode: vertical-rl;\n}\n\nIn this demo 4B, the text is rotated counter-clockwise using this code: \nh1 {\n writing-mode: vertical-rl;\n transform: rotate(180deg);\n text-align: right;\n}\nI use vertical-rl to rotate the text so that it takes up the proper amount of space in the overall flow of the layout. Then I rotate it 180\u00b0 to spin it around to the other direction. And then I use text-align: right to get it to rise up to the top of it\u2019s container. This feels like a hack, but it\u2019s a hack that works.\nNow what I would like to do instead is use another CSS value that was designed for this use case \u2014 one of the two other options for writing mode.\nIf I could, I would lay out example 4A with:\nh1 {\n writing-mode: sideways-rl;\n}\nAnd layout example 4B with: \nh1 {\n writing-mode: sideways-lr;\n}\nThe problem is that these two values are only supported in Firefox. None of the other browsers recognize sideways-*. Which means we can\u2019t really use it yet. \nIn general, the writing-mode property is very well supported across browsers. So I\u2019ll use writing-mode: vertical-rl for now, with the transform: rotate(180deg); hack to fake the other direction. \nThere\u2019s much more to what we can do with the CSS designed to support multiple languages, but I\u2019m going to stop with this intermediate introduction. \nIf you do want a bit more of a taste, look at this example that adds text-orientation: upright; to the mix \u2014 turning the individual letters of the latin font to be upright instead of sideways.\n\nIt\u2019s this demo 4C, with this CSS applied: \nh1 {\n writing-mode: vertical-rl;\n text-orientation: upright;\n text-transform: uppercase;\n letter-spacing: -25px;\n}\nYou can check out all my Writing Modes demos at labs.jensimmons.com/#writing-modes. \n\nI\u2019ll leave you with this last demo. One that applies a vertical writing mode to the sub headlines of a long article. I like how small details like this can really bring a fresh feeling to the content. \nSee the Pen Writing Mode Demo \u2014 Article Subheadlines by Jen Simmons (@jensimmons) on CodePen.", "year": "2016", "author": "Jen Simmons", "author_slug": "jensimmons", "published": "2016-12-23T00:00:00+00:00", "url": "https://24ways.org/2016/css-writing-modes/", "topic": "code"}
{"rowid": 312, "title": "Preparing to Be Badass Next Year", "contents": "Once we\u2019ve eaten our way through the holiday season, people will start to think about new year\u2019s resolutions. We tend to focus on things that we want to change\u2026 and often things that we don\u2019t like about ourselves to \u201cfix\u201d. We set rules for ourselves, or try to start new habits or stop bad ones. We focus in on things we will or won\u2019t do. \nFor many of us the list of things we \u201cought\u201d to be spending time on is just plain overwhelming \u2013 family, charity/community, career, money, health, relationships, personal development. \nIt\u2019s kinda scary even just listing it out, isn\u2019t it? I want to encourage you to think differently about next year.\nThe ever-brilliant Kathy Sierra articulates a better approach really well when talking about the attitude we should have to building great products. She tells us to think not about what the user will do with our product, but about what they are trying to achieve in the real world and how our product helps them to be badass1.\nWhen we help the user be badass, then we are really making a difference. \nI suppose this is one way of saying: focus not on what you will do, focus on what it will help you achieve. How will it help you be awesome?\nIn what ways do you want to be more badass next year?\nA professional lens\nThough of course you might want to focus in on health or family or charity or community or another area next year, many people will want to become more badass in their chosen career. \nSo let\u2019s talk about a scaffold to help you figure out your professional / career development next year. \nFirst up, an assumption: everyone wants to be awesome. Nobody gets up in the morning aiming to be crap at their job. Nobody thinks to themselves \u201cToday I am aiming for just south of mediocre, and if I can mess up everybody else\u2019s ability to do good work then that will be just perfect2\u201d. \nErgo, you want to be awesome. So what does awesome look like? \nDanger!\nThe big trap that people fall into when think about their professional development is to immediately focus on the things that they aren\u2019t good at. When you ask people \u201cwhat do you want to work on getting better at next year?\u201d they frequently gravitate to the things that they believe they are bad at. \nWhy is this a trap? Because if you focus all your time and energy on improving the areas that you suck at, you are going to end up middling at everything. Going from bad \u2192 mediocre at a given skill / behaviour takes a bunch of time and energy. So if you spend all your time going from bad \u2192 mediocre at things, what do you think you end up? That\u2019s right, mediocre. \nMediocrity is not a great career goal, kids. \nWhat do you already rock at?\nThe much better investment of time and energy is to go from good \u2192 awesome. It often takes the same amount of relative time and energy, but wow the end result is better! So first, ask yourself and those who know you well what you are already pretty damn good at. Combat imposter syndrome by asking others. \nThen figure out how to double down on those things. What does brilliant look like for a given skill? What\u2019s the knowledge or practice that you need to level yourself up even further in that thing?\nBut what if I really really suck?\nAdmittedly, sometimes something you suck at really is holding you back. But it\u2019s important to separate out weaknesses (just something you suck at) from controlling weaknesses (something you suck at that actually matters for your chosen career). \nIf skill x is just not an important thing for you to be good at, you may never need to care that you aren\u2019t good at it. If your current role or the one you aspire to next really really requires you to be great at x, then it\u2019s worth investing your time and energy (and possibly money too) getting better at it.\nSo when you look at the things that you aren\u2019t good at, which of those are actually essential for success?\nThe right ratio\nA good rule of thumb is to pick three things you are already good at to work on becoming awesome at and limit yourself to one weakness that you are trying to improve on. That way you are making sure that you get to awesome in areas where you already have an advantage, and limit the amount of time you are spending on going from bad \u2192 mediocre. \nLevelling up learning\nSo once you\u2019ve figured out your areas you want to focus on next year, what do you actually decide to do? \nMost of all, you should try to design your day-to-day work in a way that it is also an effective learning experience. This means making sure you have a good feedback loop \u2013 you get to try something, see if it works, learn from it, rinse and repeat. \nIt\u2019s also about balance: you want to be challenged enough for work to be interesting, without it being so hard it\u2019s frustrating. You want to do similar / the same things often enough that you get to learn and improve, without it being so repetitive that it\u2019s boring. \nContinuously getting better at things you are already good at is actually both easier and harder than it sounds. The advantage is that it\u2019s pretty easy to add the feedback loop to make sure that you are improving; the disadvantage is that you\u2019re already good at these skills so you could easily just \u201cdo\u201d without ever stopping to reflect and improve. Build in time for personal retrospectives (\u201cWhat went well? What didn\u2019t? What one thing will I choose to change next time?\u201d) and find a way of getting feedback from outside sources as well. \nAs for the new skills, it\u2019s worth knowing that skill development follows a particular pattern:\n\nWe all start out unconsciously incompetent (we don\u2019t know what to do and if we tried we\u2019d unwittingly get it wrong), progress on to conscious incompetence (we now know we\u2019re doing it wrong) then conscious competence (we\u2019re doing it right but wow it takes effort and attention) and eventually get to unconscious competence (automatically getting it right). \nYour past experiences and knowledge might let you move faster through these stages, but no one gets to skip them. Invest the time and remember you need the feedback loop to really improve. \nWhat about keeping up?\nEverything changes very fast in our industry. We need to invest in not falling behind, in keeping on top of what great looks like. There are a bunch of ways to do this, from reading blog posts, following links on Twitter, reading books to attending conferences or workshops, or just finding time to build things in new ways or with new technologies. \nWhich will work best for you depends on how you best learn. Do you prefer to swallow a book? Do you learn most by building or experimenting? \nWhatever your learning style though, remember that there are three real needs:\n\nScan the landscape (what\u2019s changing, does it matter)\nGain the knowledge or skills (get the detail)\nApply the knowledge or skills (use it in reality)\n\nWhen you remember that you need all three of these things it can help you get more of what you do. \nFor me personally, I use a combination of conferences and blogs / Twitter to scan the landscape. Half of what I want out of a conference is just a list of things to have on my radar that might become important. I then pick a couple of things to go read up on more (I personally learn most effectively by swallowing a book or spec or similar). And then I pick one thing at a time to actually apply in real life, to embed the skill / knowledge. \nIn summary\n\nAim to be awesome (mediocrity is not a career goal).\nFigure out what you already rock at.\nOnly care about stuff you suck at that matters for your career.\nPick three things to go from good \u2192 awesome and one thing to go from bad \u2192 mediocre (or mediocre \u2192 good) this year.\nDesign learning into your daily work.\nScan the landscape, learn new stuff, apply it for real. \nBe badass!\n\n\n\n\n\nShe wrote a whole book about it. You should read it: Badass: Making Users Awesome\u00a0\u21a9\n\n\nBefore you argue too vehemently: I suppose some antisocial sociopathic bastards do exist. Identify them, and then RUN AWAY FAST AS YOU CAN #realtalk\u00a0\u21a9", "year": "2016", "author": "Meri Williams", "author_slug": "meriwilliams", "published": "2016-12-22T00:00:00+00:00", "url": "https://24ways.org/2016/preparing-to-be-badass-next-year/", "topic": "business"}
{"rowid": 301, "title": "Stretching Time", "contents": "Time is valuable. It\u2019s a precious commodity that, if we\u2019re not too careful, can slip effortlessly through our fingers. When we think about the resources at our disposal we\u2019re often guilty of forgetting the most valuable resource we have to hand: time.\nWe are all given an allocation of time from the time bank. 86,400 seconds a day to be precise, not a second more, not a second less.\nIt doesn\u2019t matter if we\u2019re rich or we\u2019re poor, no one can buy more time (and no one can save it). We are all, in this regard, equals. We all have the same opportunity to spend our time and use it to maximum effect. As such, we need to use our time wisely.\nI believe we can \u2018stretch\u2019 time, ensuring we make the most of every second and maximising the opportunities that time affords us.\nThrough a combination of \u2018Structured Procrastination\u2019 and \u2018Focused Finishing\u2019 we can open our eyes to all of the opportunities in the world around us, whilst ensuring that we deliver our best work precisely when it\u2019s required. A win win, I\u2019m sure you\u2019ll agree.\nStructured Procrastination\nI\u2019m a terrible procrastinator. I used to think that was a curse \u2013 \u201cWhy didn\u2019t I just get started earlier?\u201d \u2013 over time, however, I\u2019ve started to see procrastination as a valuable tool if it is used in a structured manner.\nDon Norman refers to procrastination as \u2018late binding\u2019 (a term I\u2019ve happily hijacked). As he argues, in Why Procrastination Is Good, late binding (delay, or procrastination) offers many benefits:\n\nDelaying decisions until the time for action is beneficial\u2026 it provides the maximum amount of time to think, plan, and determine alternatives.\n\nWe live in a world that is constantly changing and evolving, as such the best time to execute is often \u2018just in time\u2019. By delaying decisions until the last possible moment we can arrive at solutions that address the current reality more effectively, resulting in better outcomes.\nProcrastination isn\u2019t just useful from a project management perspective, however. It can also be useful for allowing your mind the space to wander, make new discoveries and find creative connections. By embracing structured procrastination we can \u2018prime the brain\u2019.\nAs James Webb Young argues, in A Technique for Producing Ideas, all ideas are made of other ideas and the more we fill our minds with other stimuli, the greater the number of creative opportunities we can uncover and bring to life.\nBy late binding, and availing of a lack of time pressure, you allow the mind space to breathe, enabling you to uncover elements that are important to the problem you\u2019re working on and, perhaps, discover other elements that will serve you well in future tasks.\nWhen setting forth upon the process of writing this article I consciously set aside time to explore. I allowed myself the opportunity to read, taking in new material, safe in the knowledge that what I discovered \u2013 if not useful for this article \u2013 would serve me well in the future. \nRon Burgundy summarises this neatly:\n\nProcrastinator? No. I just wait until the last second to do my work because I will be older, therefore wiser.\n\nAn \u2018older, therefore wiser\u2019 mind is a good thing. We\u2019re incredibly fortunate to live in a world where we have a wealth of information at our fingertips. Don\u2019t waste the opportunity to learn, rather embrace that opportunity. Make the most of every second to fill your mind with new material, the rewards will be ample.\nDeadlines are deadlines, however, and deadlines offer us the opportunity to focus our minds, bringing together the pieces of the puzzle we found during our structured procrastination.\nLike everyone I\u2019ll hear a tiny, but insistent voice in my head that starts to rise when the deadline is approaching. The older you get, the closer to the deadline that voice starts to chirp up.\nAt this point we need to focus.\nFocused Finishing\nWe live in an age of constant distraction. Smartphones are both a blessing and a curse, they keep us connected, but if we\u2019re not careful the constant connection they provide can interrupt our flow.\nWhen a deadline is accelerating towards us it\u2019s important to set aside the distractions and carve out a space where we can work in a clear and focused manner.\nWhen it\u2019s time to finish, it\u2019s important to avoid context switching and focus. All those micro-interactions throughout the day \u2013 triaging your emails, checking social media and browsing the web \u2013 can get in the way of you hitting your deadline. At this point, they\u2019re distractions.\nChunking tasks and managing when they\u2019re scheduled can improve your productivity by a surprising order of magnitude. At this point it\u2019s important to remove distractions which result in \u2018attention residue\u2019, where your mind is unable to focus on the current task, due to the mental residue of other, unrelated tasks.\nBy focusing on a single task in a focused manner, it\u2019s possible to minimise the negative impact of attention residue, allowing you to maximise your performance on the task at hand.\nCal Newport explores this in his excellent book, Deep Work, which I would highly recommend reading. As he puts it:\n\nEfforts to deepen your focus will struggle if you don\u2019t simultaneously wean your mind from a dependence on distraction.\n\nTo help you focus on finishing it\u2019s helpful to set up a work-focused environment that is purposefully free from distractions. There\u2019s a time and a place for structured procrastination, but \u2013 equally \u2013 there\u2019s a time and a place for focused finishing.\nThe French term \u2018mise en place\u2019 is drawn from the world of fine cuisine \u2013 I discovered it when I was procrastinating \u2013 and it\u2019s applicable in this context. The term translates as \u2018putting in place\u2019 or \u2018everything in its place\u2019 and it refers to the process of getting the workplace ready before cooking.\nJust like a professional chef organises their utensils and arranges their ingredients, so too can you.\nThanks to the magic of multiple users on computers, it\u2019s possible to create a separate user on your computer \u2013 without access to email and other social tools \u2013 so that you can switch to that account when you need to focus and hit the deadline.\nAnother, less technical way of achieving the same result \u2013 depending, of course, upon your line of work \u2013 is to close your computer and find some non-digital, unconnected space to work in.\nThe goal is to carve out time to focus so you can finish. As Newport states:\n\nIf you don\u2019t produce, you won\u2019t thrive \u2013 no matter how skilled or talented you are.\n\nProcrastination is fine, but only if it\u2019s accompanied by finishing. Create the space to finish and you\u2019ll enjoy the best of both worlds.\nIn closing\u2026\nThere is a time and a place for everything: there is a time to procrastinate, and a time to focus. To truly reap the rewards of time, the mind needs both.\nBy combining the processes of \u2018Structured Procrastination\u2019 and \u2018Focused Finishing\u2019 we can make the most of our 86,400 seconds a day, ensuring we are constantly primed to make new discoveries, but just as importantly, ensuring we hit the all-important deadlines.\nMake the most of your time, you only get so much. Use every second productively and you\u2019ll be thankful that you did. Don\u2019t waste your time, once it\u2019s gone, it\u2019s gone\u2026 and you can never get it back.", "year": "2016", "author": "Christopher Murphy", "author_slug": "christophermurphy", "published": "2016-12-21T00:00:00+00:00", "url": "https://24ways.org/2016/stretching-time/", "topic": "process"}
{"rowid": 304, "title": "Five Lessons From My First 18 Months as a Dev", "contents": "I recently moved from Sydney to London to start a dream job with Twitter as a software engineer. A software engineer! Who would have thought.\nHaving started my career as a journalist, the title \u2018engineer\u2019 is very strange to me. The notion of writing in first person is also very strange. Journalists are taught to be objective, invisible, to keep yourself out of the story. And here I am writing about myself on a public platform. Cringe.\nSince I started learning to code I\u2019ve often felt compelled to write about my experience. I want to share my excitement and struggles with the world! But as a junior I\u2019ve been held back by thoughts like \u2018whatever you have to say won\u2019t be technical enough\u2019, \u2018any time spent writing a blog would be better spent writing code\u2019, \u2018blogging is narcissistic\u2019, etc.\u00a0\nWell, I\u2019ve been told that your thirties are the years where you stop caring so much about what other people think. And I\u2019m almost 30. So here goes!\nThese are five key lessons from my first year and a half in tech:\nDeployments should delight, not dread \n\nLesson #1: Making your deployment process as simple as possible is worth the investment.\n\nIn my first dev job, I dreaded deployments. We would deploy every Sunday night at 8pm. Preparation would begin the Friday before. A nominated deployment manager would spend half a day tagging master, generating scripts, writing documentation and raising JIRAs. The only fun part was choosing a train gif to post in HipChat: \u2018All aboard! The deployment train leaves in 3, 2, 1\u2026\u201d\n\nWhen Sunday night came around, at least one person from every squad would need to be online to conduct smoke tests. Most times, the deployments would succeed. Other times they would fail. Regardless, deployments ate into people\u2019s weekend time\u200a\u2014\u200aand they were intense. Devs would rush to have their code approved before the Friday cutoff. Deployment managers who were new to the process would fear making a mistake.\u00a0\nThe team knew deployments were a problem. They were constantly striving to improve them. And what I\u2019ve learnt from Twitter is that when they do, their lives will be bliss.\nTweetDeck\u2019s deployment process fills me with joy and delight. It\u2019s quick, easy and stress free. In fact, it\u2019s so easy I deployed code on my first day in the job! Anyone can deploy, at any time of day, with a single command. Rollbacks are just as simple. There\u2019s no rush to make the deployment train. No manual preparation. No fuss. Value\u200a\u2014\u200awhether in the form of big new features, simple UI improvements or even production bug fixes\u200a\u2014\u200acan be shipped in an instant. The team assures me the process wasn\u2019t always like this. They invested lots of time in making their deployments better. And it\u2019s clearly paid off.\nCode reviews need love, time and acceptance \n\nLesson #2: Code reviews are a three-way gift. Every time I review someone else\u2019s code, I help them, the team and myself.\n\nCode reviews were another pain point in my previous job. And to be honest, I was part of the problem. I would raise code reviews that were far too big. They would take days, sometimes weeks, to get merged. One of my reviews had 96 comments! I would rarely review other people\u2019s code because I felt too junior, like my review didn\u2019t carry any weight.\u00a0\nThe review process itself was also tiring, and was often raised in retrospectives as being slow. In order for code to be merged it needed to have ticks of approval from two developers and a third tick from a peer tester. It was the responsibility of the author to assign the reviewers and tester. It was felt that if it was left to team members to assign themselves to reviews, the \u201csomeone else will do it\u201d mentality would kick in, and nothing would get done.\nAt TweetDeck, no-one is specifically assigned to reviews. Instead, when a review is raised, the entire team is notified. Without fail, someone will jump on it. Reviews are seen as blocking. They\u2019re seen to be equally, if not more important, than your own work. I haven\u2019t seen a review sit for longer than a few hours without comments.\u00a0\nWe also don\u2019t work on branches. We push single commits for review, which are then merged to master. This forces the team to work in small, incremental changes. If a review is too big, or if it\u2019s going to take up more than an hour of someone\u2019s time, it will be sent back.\nWhat I\u2019ve learnt so far at Twitter is that code reviews must be small. They must take priority. And they must be a team effort. Being a new starter is no \u201cget out of jail free card\u201d. In fact, it\u2019s even more of a reason to be reviewing code. Reviews are a great way to learn, get across the product and see different programming styles. If you\u2019re like me, and find code reviews daunting, ask to pair with a senior until you feel more confident. I recently paired with my mentor at Twitter and found it really helpful.\nGet friendly with feature flagging \n\nLesson #3: Feature flagging gives you complete control over how you build and release a project.\n\nSay you\u2019re implementing a new feature. It\u2019s going to take a few weeks to complete. You\u2019ll complete the feature in small, incremental changes. At what point do these changes get merged to master? At what point do they get deployed? Do you start at the back end and finish with the UI, so the user won\u2019t see the changes until they\u2019re ready? With feature flagging\u200a\u2014\u200ait doesn\u2019t matter. In fact, with feature flagging, by the time you are ready to release your feature, it\u2019s already deployed, sitting happily in master with the rest of your codebase.\u00a0\nA feature flag is a boolean value that gets wrapped around the code relating to the thing you\u2019re working on. The code will only be executed if the value is true.\nif (TD.decider.get(\u2018new_feature\u2019)) {\n //code for new feature goes here\n}\nIn my first dev job, I deployed a navigation link to the feature I\u2019d been working on, making it visible in the product, even though the feature wasn\u2019t ready. \u201cWhy didn\u2019t you use a feature flag?\u201d a senior dev asked me. An honest response would have been: \u201cBecause they\u2019re confusing to implement and I don\u2019t understand the benefits of using them.\u201d The fix had to wait until the next deployment.\nThe best thing about feature flagging at TweetDeck is that there is no need to deploy to turn on or off a feature. We set the status of the feature via an interface called Deckcider, and the code makes regular API requests to get the status.\u00a0\nAt TweetDeck we are also able to roll our features out progressively. The first rollout might be to a staging environment. Then to employees only. Then to 10 per cent of users, 20 per cent, 30 per cent, and so on. A gradual rollout allows you to monitor for bugs and unexpected behaviour, before releasing the feature to the entire user base.\nSometimes a piece of work requires changes to existing business logic. So the code might look more like this:\nif (TD.decider.get(\u2018change_to_existing_feature\u2019)) {\n //new logic goes here\n} else {\n //old logic goes here\n}\nThis seems messy, right? Riddling your code with if else statements to determine which path of logic should be executed, or which version of the UI should be displayed. But at Twitter, this is embraced. You can always clean up the code once a feature is turned on. This isn\u2019t essential, though. At least not in the early days. When a cheeky bug is discovered, having the flag in place allows the feature to be very quickly turned off again. \nLet data and experimentation drive development \n\nLesson #4: Use data to determine the direction of your product and measure its success.\n\nThe first company I worked for placed a huge amount of emphasis on data-driven decision making. If we had an idea, or if we wanted to make a change, we were encouraged to \u201cbring data\u201d to show why it was necessary. \u201cWithout data, you\u2019re just another person with an opinion,\u201d the chief data scientist would say. This attitude helped to ensure we were building the right things for our customers. Instead of just plucking a new feature out of thin air, it was chosen based on data that reflected its need.\nBut how do you design that feature? How do you know that the design you choose will have the desired impact? That\u2019s where experiments come into play.\u00a0\nAt TweetDeck we make UI changes that we hope will delight our users. But the assumptions we make about our users are often wrong. Our front-end team recently sat in a room and tried to guess which UIs from A/B tests had produced better results. Half the room guessed incorrectly every time.\nWe can\u2019t assume a change we want to make will have the impact we expect. So we run an experiment. Here\u2019s how it works. Users are placed into buckets. One bucket of users will have access to the new feature, the other won\u2019t. We hypothesise that the bucket exposed to the new feature will have better results. The beauty of running an experiment is that we\u2019ll know for sure. Instead of blindly releasing the feature to all users without knowing its impact, once the experiment has run its course, we\u2019ll have the data to make decisions accordingly.\nHire the developer, not the degree\n\nLesson #5: Testing candidates on real world problems will allow applicants from all backgrounds to shine.\n\nSurely, a company like Twitter would give their applicants insanely difficult code tests, and the toughest technical questions, that only the cleverest CS graduates could pass, I told myself when applying for the job. Lucky for me, this wasn\u2019t the case. The process was insanely difficult\u2014don\u2019t get me wrong\u2014but the team at TweetDeck gave me real world problems to solve.\nThe first code test involved bug fixes, performance and testing. The second involved DOM traversal and manipulation. Instead of being put on the spot in a room with a whiteboard and pen I was given a task, access to the internet, and time to work on it. Similarly, in my technical interviews, I was asked to pair program on real world problems that I was likely to face on the job.\nIn one of my phone screenings I was told Twitter wanted to increase diversity in its teams. Not just gender diversity, but also diversity of experience and background. Six months later, with a bunch of new hires, team lead Tom Ashworth says TweetDeck has the most diverse team it\u2019s ever had. \u201cWe designed an interview process that gave us a way to simulate the actual job,\u201d he said. \u201cIt\u2019s not about testing whether you learnt an algorithm in school.\u201d\nIs this lowering the bar? No. The bar is whether a candidate has the ability to solve problems they are likely to face on the job. I recently spoke to a longstanding Atlassian engineer who said they hadn\u2019t seen an algorithm in their seven years at the company.\nThese days, only about 50 per cent of developers have computer science degrees. The majority of developers are self taught, learn on the job or via online courses. If you want to increase diversity in your engineering team, ensure your interview process isn\u2019t excluding these people.", "year": "2016", "author": "Amy Simmons", "author_slug": "amysimmons", "published": "2016-12-20T00:00:00+00:00", "url": "https://24ways.org/2016/my-first-18-months-as-a-dev/", "topic": "process"}
{"rowid": 310, "title": "Fairytale of new Promise", "contents": "There are only four good Christmas songs.\nI know, yeah, JavaScript or whatever. We\u2019ll get to that in a minute, I promise.\nFirst\u2014and I cannot stress this enough\u2014 there are four good Christmas songs. You\u2019re free to disagree with me here, of course, but please try to understand that you will be wrong.\nThey don\u2019t all have the most safe-for-work titles; I can\u2019t list all of them here, but if you choose to let your fingers do the walkin\u2019 to your nearest search engine, I will say that one was released by the band FEAR way back in 1982 and one was on Run the Jewels\u2019 self-titled debut album. The lyrics are a hell of a lot worse than the titles, so maybe wait until you get home from work before you queue them up. Wear headphones, if you\u2019ve got thin walls.\nFor my money, though, the two I can reference by name are the top of that small heap: Tom Waits\u2019 Christmas Card from a Hooker in Minneapolis, and The Pogues\u2019 Fairytale of New York. The former once held the honor of being the only good Christmas song\u2014about which which I was also unequivocally correct, right up until I changed my mind. It\u2019s not the song up for discussion today, but feel free to familiarize yourself just the same\u2014I\u2019ll wait.\nFairytale of New York\u2014the top of the list\u2014starts out by hinting at some pretty standard holiday fare; dreams and cheer and whatnot. Typical seasonal stuff, so long as you ignore that the story seems to be recounted as a drunken flashback in a jail cell. You can probably make a few guesses at the underlying spirit of the song based on that framing: following a lucky break, our bright-eyed protagonists move to New York in search of fame and fortune, only to quickly descend into bad decisions, name-calling, and vaguely festive chaos.\nThis song speaks to me on a couple of levels, not the least of which is as a retelling of my day-to-day interactions with JavaScript. Each day\u2019s melody might vary a little bit, granted, but the lyrics almost always follow a pretty clear arc toward \u201cPARENTAL ADVISORY: EXPLICIT CONTENT.\u201d You might have heard a similar tune yourself; it goes a little somethin\u2019 like setTimeout(function() { console.log( \"this should be happening last\" ); }, 1000); . Callbacks are calling callbacks calling callbacks and something is happening somewhere, as the JavaScript interpreter plods through our code start-to-finish, line-by-line, step-by-step. If we need to take actions based on the results of something that could take its sweet time resolving, well, we\u2019d better fiddle with the order of things to make sure those actions don\u2019t happen too soon.\n\u201cBut I can see a better time,\u201d as the song says, \u201cwhen all our dreams come true.\u201d So, with that Pogues brand of holiday spirit squarely in mind\u2014by which I mean that your humble narrator is almost certainly drunk, and may be incarcerated at the time of publication\u2014gather \u2019round for a story of hope, of hardships, of semi-asynchronous JavaScript programming, and ultimately: of Promise unfulfilled.\nThe Main Thread\nJavaScript is single-minded, in a manner of speaking. Anything we tell the JavaScript runtime to do goes into a single-file queue; you\u2019ll see it referred to as the \u201cmain thread,\u201d or \u201cUI thread.\u201d That thread can be shared by a number of critical browser processes, like rendering and re-rendering parts of the page, and user interactions ranging from the simple\u2014say, highlighting text\u2014to the more complex\u2014interacting with form elements.\nIf that sounds a little scary to you, well, that\u2019s because it is. The more complex our scripts, the more we\u2019re cramming into that single-file main thread, to be processed along with\u2014say\u2014some of our CSS animations. Too much JavaScript clogging up the main thread means a lot of user-facing performance jankiness. Getting away from that single thread is a big part of all the excitement around Web Workers, which allow us to offload entire scripts into their own dedicated background threads\u2014though not without limitations of their own. Outside of Web Workers, that everything-thread is the only game in town: scripts executed one thing at a time, functions calling functions calling functions, taking numbers and crowding up the same deli counter as a user\u2019s interactions\u2014which, in this already strained metaphor, would be ham, I guess?\nAsynchronous JavaScript\nNow, those queued actions may include asynchronous things. For example: AJAX callbacks, setTimeout/setInterval, and addEventListener won\u2019t block the main thread while we\u2019re waiting for a request to come back, a timer to tick away, or an event to trigger. Once those things do kick in, though, the actions they\u2019re meant to perform will get shuffled right back into that single-thread queue.\nThere are a couple of places you might have written asynchronously-fired JavaScript, even if you\u2019re not super familiar with the overarching concept: XMLHttpRequest\u2014\u201cAJAX,\u201d if ya nasty\u2014or just kicking off a function once a user triggers a click or mouseenter event. Event-driven development is writ a little larger, with the overall flow of the script dictated by events, both internal and external. Writing event-driven JavaScript applications is a step in the right direction for sure\u2014it won\u2019t cure what ails the main thread, but it does work with the medium in a reasonable way. Event-driven development allows us to manage our use of the main thread in a way that makes sense. If any of this rings a bell for you, the motivation for Promises should feel familiar.\nFor example, a custom init event might kick things off, and fire a create event that applies our classes and restructures our markup which, on completion, fires a bindEvents event to handle all the event listeners for user interaction. There might not sound like much difference between that and one big function that kicks off, manipulates the DOM, and binds our events line-by-line\u2014but in a script of sufficient size and complexity we\u2019re not only provided with a decoupled flow through the script, but obvious touchpoints for future updates and a predictable structure for ongoing maintenance. \nThis pattern falls apart a little where we were still creating, binding, and listening for events in the same top-to-bottom, one-item-at-a-time way\u2014we had to set a listener on a given object before the event fires, or nothing would happen:\n// Create the event:\nvar event = document.createEvent( \"Event\" );\n\n// Name the event:\nevent.initEvent( \"doTheStuff\", true, true );\n\n// Listen for the custom `doTheStuff` event on `window`:\nwindow.addEventListener( \"doTheStuff\", initializeEverything );\n\n// Fire the custom event\nwindow.dispatchEvent( event );\nThis example is a little contrived, and this stuff is a lot more manageable for sure with the addition of a framework, but that\u2019s the basic gist: create and name the event, add a listener for the event, and\u2014after setting our listener\u2014dispatch the event.\nEvents and callbacks aren\u2019t the only game in town for weaving our way in and out of the main thread, though\u2014at least, not anymore. \nPromises\nA Promise is, at the risk of sounding sentimental, pure potential\u2014an empty container into which a value eventually results. A Promise can exist in several states: \u201cpending,\u201d while the computation they contain is being performed or \u201cresolved\u201d once that computation is complete. Once resolved, a Promise is \u201cfulfilled\u201d if it gave us back something we expect, or \u201crejected\u201d if it didn\u2019t.\nThe Promise constructor accepts a callback with two arguments: resolve and reject. We perform an action\u2014asynchronous or otherwise\u2014within that callback. If everything in there has gone according to plan, we call resolve. If something has gone awry, we call reject\u2014with an error, conventionally. To illustrate, let\u2019s tack something together with a pretty decent chance of doing what we don\u2019t want: a promise meant only to give us the number 1, but has a chance of giving us back a 2. No reasonable person would ever do this, of course, but I wouldn\u2019t necessarily put it past me.\nvar promisedOne = new Promise( function( resolve, reject ) {\n var coinToss = Math.floor( Math.random() * 2 ) + 1;\n\n if( coinToss === 1 ) {\n resolve( coinToss );\n } else {\n reject( new Error( \"That ain\u2019t a one.\" ) );\n }\n});\nThere\u2019s nothing too surprising in there, after you boil it all down. It\u2019s a little return-y, with the exception that we\u2019re flagging results as \u201cas expected\u201d or \u201csomething went wrong.\u201d\nTapping into that Promise uses another new keyword: then\u2014and as someone who attempts to make sense of JavaScript by breaking it down to plain ol\u2019 human-language, I\u2019m a big fan of this syntax. then is tacked onto our Promise identifier, and does just what it says on the tin: once the Promise is resolved, then do one of two things, both supplied as callbacks: the first in the case of a fulfilled promise, and the second in the case of a rejected one. Those two callbacks will have, as arguments, the results we specified with resolve orreject, respectively. It sounds like a lot in prose, but in code it\u2019s a pretty simple pattern:\npromisedOne.then( function( result ) {\n console.log( result );\n}, function( error ) {\n console.error( error );\n});\nIf you\u2019ve spent any time working with AJAX\u2014jQuery-wise, in particular\u2014you\u2019ve seen something like this pattern before: a success callback and an error callback. The state of a promise, once fulfilled or rejected, cannot be changed\u2014any reference we make to promisedOne will have a single, fixed result.\nIt may not look like too much the way I\u2019m using it here, but it\u2019s powerful stuff\u2014a pattern for asynchronously resolving anything. I\u2019ve recently used Promises alongside a script that emulates Font Load Events, to apply webfonts asynchronously and avoid a potential performance hit. Font Face Observer allows us to, as the name implies, determine when the files referenced by our @font-face rules have finished loading. \nvar fontObserver = new FontFaceObserver( \"Fancy Font\" );\n\nfontObserver.check().then(function() {\n document.documentElement.className += \" fonts-loaded\";\n}, function( error ) {\n console.error( error );\n});\nfontObserver.check() gives us back a Promise, allowing us to chain on a then containing our callbacks for success and failure. We use the fulfilled callback to bolt a class onto the page once the font file has been fully transferred. We don\u2019t bother including an argument in the first function, since we don\u2019t care about the result itself so much as we care that the promise resolved without error\u2014we\u2019re not doing anything with the resolved value, just adding a class to the page. We do include the error argument, since we\u2019ll want to know what happened should something go wrong.\nNow, this isn\u2019t the tidiest syntax around\u2014at least to my eyes\u2014with those two functions just kinda floating in a then. Luckily there\u2019s an similar alternative syntax; one that I find a bit easier to parse at-a-glance:\nfontObserver.check()\n .then(function() {\n document.documentElement.className += \" fonts-loaded\";\n })\n .catch(function( error ) {\n console.log( error );\n });\nThe first callback inside then provides us with our success state, while the catch provides us with a single, explicit \u201csomething went wrong\u201d callback. The two syntaxes aren\u2019t completely identical in all situations, but for a simple case like this, I find it a little neater.\nThe Common Thread\nI guess I still owe you an explanation, huh. Not about the JavaScript-whatever; I think I\u2019ve explained that plenty. No, I mean Fairytale of New York, and why it\u2019s perched up there at the top of the four (4) song heap.\nFairytale is a sad song, ostensibly. If you follow the main thread\u2014start to finish, line-by-line, step by step\u2014 Fairytale is a sad song. And I can see you out there, visions of Die Hard dancing in your heads: \u201cbut is it a Christmas song?\u201d\nWell, for my money, nothing says \u201cholidays\u201d quite like unreliable narration.\nShane MacGowan, the song\u2019s author, has placed the first verse about \u201cChristmas Eve in the drunk tank\u201d as happening right after the \u201clucky one, came in eighteen-to-one\u201d\u2014not at the chronological end of the story. That means the song might not be mostly drunken flashback, but all of it a single, overarching flashback including a Christmas Eve in protective custody. It could be that the man and woman are, together, recounting times long past\u2014good times and bad times\u2014maybe not even in chronological order. Hell, the \u201cNYPD Choir\u201d mentioned in the chorus? There\u2019s no such thing.\nWe\u2019re not big Christmas folks, my family and I. But just the same, every year, the handful of us get together, and every year\u2014like clockwork\u2014there\u2019s a lull in conversation, there\u2019s a sharp exhale, and Ma says \u201cwe all made it.\u201d Not to a house, not to a dinner, but through another year, to another Christmas. At this point, without fail, someone starts telling a story\u2014and one begets another, and so on. Sometimes the stories are happy, sometimes they\u2019re sad, more often than not they\u2019re both. Some are about things we were lucky to walk away from, some are about a time when another one of us didn\u2019t.\nStart-to-finish, line-by-line, step-by-step, the main thread through the year doesn\u2019t change, and maybe there isn\u2019t a whole lot we can do to change it. But by carefully weaving our way in and out of that thread\u2014stories all out of sync and resolving one way or the other, with the results determined by questionably reliable narrators\u2014we can change the way we interact with it and, little by little, we can start making sense of it.", "year": "2016", "author": "Mat Marquis", "author_slug": "matmarquis", "published": "2016-12-19T00:00:00+00:00", "url": "https://24ways.org/2016/fairytale-of-new-promise/", "topic": "code"}
{"rowid": 294, "title": "New Tricks for an Old Dog", "contents": "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.\nI\u2019ve loved doing this. Everything from writing new documentation, drawing diagrams, and holding technical architecture sessions teaches you something you didn\u2019t know or exposes an area of uncertainty that you can go work on.\nIn 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!\nHow do you do, fellow kids?\nTo start with I\u2019d like to introduce you to our JavaScript framework, Flight. Right now it\u2019s used by twitter.com and TweetDeck although, as a company, Twitter is largely moving to React.\nOver time, as we used Flight for more complex interfaces, we found it wasn\u2019t scaling with us.\nComposing 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\u2019t come built-in to Flight, and it made reusing components a real challenge.\nThere 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\u2019t predict how a component would be built until you opened it.\nMaking matters worse, Flight relied on events to move data around the application. Unfortunately, events aren\u2019t good for giving structure to complex logic. They jump around in a way that\u2019s hard to understand and debug, and force you to search your code for a specific string \u2014 the event name\u201a to figure out what\u2019s going on.\nTo find fixes for these problems, we looked around at other frameworks. We like React for it\u2019s simple, predictable state management and reactive re-render flow, and Elm for bringing strict functional programming to everyone.\nBut 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\u2019ll test it alongside existing code, and how it will affect the size and performance of the application. This all takes time and effort!\nInstead 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.\nBoiled down, what we liked seemed quite simple:\n\nComponent nesting & composition\nEasy, predictable state management\nNormal functions for data manipulation\n\nMaking these ideas applicable to Flight took some time, but we\u2019re 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.\nWhile the specifics of our situation and Flight aren\u2019t really important, this experience taught me something: \n\nDistill good tech into great ideas. You can apply great ideas anywhere.\n\nYou don\u2019t have to use cool kids\u2019 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?\nTimes, they are a changin\u2019\nApart 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.\nGoing 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\u2019s source was encased in AMD boilerplate.\nIn fact, we found ourselves with a mix of both AMD syntaxes:\ndefine([\"lodash\"], function (_) {\n // . . .\n});\n\ndefine(function (require) {\n var _ = require(\"lodash\");\n // . . .\n});\nThis just wouldn\u2019t do. And besides, what we really wanted was CommonJS, or even ES2015 module syntax:\nimport _ from \"lodash\";\nThese days we\u2019re using Babel, Webpack, ES2015 modules and many new language features that make development just\u2026 better. But how did we get there?\nTo explain, I want to introduce you to codemods and jscodeshift.\nA 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(\"...\").\njscodeshift is a toolkit for running automated codemods, where you express a code transformation using code. The automated codemod operates on each file\u2019s syntax tree \u2013 a data-structure representation of the code \u2014 finding and modifying in place as it goes.\nHere\u2019s an example that renames all instances of the variable foo to bar:\nmodule.exports = function (fileInfo, api) {\n return api\n .jscodeshift(fileInfo.source)\n .findVariableDeclarators('foo')\n .renameTo('bar')\n .toSource();\n};\nIt\u2019s a seriously powerful tool, and we\u2019ve used it to write a series of codemods that:\n\nrename modules,\nunify our use of AMD to a single syntax,\ntransition from one testing framework to another, and\nswitch from AMD to CommonJS.\n\nThese changes can be pretty huge and far-reaching. Here\u2019s an example commit from when we switched to CommonJS:\ncommit 8f75de8fd4c702115c7bf58febba1afa96ae52fc\nDate: Tue Jul 12 2016\n\n Run AMD -> CommonJS codemod\n\n 418 files changed, 47550 insertions(+), 48468 deletions(-)\n\nYep, that\u2019s just under 50k lines changed, tested, merged and deployed without any trouble. AMD be gone!\n\nFrom this step-by-step approach, using codemods to incrementally tweak and improve, we extracted a little codemod recipe for making significant, multi-stage changes:\n\nFind all the existing patterns\nChoose the two most similar\nUnify with a codemod\nRepeat.\n\nFor example:\n\nFor module loading, we had 2 competing AMD patterns plus some use of CommonJS\nThe two AMD syntaxes were the most similar\nWe used a codemod to move to unify the AMD patterns\nLater we returned to AMD to convert it to CommonJS\n\nIt\u2019s worked for us, and if you\u2019d like to know more about codemods then check out Evolving Complex Systems Incrementally by Facebook engineer, Christoph Pojer.\nWelcome aboard!\nAs 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.\nInspired by Amy\u2019s 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.\nJoining 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!\nAnd as you build up an onboarding process, you\u2019ll create things that are useful for more than just new hires; it\u2019ll force you to write documentation, for example, in a way that\u2019s 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.\nThis is something that\u2019s taken for granted in open source, but somehow I think we forget about it in big companies.\nAfter all, better documentation is just a good thing. You will forget things from time to time, and you\u2019d be surprised how often the \u201cbeginner\u201d docs help!\nFor TweetDeck, we put together system and architecture diagrams, and one-pager explanations of important concepts:\n\nWhat are our dependencies?\nWhere are the potential points of failure?\nWhere does authentication live? Storage? Caching?\nWho owns \u201cX\u201d?\n\n\nOf 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.\nTo address this, we\u2019ve thought hard about our knowledge sharing practices across the whole team. For example, we completely changed the way we do code review.\nIn 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\u2019s work. But, if you\u2019re not doing it, here\u2019s my suggestion for getting started:\n\nEvery pull request gets a +1 from someone else.\n\nThat\u2019s all \u2014 it\u2019s very light-weight and easy. Just ask someone to have a quick look over your code before it goes into master.\nAt 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:\n\nDon\u2019t review for more than hour 1\nKeep reviews smaller than ~400 lines 2\nCode review your own code first 2\n\nAfter 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\u2019s put code up for a review, that review is blocking them doing other work. It\u2019s your job to unblock them.\nOn TweetDeck, we actually try to keep reviews under 250 lines. It doesn\u2019t 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.\nBut the most important thing I\u2019ve 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\u2019s: with fresh, critical eyes, after a break, using a dedicated code review tool.\nIt\u2019s amazing what you can spot when you put a new in a new interface around code you\u2019ve been staring at for hours!\nAnd yes, this list features science. The data backs up these conclusions, and if you\u2019d 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\u2019s ace.\nFor more dedicated information sharing, we\u2019ve 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\u2019s someone else\u2019s turn. Giving everyone a chance to speak, and encouraging a wide range of topics, is starting to produce great results.\nIf you\u2019d 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 \u2014 thanks to James for this idea. And guess what\u2026 your onboarding architecture diagrams will help (and benefit from) this!\nMore, please!\nThere\u2019s 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.\nAnd finally, thanks to Amy for proof reading this and to Passy for feedback on the original talk.\n\n\n\n\nDunsmore et al. 2000. Object-Oriented Inspection in the Face of Delocalisation. Beverly, MA: SmartBear Software.\u00a0\u21a9\n\n\nCohen, Jason. 2006. Best Kept Secrets of Peer Code Review. Proceedings of the 22nd ICSE 2000: 467-476.\u00a0\u21a9 \u21a9", "year": "2016", "author": "Tom Ashworth", "author_slug": "tomashworth", "published": "2016-12-18T00:00:00+00:00", "url": "https://24ways.org/2016/new-tricks-for-an-old-dog/", "topic": "code"}
{"rowid": 289, "title": "Front-End Developers Are Information Architects Too", "contents": "The theme of this year\u2019s World IA Day was \u201cInformation Everywhere, Architects Everywhere\u201d. This article isn\u2019t about what you may consider an information architect to be: someone in the user-experience field, who maybe studied library science, and who talks about taxonomies. This is about a realisation I had a couple of years ago when I started to run an increasing amount of usability-testing sessions with people who have disabilities: that the structure, labelling, and connections that can be made in front-end code is information architecture. People\u2019s ability to be successful online is unequivocally connected to the quality of the code that is written.\nPlaces made of information\nIn information architecture we talk about creating places made of information. These places are made of ones and zeros, but we talk about them as physical structures. We talk about going onto a social media platform, posting in blogs, getting locked out of an environment, and building applications. In 2002, Andrew Hinton stated:\n\nPeople live and work in these structures, just as they live and work in their homes, offices, factories and malls. These places are not virtual: they are as real as our own minds.\n25 Theses\n\nWe\u2019re creating structures which people rely on for significant parts of their lives, so it\u2019s critical that we carry out our work responsibly. This means we must use our construction materials correctly. Luckily, our most important material, HTML, has a well-documented specification which tells us how to build robust and accessible places. What is most important, I believe, is to understand the semantics of HTML.\nSemantics\nThe word \u201csemantic\u201d has its origin in Greek words meaning \u201csignificant\u201d, \u201csignify\u201d, and \u201csign\u201d. In the physical world, a structure can have semantic qualities that tell us something about it. For example, the stunning Westminster Abbey inspires awe and signifies much about the intent and purpose of the structure. The building\u2019s size; the quality of the stone work; the massive, detailed stained glass: these are all signs that this is a building meant for something the creators deemed important. Alternatively consider a set of large, clean, well-positioned, well-lit doors on the ground floor of an office block: they don\u2019t need an \u201centrance\u201d sign to communicate their use and to stop people trying to use a nearby fire exit to get into the building. The design of the doors signify their usage. Sometimes a more literal and less awe-inspiring approach to communicating a building\u2019s purpose happens, but the affect is similar: the building is signifying something about its purpose.\nHTML has over 115 elements, many of which have semantics to signify structure and affordance to people, browsers, and assistive technology. The HTML 5.1 specification mentions semantics, stating:\n\nElements, attributes, and attribute values in HTML are defined \u2026 to have certain meanings (semantics). For example, the element represents an ordered list, and the lang attribute represents the language of the content.\nHTML 5.1 Semantics, structure, and APIs of HTML documents\n\nHTML\u2019s baked-in semantics means that developers can architect their code to signify structure, create relationships between elements, and label content so people can understand what they\u2019re interacting with. Structuring and labelling information to make it available, usable, and understandable to people is what an information architect does. It\u2019s also what a front-end developer does, whether they realise it or not.\nA brief introduction to information architecture\nWe\u2019re going to start by looking at what an information architect is. There are many definitions, and I\u2019m going to quote Richard Saul Wurman, who is widely regarded as the father of information architecture. In 1976 he said an information architect is:\n\nthe individual who organizes the patterns inherent in data, making the complex clear; a person who creates the structure or map of information which allows others to find their personal paths to knowledge; the emerging 21st century professional occupation addressing the needs of the age focused upon clarity, human understanding, and the science of the organization of information.\nOf Patterns And Structures\n\nTo me, this clearly defines any developer who creates code that a browser, or other user agent (for example, a screen reader), uses to create a structured, navigable place for people.\nJust as there are many definitions of what an information architect is, there are for information architecture itself. I\u2019m going to use the definition from the fourth edition of Information Architecture For The World Wide Web, in which the authors define it as:\nThe structural design of shared information environments.\nThe synthesis of organization, labeling, search, and navigation systems within digital, physical, and cross-channel ecosystems.\nThe art and science of shaping information products and experiences to support usability, findability, and understanding.\nInformation Architecture For The World Wide Web, 4th Edition\nTo me, this describes front-end development. Done properly, there is an art to creating robust, accessible, usable, and findable spaces that delight all our users. For example, at 2015\u2019s State Of The Browser conference, Edd Sowden talked about the accessibility of s. He discovered that by simply not using the semantically-correct element to mark up headings, in some situations browsers will decide that a is being used for layout and essentially make it invisible to assistive technology. Another example of how coding practices can affect the usability and findability of content is shown by L\u00e9onie Watson in her How ARIA landmark roles help screen reader users video. By using ARIA landmark roles, people who use screen readers are quickly able to identify and jump to common parts of a web page.\nOur definitions of information architects and information architecture mention patterns, rules, organisation, labelling, structure, and relationships. There are numerous different models for how these elements get boiled down to their fundamentals. In his Understanding Context book, Andrew Hinton calls them Labels, Relationships, and Rules; Jorge Arango calls them Links, Nodes, And Order; and Dan Klyn uses Ontology, Taxonomy, and Choreography, which is the one we\u2019re going to use. Dan defines these terms as:\nOntology\nThe definition and articulation of the rules and patterns that govern the meaning of what we intend to communicate.\nWhat we mean when we say what we say.\nTaxonomy\nThe arrangements of the parts. Developing systems and structures for what everything\u2019s called, where everything\u2019s sorted, and the relationships between labels and categories\nChoreography\nRules for interaction among the parts. The structures it creates foster specific types of movement and interaction; anticipating the way users and information want to flow and making affordance for change over time.\n\nWe now have definitions of an information architect, information architecture, and a model of the elements of information architecture. But is writing HTML really creating information or is it just wrangling data and metadata? When does data turn into information? In his book Managing For The Future Peter Drucker states:\n\n\u2026 data is not information. Information is data endowed with relevance and purpose.\nManaging For The Future\n\nIf we use the correct semantic element to mark up content then we\u2019re developing with purpose and creating relevance. For example, if we follow the advice of the HTML 5.1 specification and mark up headings using heading rank instead of the outline algorithm, we\u2019re creating a structure where the depth of one heading is relevant to the previous one. Architected correctly, an element should be relevant to its parent, which should be the . By following the HTML specification we can create a structured, searchable, labeled document that will hopefully be relevant to what our users need to be successful. If you\u2019ve never used a screen reader, you might be wondering how the headings on a page are searchable. Screen readers give users the ability to interact with headings in a couple of ways:\n\nby creating a list of headings so users can quickly scan the page for information\nby using a keyboard command to cycle through one heading at a time\n\nIf we had a document for Christmas Day TV we might structure it something like this:\nChristmas Day TV schedule \n BBC1 \n Morning \n Evening \n BBC2 \n Morning \n Evening \n ITV \n Morning \n Evening \n Channel 4 \n Morning \n Evening \nIf I use VoiceOver to generate a list of headings, I get this:\n\nOnce I have that list I can use keyboard commands to filter the list based on the heading level. For example, I can press 2 to hear just the s:\n\nIf we hadn\u2019t used headings, of if we\u2019d nested them incorrectly, our users would be frustrated.\nPutting this together\nLet\u2019s put this together with an example of a button that, when pressed, toggles the appearance of a panel of links. There are numerous ways we could create a button on a web page, but the best way is to just use a . Every browser understands what a is, how it works, and what keyboard shortcuts should be used with them. The HTML specification for the element says:\n\nThe element represents a button labeled by its contents.\n\nThe contents that a can have include the type attribute, any relevant ARIA attributes, and the actual text label that the user sees. This information is more important than the visual design: it doesn\u2019t matter how beautiful or obtuse the design is, if the underlying code is non-semantic and poorly labelled, people are going to struggle to use it. Here are three buttons, each created with the same HTML but with different designs:\n\nRegardless of what they look like, because we\u2019ve used semantic HTML instead of a bunch of meaningless s or
s, people who use assistive technology are going to benefit. Out of the box, without any extra development effort, a is accessible and usable with a keyboard. We don\u2019t have to write event handlers to listen for people pressing the Enter key or the space bar, which we would have to do if we\u2019d faked a button with non-semantic elements. Our can also be quickly findable: for example, in the same way it\u2019s possible to create a list of headings with a screen reader, I can also create a list of form elements and then quickly jump to the one I want.\nNow we have our , let\u2019s add the panel we\u2019re toggling the appearance of. Here\u2019s our code:\nSettings \n\n\nThere\u2019s quite a bit going on here. We\u2019re using the:\n\naria-controls attribute to architect a connection between the element and the panel whose appearance it controls. When some assistive technology, for example the JAWS screen reader, encounters an element with aria-controls it audibly tells a user about the controlled expanded element and gives them the ability to move focus to it.\naria-expanded attribute to denote whether the panel is visible or not. We toggle this value using JavaScript to true when the panel is visible and false when it\u2019s not. This important attribute tells people who use screen readers about the state of the elements they\u2019re interacting with. For example, VoiceOver announces Settings expanded button when the panel is visible and Settings collapsed button when it\u2019s hidden.\naria-labelledby attribute to give the list a title of \u201cSettings\u201d. This can benefit some users of assistive technology. For example, screen readers can cycle through all the lists on a page, so being able to title them can improve findability. Being able to hear list Settings three items is, I\u2019d argue, more useful than list three items. By doing this we\u2019re supporting usability and findability.\n element to contain our list of links in our panel.\n\nLet\u2019s look at the choice of to contain our settings choices. Firstly, our settings are related items, so they belong in a structure that semantically groups things. This is something that a list can do that other elements or patterns can\u2019t. This pattern, for example, isn\u2019t semantic and has no structure:\n\n\n\nAll we have there is three elements next to each other on the screen and in the DOM. That is not robust code that signifies anything.\nWhy are we using an unordered list as opposed to an ordered list or a definition list? A quick look at the HTML specification tells us why:\n\nThe element represents a list of items, where the order of the items is not important \u2014 that is, where changing the order would not materially change the meaning of the document.\nThe HTML 5.1 specification\u2019s description of the element\n\nWill the meaning of our document materially change if we moved the order of our links around? Nope. Therefore, I\u2019d argue, we\u2019ve used the correct element to structure our content.\nThese coding decisions are information architecture\nI believe that what we\u2019ve done here is pure information architecture. Going back to Dan Klyn\u2019s model, we\u2019ve practiced ontology by looking at the meaning of what we\u2019re intending to communicate:\n\nwe want to communicate there is an interactive element that toggles the appearance of an element on a page so we\u2019ve used one, a , with those semantics.\nprogrammatically we\u2019ve used the type='button' attribute to signify that the button isn\u2019t a menu, reset, or submit element.\nvisually we\u2019ve designed our look like something that can be interacted with and, importantly, we haven\u2019t removed the focus ring.\nwe\u2019ve labelled the with the word \u201cSettings\u201d so that our users will hopefully understand what the button is for.\nwe\u2019ve used an element to structure and communicate our list of related items.\n\nWe\u2019ve also practiced taxonomy by developing systems and structures and creating relationships between our elements:\n\nby connecting the to the panel using the aria-controls attribute we\u2019ve programmatically created a relationship between two elements.\nwe\u2019ve developed a structure in our elements by labelling our with the same name as the that controls its appearance.\n\nAnd finally we\u2019ve practiced choreography by creating elements that foster movement and interaction. We\u2019ve anticipated the way users and information want to flow:\n\nwe\u2019ve used a element that is interactive and accessible out of the box.\nour aria-controls attribute can help some people who use screen readers move easily from the to the panel it controls.\nby toggling the value of the aria-expanded attribute we\u2019ve developed a system that tells assistive technology about the status of the relationship between our elements: the panel is visible or the panel is hidden.\nwe\u2019ve made sure our information is more usable and findable no matter how our users want or need to interact with it. Regardless of how someone \u201csees\u201d our work they\u2019re going to be able to use it because we\u2019ve architected multiple ways to access our information.\n\nInformation architecture, robust code, and accessibility\nThe United Nations estimates that around 10% of the world\u2019s population has some form of disability which, at the time of writing, is around 740,000,000 people. That\u2019s a lot of people who rely on well-architected semantic code that can be interpreted by whatever assistive technology they may need to use.\nIf everyone involved in the creation of our places made of information practiced information architecture it would make satisfying the WCAG 2.0 POUR principles so much easier. Our digital construction practices directly affect the quality of life of millions of people, and we have a responsibility to make technology available to them. In her book How To Make Sense Of Any Mess, Abby Covert states:\nIf we\u2019re going to be successful in this new world, we need to see information as a workable material and learn to architect it in a way that gets us to our goals.\nHow To Make Sense Of Any Mess\nI believe that the world will be a better place if we start treating front-end development as information architecture.", "year": "2016", "author": "Francis Storr", "author_slug": "francisstorr", "published": "2016-12-17T00:00:00+00:00", "url": "https://24ways.org/2016/front-end-developers-are-information-architects-too/", "topic": "code"}
{"rowid": 296, "title": "Animation in Design Systems", "contents": "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. \nBut 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\u2019s leverage existing structures and workflows to reduce friction when it comes to animation and create cohesive and performant user experiences. \nUnderstand the importance of animation\nPart of the reason we treat animation like a second-class citizen is that we don\u2019t 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. \nWe 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. \n\n\u201cWhere did that menu go? Oh it\u2019s in there.\u201d \n\nFor a deeper dive into how animation can connect disparate states, I wrote about the Importance of Context-Shifting in UX Patterns for CSS-Tricks.\nAn animation flow on mobile.\nAnimation 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\u2019t anything very fancy or crazy. Just by showing their users that they cared about them, they stuck around, and the bounce rates dropped.\n\n14 second generic loading screen.22 second custom loading screen.\nThis 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\u2019t as long. \nEli Fitch gave a talk at CSS Dev Conf called: \u201cPerceived Performance: The Only Kind That Really Matters\u201d, 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\u2013and therefore easier to measure\u2013but that measuring how a user feels when visiting the site is more important and worth the time and attention. \nIn his talk, he states \u201cHumans over-estimate passive waits by 36%, per Richard Larson of MIT\u201d. This means that if you\u2019re 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.\nReign it in\nUnlike 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\u2019re 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.\nThe 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\u2019t using animation but probably should. (Hint: perceived performance of a loader on a form submission can dramatically change your bounce rates.) \nNot 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.\nEven some beautiful component libraries that have animation in the docs make this mistake. You don\u2019t need every kind of animation, just like you don\u2019t need every kind of font. This bloats our code. Ask yourself questions like: do you really need a flip 180 degree animation? I can\u2019t even conceive of a place on a typical UI where that would be useful, yet most component libraries that I\u2019ve seen have a mixin that does just this.\nWhich leads to\u2026\nHave an opinion\nMany people are confused about Material Design. They think that Material Design is Motion Design, mostly because they\u2019ve 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\u2019s good branding.\nBy using Google\u2019s motion design language and not your own, you\u2019re losing out on a chance to be memorable on your own website.\nWhat does having an opinion on motion look like in practice? It could mean you\u2019ve 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 \u201cgliding\u201d 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\u2019re working on an entirely different codebase), and to instead work on something that feels like it glides. You save time and don\u2019t have to communicate again and again to make things feel cohesive.\nCreate good developer resources\nSometimes people don\u2019t incorporate animation into a design system because they aren\u2019t 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):\nCreate 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\u2019s the default (usually around .25 seconds or thereabouts).\nKeep 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.\nUse 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. \nSee the Pen Modularized Animation for Component Libraries by Sarah Drasner (@sdras) on CodePen.\n\nThe 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.\nOne 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. \nReact 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!\nResponsive\nAt the very least we should ensure that interaction also works well on mobile, but if we\u2019d 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.\nResponsive 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 \u00d7 40px or greater) or use @media(pointer:coarse) as support allows.\nBuy-in\nSometimes people don\u2019t 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:\n\n\nThis helps people you\u2019re working with figure out the relative necessity and workload of the addition of these animations and think more critically about it. You\u2019re also more likely to get something through if you\u2019re proving that what you\u2019re making is needed and can be reused. \nGood compromises can be made this way: \u201cwe\u2019re not going to go all out and create an animated \u2018About Us\u2019 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.\u201d \nSuccessfully 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\u2019t be overstressed that good communication is key.\nGet started!\nWith 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.", "year": "2016", "author": "Sarah Drasner", "author_slug": "sarahdrasner", "published": "2016-12-16T00:00:00+00:00", "url": "https://24ways.org/2016/animation-in-design-systems/", "topic": "code"}
{"rowid": 309, "title": "HTTP/2 Server Push and Service Workers: The Perfect Partnership", "contents": "Being a web developer today is exciting! The web has come a long way since its early days and there are so many great technologies that enable us to build faster, better experiences for our users. One of these technologies is HTTP/2 which has a killer feature known as HTTP/2 Server Push.\nDuring this year\u2019s Chrome Developer Summit, I watched a really informative talk by Sam Saccone, a Software Engineer on the Google Chrome team. He gave a talk entitled Planning for Performance, and one of the topics that he covered immediately piqued my interest; the idea that HTTP/2 Server Push and Service Workers were the perfect web performance combination.\n\nIf you\u2019ve never heard of HTTP/2 Server Push before, fear not - it\u2019s not as scary as it sounds. HTTP/2 Server Push simply allows the server to send data to the browser without having to wait for the browser to explicitly request it first. In this article, I am going to run through the basics of HTTP/2 Server Push and show you how, when combined with Service Workers, you can deliver the ultimate in web performance to your users.\nWhat is HTTP/2 Server Push?\nWhen a user navigates to a URL, a browser will make an HTTP request for the underlying web page. The browser will then scan the contents of the HTML document for any assets that it may need to retrieve such as CSS, JavaScript or images. Once it finds any assets that it needs, it will then make multiple HTTP requests for each resource that it needs and begin downloading one by one. While this approach works well, the problem is that each HTTP request means more round trips to the server before any data arrives at the browser. These extra round trips take time and can make your web pages load slower. \nBefore we go any further, let\u2019s see what this might look like when your browser makes a request for a web page. If you were to view this in the developer tools of your browser, it might look a little something like this:\n\nAs you can see from the image above, once the HTML file has been downloaded and parsed, the browser then makes HTTP requests for any assets that it needs. \nThis is where HTTP/2 Server Push comes in. The idea behind HTTP/2 Server Push is that when the browser requests a web page from the server, the server already knows about all the assets that are needed for the web page and \u201cpushes\u201d it to browser. This happens when the first HTTP request for the web page takes place and it eliminates an extra round trip, making your site faster. \nUsing the same example above, let\u2019s \u201cpush\u201d the JavaScript and CSS files instead of waiting for the browser to request them. The image below gives you an idea of what this might look like.\n\nWhoa, that looks different - let\u2019s break it down a little. Firstly, you can see that the JavaScript and CSS files appear earlier in the waterfall chart. You might also notice that the loading times for the files are extremely quick. The browser doesn\u2019t need to make an extra HTTP request to the server, instead it receives the critical files it needs all at once. Much better! \nThere are a number of different approaches when it comes to implementing HTTP/2 Server Push. Adoption is growing and many commercial CDNs such as Akamai and Cloudflare already offer support for Server Push. You can even roll your own implementation depending on your environment. I\u2019ve also previously blogged about building a basic HTTP/2 Server Push example using Node.js. In this post, I\u2019m not going to dive into how to implement HTTP/2 Server Push as that is an entire post in itself! However, I do recommend reading this article to find out more about the inner workings.\nHTTP/2 Server Push is awesome, but it isn\u2019t a magic bullet. It is fantastic for improving the load time of a web page when it first loads for a user, but it isn\u2019t that great when they request the same web page again. The reason for this is that HTTP/2 Server Push is not cache \u201caware\u201d. This means that the server isn\u2019t aware about the state of your client. If you\u2019ve visited a web page before, the server isn\u2019t aware of this and will push the resource again anyway, regardless of whether or not you need it. HTTP/2 Server Push effectively tells the browser that it knows better and that the browser should receive the resources whether it needs them or not. In theory browsers can cancel HTTP/2 Server Push requests if they\u2019re already got something in cache but unfortunately no browsers currently support it. The other issue is that the server will have already started to send some of the resource to the browser by the time the cancellation occurs.\nHTTP/2 Server Push & Service Workers\nSo where do Service Workers fit in? Believe it or not, when combined together HTTP/2 Server Push and Service Workers can be the perfect web performance partnership. If you\u2019ve not heard of Service Workers before, they are worker scripts that run in the background of your website. Simply put, they act as middleman between the client and the browser and enable you to intercept any network requests that come and go from the browser. They are packed with useful features such as caching, push notifications, and background sync. Best of all, they are written in JavaScript, making it easy for web developers to understand.\nUsing Service Workers, you can easily cache assets on a user\u2019s device. This means when a browser makes an HTTP request for an asset, the Service Worker is able to intercept the request and first check if the asset already exists in cache on the users device. If it does, then it can simply return and serve them directly from the device instead of ever hitting the server.\nLet\u2019s stop for a second and analyse what that means. Using HTTP/2 Server Push, you are able to push critical assets to the browser before the browser requests them. Then, using Service Workers you are able to cache these resources so that the browser never needs to make a request to the server again. That means a super fast first load and an even faster second load!\nLet\u2019s put this into action. The following HTML code is a basic web page that retrieves a few images and two JavaScript files.\n\n\n\n \n HTTP2 Push Demo \n\n\n HTTP2 Push \n \n \n \n \n \n \n \n \n \n \n\n\nIn the HTML code above, I am registering a Service Worker file named service-worker.js. In order to start caching assets, I am going to use the Service Worker toolbox . It is a lightweight helper library to help you get started creating your own Service Workers. Using this library, we can actually cache the base web page with the path /push.\nThe Service Worker Toolbox comes with a built-in routing system which is based on the same routing as Express. With just a few lines of code, you can start building powerful caching patterns.\nI\u2019ve add the following code to the service-worker.js file.\n(global => {\n 'use strict';\n\n // Load the sw-toolbox library.\n importScripts('/js/sw-toolbox/sw-toolbox.js');\n\n // The route for any requests\n toolbox.router.get('/push', global.toolbox.fastest);\n\n toolbox.router.get('/images/(.*)', global.toolbox.fastest);\n\n toolbox.router.get('/js/(.*)', global.toolbox.fastest);\n\n // Ensure that our service worker takes control of the page as soon as possible.\n global.addEventListener('install', event => event.waitUntil(global.skipWaiting()));\n global.addEventListener('activate', event => event.waitUntil(global.clients.claim()));\n})(self);\nLet\u2019s break this code down further. Around line 4, I am importing the Service Worker toolbox. Next, I am specifying a route that will listen to any requests that match the URL /push. Because I am also interested in caching the images and JavaScript for that page, I\u2019ve told the toolbox to listen to these routes too.\nThe best thing about the code above is that if any of the assets exist in cache, we will instantly return the cached version instead of waiting for it to download. If the asset doesn\u2019t exist in cache, the code above will add it into cache so that we can retrieve it when it\u2019s needed again.\nYou may also notice the code global.toolbox.fastest - this is important because gives you the compromise of fulfilling from the cache immediately, while firing off an additional HTTP request updating the cache for the next visit.\nBut what does this mean when combined with HTTP/2 Server Push? Well, it means that on the first load of the web page, you are able to \u201cpush\u201d everything to the user at once before the browser has even requested it. The Service Worker activates and starts caching the assets on the users device. The next time a user visits the page, the Service Worker will intercept the request and serve the asset directly from cache. Amazing! \nUsing this technique, the waterfall chart for a repeat visit should look like the image below.\n\nIf you look closely at the image above, you\u2019ll notice that the web page returns almost instantly without ever making an HTTP request over the network. Using the Service Worker library, we cached the base page for the route /push, which allowed us to retrieve this directly from cache.\nWhether used on their own or combined together, the best thing about these two features is that they are the perfect progressive enhancement. If your user\u2019s browser doesn\u2019t support them, they will simply fall back to HTTP/1.1 without Service Workers. Your users may not experience as fast a load time as they would with these two techniques, but it would be no different from their normal experience. HTTP/2 Server Push and Service Workers are really the perfect partners when it comes to web performance.\nSummary\nWhen used correctly, HTTP/2 Server Push and Service Workers can have a positive impact on your site\u2019s load times. Together they mean super fast first load times and even faster repeat views to a web page. Whilst this technique is really effective, it\u2019s worth noting that HTTP/2 push is not a magic bullet. Think about the situations where it might make sense to use it and don\u2019t just simply \u201cpush\u201d everything; it could actually lead to having slower page load times. If you\u2019d like to learn more about the rules of thumb for HTTP/2 Server Push, I recommend reading this article for more information. \nAll of the code in this example is available on my Github repo - if you have any questions, please submit an issue and I\u2019ll get back to you as soon as possible. \nIf you\u2019d like to learn more about this technique and others relating to HTTP/2, I highly recommend watching Sam Saccone\u2019s talk at this years Chrome Developer Summit. \nI\u2019d also like to say a massive thank you to Robin Osborne, Andy Davies and Jeffrey Posnick for helping me review this article before putting it live!", "year": "2016", "author": "Dean Hume", "author_slug": "deanhume", "published": "2016-12-15T00:00:00+00:00", "url": "https://24ways.org/2016/http2-server-push-and-service-workers/", "topic": "code"}
{"rowid": 291, "title": "Information Literacy Is a Design Problem", "contents": "Information literacy, wrote Dr. Carol Kulthau in her 1987 paper \u201cInformation Skills for an Information Society,\u201d is \u201cthe ability to read and to use information essential for everyday life\u201d\u2014that is, to effectively navigate a world built on \u201ccomplex masses of information generated by computers and mass media.\u201d\nNearly thirty years later, those \u201ccomplex masses of information\u201d have only grown wilder, thornier, and more constant. We call the internet a firehose, yet we\u2019re loathe to turn it off (or even down). The amount of information we consume daily is staggering\u2014and yet our ability to fully understand it all remains frustratingly insufficient. \nThis should hit a very particular chord for those of us working on the web. We may be developers, designers, or strategists\u2014we may not always be responsible for the words themselves\u2014but we all know that communication is much more than just words. From fonts to form fields, every design decision that we make changes the way information is perceived\u2014for better or for worse.\nWhat\u2019s more, the design decisions that we make feed into larger patterns. They don\u2019t just affect the perception of a single piece of information on a single site; they start to shape reader expectations of information anywhere. Users develop cumulative mental models of how websites should be: where to find a search bar, where to look at contact information, how to filter a product list. \nAnd yet: our models fail us. Fundamentally, we\u2019re not good at parsing information, and that\u2019s troubling. Our experience of an \u201cinformation society\u201d may have evolved, but the skills Dr. Kuhlthau spoke of are even more critical now: our lives depend on information literacy.\nPatterns from words\nLet\u2019s start at the beginning: with the words. Our choice of words can drastically alter a message, from its emotional resonance to its context to its literal meaning. Sometimes we can use word choice for good, to reinvigorate old, forgotten, or unfairly besmirched ideas.\nOne time at a wedding bbq we labeled the coleslaw BRASSICA MIXTA so people wouldn\u2019t skip it based on false hatred.\u2014 Eileen Webb (@webmeadow) November 27, 2016\n\nWe can also use clever word choice to build euphemisms, to name sensitive or intimate concepts without conjuring their full details. This trick gifts us with language like \u201cthe beast with two backs\u201d (thanks, Shakespeare!) and \u201csurfing the crimson wave\u201d (thanks, Cher Horowitz!).\nBut when we grapple with more serious concepts\u2014war, death, human rights\u2014this habit of declawing our language gets dangerous. Using more discrete wording serves to nullify the concepts themselves, euphemizing them out of sight and out of mind.\nThe result? Politicians never lie, they just \u201cmisspeak.\u201d Nobody\u2019s racist, but plenty of people are \u201ceconomically anxious.\u201d Nazis have rebranded as \u201calt-right.\u201d \nI\u2019m not an asshole, I\u2019m just alt-nice.\u2014 Andi Zeisler (@andizeisler) November 22, 2016\n\nThe problem with euphemisms like these is that they quickly infect everyday language. We use the words we hear around us. The more often we see \u201calt-right\u201d instead of \u201cNazi,\u201d the more likely we are to use that phrase ourselves\u2014normalizing the term as well as the terrible ideas behind it.\nPatterns from sentences\nThat process of normalization gets a boost from the media, our main vector of information about the world outside ourselves. Headlines control how we interpret the news that follows\u2014even if the story contradicts it in the end. We hear the framing more clearly than the content itself, coloring our interpretation of the news over time.\nEven worse, headlines are often written to encourage clicks, not to convey critical information. When headline-writing is driven by sensationalism, it\u2019s much, much easier to build a pattern of misinformation. Take this CBS News headline: \u201cDonald Trump: \u2018Millions\u2019 voted illegally for Hillary Clinton.\u201d The headline makes no indication that this an objectively false statement; instead, this word choice subtly suggestions that millions did, in fact, illegally vote for Hillary Clinton.\nHeadlines like this are what make lying a worthwhile political strategy. https://t.co/DRjGeYVKmW\u2014 Binyamin Appelbaum (@BCAppelbaum) November 27, 2016\n\nThis is a deeply dangerous choice of words when headlines are the primary way that news is conveyed\u2014especially on social media, where it\u2019s much faster to share than to actually read the article. In fact, according to a study from the Media Insight Project, \u201croughly six in 10 people acknowledge that they have done nothing more than read news headlines in the past week.\u201d \nIf a powerful person asserts X there are 2 responsible ways to cover:1. \u201cX is true\u201d2. \u201cPerson incorrectly thinks X\u201dNever \u201cPerson says X\u201d\u2014 Helen Rosner (@hels) November 27, 2016\n\nEven if we do, in fact, read the whole article, there\u2019s no guarantee that we\u2019re thinking critically about it. A study conducted by Stanford found that \u201c82 percent of students could not distinguish between a sponsored post and an actual news article on the same website. Nearly 70 percent of middle schoolers thought they had no reason to distrust a sponsored finance article written by the CEO of a bank, and many students evaluate the trustworthiness of tweets based on their level of detail and the size of attached photos.\u201d \nFriends: our information literacy is not very good. Luckily, we\u2014workers of the web\u2014are in a position to improve it.\nSentences into design\nConsider the presentation of those all-important headlines in social media cards, as on Facebook. The display is a combination of both the card\u2019s design and the article\u2019s source code, and looks something like this:\n\nA large image, a large headline; perhaps a brief description; and, at the bottom, in pale gray, a source and an author\u2019s name. \nThose choices convey certain values: specifically, they suggest that the headline and the picture are the entire point. The source is so deemphasized that it\u2019s easy to see how fake news gains a foothold: daily exposure to this kind of hierarchy has taught us that sources aren\u2019t important. \nAnd that\u2019s the message from the best-case scenario. Not every article shows every piece of data. Take this headline from the BBC: \u201cWisconsin receives request for vote recount.\u201d \n\nWith no image, no description, and no author, there\u2019s little opportunity to signal trust or provide nuance. There\u2019s also no date\u2014ever\u2014which presents potentially misleading complications, especially in the context of \u201cbreaking news.\u201d \nAnd lest you think dates don\u2019t matter in the light-speed era of social media, take the headline, \u201cMaryland sidesteps electoral college.\u201d Shared into my feed two days after the US presidential election, that\u2019s some serious news with major historical implications. But since there\u2019s no date on this card, there\u2019s no way for readers to know that the \u201cTuesday\u201d it refers to was in 2007. Again, a design choice has made misinformation far too contagious.\n\nMore recently, I posted my personal reaction to the death of Fidel Castro via a series of twenty tweets. Wanting to share my thoughts with friends and family who don\u2019t use Twitter, I then posted the first tweet to Facebook. The card it generated was less than ideal:\n\nThe information hierarchy created by this approach prioritizes the name of the Twitter user (not even the handle), along with the avatar. Not only does that create an awkward \u201cheadline\u201d (at least when you include a full stop in your name), but it also minimizes the content of the tweet itself\u2014which was the whole point. \nThe arbitrary elevation of some pieces of content over others\u2014like huge headlines juxtaposed with minimized sources\u2014teaches readers that these values are inherent to the content itself: that the headline is the news, that the source is irrelevant. We train readers to stop looking for the information we don\u2019t put in front of them. \nThese aren\u2019t life-or-death scenarios; they are just cases where design decisions noticeably dictate the perception of information. Not every design decision makes so obvious an impact, but the impact is there. Every single action adds to the pattern.\nDesign with intention\nWe can\u2019t necessarily teach people to read critically or vet their sources or stop believing conspiracy theories (or start believing facts). Our reach is limited to our roles: we make websites and products for companies and colleges and startups.\nBut we have more reach there than we might realize. Every decision we make influences how information is presented in the world. Every presentation adds to the pattern. No matter how innocuous our organization, how lowly our title, how small our user base\u2014every single one of us contributes, a little bit, to the way information is perceived.\nAre we changing it for the better?\nWhile it\u2019s always been crucial to act ethically in the building of the web, our cultural climate now requires dedicated, individual conscientiousness. It\u2019s not enough to think ourselves neutral, to dismiss our work as meaningless or apolitical. Everything is political. Every action, and every inaction, has an impact.\nAs Chappell Ellison put it much more eloquently than I can:\nEvery single action and decision a designer commits is a political act. The question is, are you a conscious actor?\u2014 Chappell Ellison\ud83e\udd14 (@ChappellTracker) November 28, 2016\n\nAs shapers of information, we have a responsibility: to create clarity, to further understanding, to advance truth. Every single one of us must choose to treat information\u2014and the society it builds\u2014with integrity.", "year": "2016", "author": "Lisa Maria Martin", "author_slug": "lisamariamartin", "published": "2016-12-14T00:00:00+00:00", "url": "https://24ways.org/2016/information-literacy-is-a-design-problem/", "topic": "content"}
{"rowid": 311, "title": "Designing Imaginative Style Guides", "contents": "(Living) style guides and (atomic) patterns libraries are \u201call the rage,\u201d as my dear old Nana would\u2019ve said. If articles and conference talks are to be believed, making and using them has become incredibly popular. I think there are plenty of ways we can improve how style guides look and make them better at communicating design information to creatives without it getting in the way of information that technical people need.\nGuides to libraries of patterns\nMost of my consulting work and a good deal of my creative projects now involve designing style guides. I\u2019ve amassed a huge collection of brand guidelines and identity manuals as well as, more recently, guides to libraries of patterns intended to help designers and developers make digital products and websites.\nTwo pages from one of my Purposeful style guide packs. Designs \u00a9 Stuff & Nonsense.\n\u201cStyle guide\u201d is an umbrella term for several types of design documentation. Sometimes we\u2019re referring to static style or visual identity guides, other times voice and tone. We might mean front-end code guidelines or component/pattern libraries. These all offer something different but more often than not they have something in common. They look ugly enough to have been designed by someone who enjoys configuring a router.\nOK, that was mean, not everyone\u2019s going to think an unimaginative style guide design is a problem. After all, as long as a style guide contains information people need, how it looks shouldn\u2019t matter, should it?\nInspiring not encyclopaedic\nWell here\u2019s the thing. Not everyone needs to take the same information away from a style guide. If you\u2019re looking for markup and styles to code a \u2018media\u2019 component, you\u2019re probably going to be the technical type, whereas if you need to understand the balance of sizes across a typographic hierarchy, you\u2019re more likely to be a creative. What you need from a style guide is different.\nSure, some people1 need rules:\n\n\u201cDo this (responsive pattern)\u201d or \u201cdon\u2019t do that (auto-playing video.)\u201d \n\nThose people probably also want facts:\n\n\u201cUse this (hexadecimal value)\u201d and not that inaccessible colour combination.\u201d\n\nStyle guides need to do more than list facts and rules. They should demonstrate a design, not just document its parts. The best style guides are inspiring not encyclopaedic. I\u2019ll explain by showing how many style guides currently present information about colour. \nColours communicate\nI\u2019m sure you\u2019ll agree that alongside typography, colour\u2019s one of the most important ingredients in a design. Colour communicates personality, creates mood and is vital to an easily understandable interactive vocabulary. So you\u2019d think that an average style guide would describe all this in any number of imaginative ways. Well, you\u2019d be disappointed, because the most inspiring you\u2019ll find looks like a collection of chips from a paint chart.\n\nLonely Planet\u2019s Rizzo does a great job of separating its Design Elements from UI Components, and while its \u2018Click to copy\u2019\u00a0colour values are a thoughtful touch, you\u2019ll struggle to get a feeling for Lonely Planet\u2019s design by looking at their colour chips.\nLonely Planet\u2019s Rizzo style guide.\nLonely Planet approach is a common way to display colour information and it\u2019s one that you\u2019ll also find at Greenpeace, Sky, The Times and on countless more style guides.\n\n\n\n\n\nGreenpeace, Sky and The Times style guides.\nGOV.UK\u2014not a website known for its creative flair\u2014varies this approach by using circles, which I find strange as circles don\u2019t feature anywhere else in its branding or design. On the plus side though, their designers have provided some context by categorising colours by usage such as text, links, backgrounds and more.\nGOV.UK style guide.\nGoogle\u2019s Material Design offers an embarrassment of colours but most helpfully it also advises how to combine its primary and accent colours into usable palettes.\nGoogle\u2019s Material Design.\nWhile the ability to copy colour values from a reference might be all a technical person needs, designers need to understand why particular colours were chosen as well as how to use them. \nInspiration not documentation\nFew style guides offer any explanation and even less by way of inspiring examples. Most are extremely vague when they describe colour:\n\n\u201cUse colour as a presentation element for either decorative purposes or to convey information.\u201d\n\nThe Government of Canada\u2019s Web Experience Toolkit states, rather obviously.\n\n\u201cCertain colors have inherent meaning for a large majority of users, although we recognize that cultural differences are plentiful.\u201d\n\nSalesforce tell us, without actually mentioning any of those plentiful differences. \nI\u2019m also unsure what makes the Draft U.S. Web Design Standards colours a \u201cdistinctly American palette\u201d but it will have to work extremely hard to achieve its goal of communicating \u201cwarmth and trustworthiness\u201d now. \nIn Canada, \u201cbold and vibrant\u201d colours reflect Alberta\u2019s \u201cdiverse landscape.\u201d \nAdding more colours to their palette has made Adobe \u201crich, dynamic, and multi-dimensional\u201d and at Skype, colours are \u201cbold, colourful (obviously) and confident\u201d although their style guide doesn\u2019t actually provide information on how to use them.\nThe University of Oxford, on the other hand, is much more helpful by explaining how and why to use their colours:\n\n\u201cThe (dark) Oxford blue is used primarily in general page furniture such as the backgrounds on the header and footer. This makes for a strong brand presence throughout the site. Because it features so strongly in these areas, it is not recommended to use it in large areas elsewhere. However it is used more sparingly in smaller elements such as in event date icons and search/filtering bars.\u201d\n\nOpenTable style guide.\nThe designers at OpenTable have cleverly considered how to explain the hierarchy of their brand colours by presenting them and their supporting colours in various size chips. It\u2019s also obvious from OpenTable\u2019s design which colours are primary, supporting, accent or neutral without them having to say so.\nArt directing style guides\nFor the style guides I design for my clients, I go beyond simply documenting their colour palette and type styles and describe visually what these mean for them and their brand. I work to find distinctive ways to present colour to better represent the brand and also to inspire designers. \nFor example, on a recent project for SunLife, I described their palette of colours and how to use them across a series of art directed pages that reflect the lively personality of the SunLife brand. Information about HEX and RGB values, Sass variables and when to use their colours for branding, interaction and messaging is all there, but in a format that can appeal to both creative and technical people.\nSunLife style guide. Designs \u00a9 Stuff & Nonsense.\nPurposeful style guides\nIf you want to improve how you present colour information in your style guides, there\u2019s plenty you can do.\nFor a start, you needn\u2019t confine colour information to the palette page in your style guide. Find imaginative ways to display colour across several pages to show it in context with other parts of your design. Here are two CSS gradient filled \u2018cover\u2019 pages from my Purposeful style sheets.\nColour impacts other elements too, including typography, so make sure you include colour information on those pages, and vice-versa.\nPurposeful. Designs \u00a9 Stuff & Nonsense.\nA visual hierarchy can be easier to understand than labelling colours as \u2018primary,\u2019 \u2018supporting,\u2019 or \u2018accent,\u2019 so find creative ways to present that hierarchy. You might use panels of different sizes or arrange boxes on a modular grid to fill a page with colour.\nDon\u2019t limit yourself to rectangular colour chips, use circles or other shapes created using only CSS. If irregular shapes are a part of your brand, fill SVG silhouettes with CSS and then wrap text around them using CSS shapes. \nPurposeful. Designs \u00a9 Stuff & Nonsense.\nSumming up\nIn many ways I\u2019m as frustrated with style guide design as I am with the general state of design on the web. Style guides and pattern libraries needn\u2019t be dull in order to be functional. In fact, they\u2019re the perfect place for you to try out new ideas and technologies. There\u2019s nowhere better to experiment with new properties like CSS Grid than on your style guide.\nThe best style guide designs showcase new approaches and possibilities, and don\u2019t simply document the old ones. Be as creative with your style guide designs as you are with any public-facing part of your website.\n\nPurposeful are HTML and CSS style guides templates designed to help you develop creative style guides and pattern libraries for your business or clients. Save time while impressing your clients by using easily customisable HTML and CSS files that have been designed and coded to the highest standards. Twenty pages covering all common style guide components including colour, typography, buttons, form elements, and tables, plus popular pattern library components. Purposeful style guides will be available to buy online in January.\n\n\n\n\nBoring people\u00a0\u21a9", "year": "2016", "author": "Andy Clarke", "author_slug": "andyclarke", "published": "2016-12-13T00:00:00+00:00", "url": "https://24ways.org/2016/designing-imaginative-style-guides/", "topic": "design"}
{"rowid": 306, "title": "What next for CSS Grid Layout?", "contents": "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\u2019t 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. \nAs 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.\nThe 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\u2019t mean that works stops here, and that new use cases and features can\u2019t be proposed for future levels of Grid Layout. Therefore, in this article I\u2019m 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.\nSubgrid - the missing feature of Level 1\nThe 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.\n\nNesting Grids by Rachel Andrew (@rachelandrew) on CodePen.\nThe 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.\nThe 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.\nIn 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 \u201cat risk\u201d in the Level 1 Candidate Recommendation. With regard to \u2018at-risk\u2019 this is explained as follows:\n\n\u201c\u2018At-risk\u2019 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.\u201d \n\nIf 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\u2019m 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. \nFurther reading about subgrid\n\nMy post from 2015 detailing why I feel subgrid is important\nMy post based on the revised specification\nEric Meyer\u2019s thoughts on subgrid\nWrite-up of a discussion from Igalia who work on the Blink and Webkit browser implementations\n\nStyling cells, tracks and areas\nHaving defined a grid with CSS Grid Layout you can place child elements into that grid, however what you can\u2019t do is style the grid tracks or cells. Grid doesn\u2019t even go as far as multiple column layout, which has the column-rule properties.\nIn 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\u2019m using a 1 pixel grid gap to fake lines between grid cells, and empty div elements, and some generated content to colour those cells.\n\nFaked backgrounds and borders by Rachel Andrew (@rachelandrew) on CodePen.\nI 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.\nMore control over auto placement\nIf you haven\u2019t 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.\n\nItems auto-place on a defined grid by Rachel Andrew (@rachelandrew) on CodePen.\nThe 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.\n\nWebsafe colors meet CSS Grid (auto-placement demo) by Rachel Andrew (@rachelandrew) on CodePen.\nI 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\u00f6rklund 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.\nCreating non-rectangular grid areas\nA 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\u2019t create an L-shaped or otherwise non-regular shape.\n\nGrid Areas by Rachel Andrew (@rachelandrew) on CodePen.\n\nPerhaps 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.\n.wrapper {\n display: grid;\n grid-template-areas:\n \"sidebar header header\"\n \"sidebar content quote\"\n \"sidebar content content\";\n}\nFlowing content through grid cells or areas\nSome 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.\nBeing 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.\nIn 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.\nSolving the keyboard/layout disconnect\nOne 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\u00e9onie Watson with reference to flexbox in Flexbox and the keyboard navigation disconnect.\nThe 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\u2019s 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.\nBringing your ideas to the future of Grid Layout\nWhen I\u2019m 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.\nAs a \u201cproduct\u201d grid has been well thought through by many people. Yet however hard we try there will be use cases we just didn\u2019t think of. You may well have one in mind right now. That\u2019s 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.\nThis 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\u2019t just mutter about how the CSS Working Group don\u2019t 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\u2019t 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. \nI opened this article by explaining I\u2019d written about grid layout four years ago, and how we\u2019re 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\u2019s 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\u2019t feel that because you don\u2019t 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\u2019re dealing with now and in the future.", "year": "2016", "author": "Rachel Andrew", "author_slug": "rachelandrew", "published": "2016-12-12T00:00:00+00:00", "url": "https://24ways.org/2016/what-next-for-css-grid-layout/", "topic": "code"}
{"rowid": 298, "title": "First Steps in VR", "contents": "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. \nI 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.\nEvery year we see articles saying it will be the \u201cyear of virtual reality\u201d, that was especially prevalent this year. 2016 has been a year of progress, VR isn\u2019t 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.\nWebVR 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.\nGetting Started with A-Frame\nI 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\u2019s not to say you can\u2019t build complex things, you have complete access to write JavaScript and shaders.\nI\u2019m 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\u2019s 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\u2019s fun.\nFor this project I wanted to keep things as simple as possible, so I can easily explain it without the classic \u201cdraw a circle then draw an owl\u201d. I wrote a list of requirements, with some stretch goals that you can give a try yourself if you fancy:\n\nMust work on Google Cardboard at a minimum, because of price\nTherefore, it must not rely on having a controller\nAuto-moving around a maze would be a good example\nMove in direction you look\nStretch goal: Scoring, time until you hit a wall or get stuck in maze\nStretch goal: Levels, so the map doesn\u2019t need to be random\nStretch goal: Snow!\n\nI 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. \n\n\n\n \n \n 24 ways \n \n \n\n\n\n \n \n\n \n\n \n\n \n\n \n \n \n\n\n\nAs 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 which is the container for everything that is going to show up on the screen. There are a few which can be compared to 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.\nStyling\nNow we\u2019ve 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.\nNote, 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.\nTextures\nUnless 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.\n
\n \n \n \nThe
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. \nTo 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.\nReplace: \n \nWith:\n \nThis 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.\nbox.setAttribute('material', 'src: #texture-wall');\nThat\u2019s 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. \nLighting\nThe 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.\nThere are lots of types of light in A-Frame (most coming from Three.js). You can add a light either by using the 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.\nTo 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 (), as it looked a bit odd with a white sky.\n \n \nI 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\u2019t a walking human or anything but by moving light where the player is it feels a bit more physical.\n \n\nBy 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 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.\n\nI 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.\nMovement\nOne 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\u2019re looking, but I wasn\u2019t 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.\nAFRAME.registerComponent('automove-controls', {\n init: function () {\n this.speed = 0.1;\n this.isMoving = true;\n this.velocityDelta = new THREE.Vector3();\n },\n isVelocityActive: function () {\n return this.isMoving;\n },\n getVelocityDelta: function () {\n this.velocityDelta.z = this.isMoving ? -speed : 0;\n return this.velocityDelta.clone();\n }\n});\nReplace:\nuniversal-controls\nWith:\nuniversal-controls=\"movementControls: automove, gamepad, keyboard\"\nThis works by creating a component automove-controls that adds auto-move to the player without overriding movement completely. It doesn\u2019t 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.\nBuilding a map\nCurrently 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.\nI made the maze in Tiled by finding a random tileset online (we don\u2019t 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\u2019t 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\u2019s easy to update in the future. \nvar map =\n{\n \"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],\n \"height\":10,\n \"width\":10\n}\n\nAs 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\u2019s 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.\ndocument.querySelector('a-scene').addEventListener('render-target-loaded', function () {\n var WALL_SIZE = 5,\n WALL_HEIGHT = 3;\n var el = document.querySelector('#walls');\n var wall;\n\n for (var x = 0; x < map.height; x++) {\n for (var y = 0; y < map.width; y++) {\n\n var i = y*map.width + x;\n var position = (x-map.width/2)*WALL_SIZE + ' ' + 1.5 + ' ' + (y-map.height/2)*WALL_SIZE;\n if (map.data[i] === 1) {\n // Create wall\n wall = document.createElement('a-box');\n el.appendChild(wall);\n wall.setAttribute('color', '#fff');\n wall.setAttribute('material', 'src: #texture-wall;');\n wall.setAttribute('width', WALL_SIZE);\n wall.setAttribute('height', WALL_HEIGHT);\n wall.setAttribute('depth', WALL_SIZE);\n wall.setAttribute('position', position);\n wall.setAttribute('static-body', ');\n }\n\n if (map.data[i] === 2) {\n // Set player position\n document.querySelector('#player').setAttribute('position', position);\n }\n\n }\n }\n console.info('Walls added.');\n});\n\nWith 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\u2019s 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.\nIt\u2019s Not All Fun And Games\nA 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\u2019s just a tiny subset. There are all sorts of applications for VR, including story telling, data visualisation and even meditation.\nThere have been a number of cases where it has been shown virtual reality can help as a tool for therapies:\n\nOxford study finds virtual reality can help treat severe paranoia\nVirtual Reality Therapy for Phobias at the Duke Faculty Practice\nBravemind: Virtual Reality Exposure Therapy at the University of Southern California\n\nThese 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.\nWrapping Up\nTen 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. \u201cThe mobile web is rapidly becoming an XHTML environment, and thus you and I can apply our existing \u201cdesktop web\u201d skills to understand how to develop content for it.\u201d\nWe 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 \u201cdesktop web\u201d Cameron was referring to.\nSo 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\u2019t 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\u2026 well, let\u2019s hope we have used our skills well and made the world just that little bit better. And if VR is a fad? Well it\u2019s fun\u2026 have a go anyway.", "year": "2016", "author": "Shane Hudson", "author_slug": "shanehudson", "published": "2016-12-11T00:00:00+00:00", "url": "https://24ways.org/2016/first-steps-in-vr/", "topic": "code"}
{"rowid": 292, "title": "Watch Your Language!", "contents": "I\u2019m bilingual. My first language is French. I learned English in my early 20s. Learning a new language later in life meant that I was able to observe my thought processes changing over time. It made me realize that some concepts can\u2019t be expressed in some languages, while other languages express these concepts with ease.\nIt also helped me understand the way we label languages. English: business. French: romance. Here\u2019s an example of how words, or the absence thereof, can affect the way we think:\nIn French we love everything. There\u2019s no straightforward way to say we like something, so we just end up loving everything. I love my sisters, I love broccoli, I love programming, I love my partner, I love doing laundry (this is a lie), I love my mom (this is not a lie). I love, I love, I love. It\u2019s no wonder French is considered romantic. When I first learned English I used the word love rather than like because I hadn\u2019t grasped the difference. Needless to say, I\u2019ve scared away plenty of first dates!\nLearning another language made me realize the limitations of my native language and revealed concepts I didn\u2019t know existed. Without the nuances a given language provides, we fail to express what we really think. The absence of words in our vocabulary gets in the way of effectively communicating and considering ideas.\nWhen I lived in Montr\u00e9al, most people in my circle spoke both French and English. I could switch between them when I could more easily express an idea in one language or the other. I liked (or should I say loved?) those conversations. They were meaningful. They were efficient.\n\nI\u2019m quadrilingual. I code in Ruby, HTML/CSS, JavaScript, Python. In the past couple of years I have been lucky enough to write code in these languages at a massive scale. In learning Ruby, much like learning English, I discovered the strengths and limitations of not only the languages I knew but the language I was learning. It taught me to choose the right tool for the job.\nWhen I started working at Shopify, making a change to a view involved copy/pasting HTML and ERB from one view to another. The CSS was roughly structured into modules, but those modules were not responsive to different screen sizes. Our HTML was complete mayhem, and we didn\u2019t consider accessibility. All this made editing views a laborious process.\nGrep. Replace all. Test. Ship it. Repeat.\nThis wasn\u2019t sustainable at Shopify\u2019s scale, so the newly-formed front end team was given two missions:\n\nMake the app responsive (AKA Let\u2019s Make This Thing Responsive ASAP)\nMake the view layer scalable and maintainable (AKA Let\u2019s Build a Pattern Library\u2026 in Ruby)\n\nLet\u2019s make this thing responsive ASAP\nThe year was 2015. The Shopify admin wasn\u2019t mobile friendly. Our browser support was set to IE10. We had the wind in our sails. We wanted to achieve complete responsiveness in the shortest amount of time. Our answer: container queries.\nIt seemed like the obvious decision at the time. We would be able to set rules for each component in isolation and the component would know how to lay itself out on the page regardless of where it was rendered. It would save us a ton of development time since we wouldn\u2019t need to change our markup, it would scale well, and we would achieve complete component autonomy by not having to worry about page layout. By siloing our components, we were going to unlock the ultimate goal of componentization, cutting the tie to external dependencies. We were cool.\nWriting the JavaScript handling container queries was my first contribution to Shopify. It was a satisfying project to work on. We could drop our components in anywhere and they would magically look good. It took us less than a couple weeks to push this to production and make our app mostly responsive.\nBut with time, it became increasingly obvious that this was not as performant as we had hoped. It wasn\u2019t performant at all. Components would jarringly jump around the page before settling in on first paint.\nIt was only when we started using the flex-wrap: wrap CSS property to build new components that we realized we were not using the right language for the job. So we swapped out JavaScript container queries for CSS flex-wrapping. Even though flex wasn\u2019t yet as powerful as we wanted it to be, it was still a good compromise. Our components stayed independent of the window size but took much less time to render. Best of all: they used CSS instead of relying on JavaScript for layout.\nIn other words: we were using the wrong language to express our layout to the browser, when another language could do it much more simply and elegantly.\nLet\u2019s build a pattern library\u2026 in Ruby\nIn order to make our view layer maintainable, we chose to build a comprehensive library of helpers. This library would generate our markup from a single source of truth, allowing us to make changes system-wide, in one place. No. More. Grepping.\nWhen I joined Shopify it was a Rails shop freshly wounded by a JavaScript framework (See: Batman.js). JavaScript was like Voldemort, the language that could not be named. Because of this baggage, the only way for us to build a pattern library that would get buyin from our developers was to use Rails view helpers. And for many reasons using Ruby was the right choice for us. The time spent ramping developers up on the new UI Components would be negligible since the Ruby API felt familiar. The transition would be simple since we didn\u2019t have to introduce any new technology to the stack. The components would be fast since they would be rendered on the server. We had a plan.\nWe put in place a set of Rails tools to make it easy to build components, then wrote a bunch of sweet, sweet components using our shiny new tools. To document our design, content and front end patterns we put together an interactive styleguide to demonstrate how every component works. Our research and development department loved it (and still do)! We continue to roll out new components, and generally the project has been successful, though it has had its drawbacks.\nSince the Shopify admin is mostly made up of a huge number of forms, most of the content is static. For this reason, using server-rendered components didn\u2019t seem like a problem at the time. With new app features increasing the amount of DOM manipulation needed on the client side, our early design decisions mean making requests to the server for each re-paint. This isn\u2019t going to cut it.\nI don\u2019t know the end of this story, because we haven\u2019t written it yet. We\u2019ve been exploring alternatives to our current system to facilitate the rendering of our components on the client, including React, Vue.js, and Web Components, but we haven\u2019t determined the winner yet. Only time (and data gathering) will tell.\nRuby is great but it doesn\u2019t speak the browser\u2019s language efficiently. It was not the right language for the job.\n\nLearning a new spoken language has had an impact on how I write code. It has taught me that you don\u2019t know what you don\u2019t know until you have the language to express it. Understanding the strengths and limitations of any programming language is fundamental to making good design decisions. At the end of the day, you make the best choices with the information you have. But if you still feel like you\u2019re unable to express your thoughts to the fullest with what you know, it might be time to learn a new language.", "year": "2016", "author": "Annie-Claude C\u00f4t\u00e9", "author_slug": "annieclaudecote", "published": "2016-12-10T00:00:00+00:00", "url": "https://24ways.org/2016/watch-your-language/", "topic": "code"}
{"rowid": 307, "title": "Get the Balance Right: Responsive Display Text", "contents": "Last year in 24 ways I urged you to Get Expressive with Your Typography. I made the case for grabbing your readers\u2019 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.\nWhen 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\u2019s preferences. You can take the same approach with display text by choosing larger sizes from the same scale.\nHowever, 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.\nIntroducing viewport units\nWith 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:\n\nvw - viewport width,\nvh - viewport height,\nvmin - viewport height or width, whichever is smaller\nvmax - viewport height or width, whichever is larger\n\nIn 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:\nh1 {\n font-size: 13 vw;\n}\nSo for a selection of widths, the rendered font size would be:\nRendered font size (px)\nViewport width\n13\u202fvw\n320\n42\n768\n100\n1024\n133\n1280\n166\n1920\n250\n\nA 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. \nLandscape text is much bigger than portrait text when using vw units.\nThe 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.\nHowever 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.\nh1 {\n font-size: 13vmin;\n}\nLandscape text is consistent with portrait text when using vmin units.\nComparing vw and vmin renderings for various common screen dimensions, you can see how using vmin keeps the text size down to a usable magnitude:\nRendered font size (px)\nViewport\n13\u202fvw\n13\u202fvmin\n320 \u00d7 480\n42\n42\n414 \u00d7 736\n54\n54\n768 \u00d7 1024\n100\n100\n1024 \u00d7 768\n133\n100\n1280 \u00d7 720\n166\n94\n1366 \u00d7 768\n178\n100\n1440 \u00d7 900\n187\n117\n1680 \u00d7 1050\n218\n137\n1920 \u00d7 1080\n250\n140\n2560 \u00d7 1440\n333\n187\n\nHybrid font sizing\nUsing 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:\nh1 {\n font-size: 13vmin;\n}\nh2 {\n font-size: 5vmin;\n}\nUsing vmin alone for supporting text can scale it too quickly\nThe 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.\nA 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:\nh2 {\n font-size: calc(0.5rem + 2.5vmin);\n}\nFor a 320 px wide screen, the font size will be 16 px, calculated as follows:\n(0.5 \u00d7 16) + (320 \u00d7 0.025) = 8 + 8 = 16px\nFor a 768 px wide screen, the font size will be 27 px:\n(0.5 \u00d7 16) + (768 \u00d7 0.025) = 8 + 19 = 27px\nThis results in a more balanced subheading that doesn\u2019t take emphasis away from the main heading:\n\nTo give you an idea of the effect of using a hybrid approach, here\u2019s a side-by-side comparison of hybrid and viewport text sizing:\ntable.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}\n\ntop: calc() hybrid method; bottom: vmin only\n16\n20\n27\n32\n35\n40\n44\n16\n24\n38\n48\n54\n64\n72\n320\n480\n768\n960\n1080\n1280\n1440\n\nOver 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.\n\n\n\n\nA reference pixel is based on the logical resolution of a device which takes into account double density screens such as Retina displays.\u00a0\u21a9\ufe0e\n\n\nFor even more sophisticated uses of hybrid text sizing see the work of Mike Riethmuller.\u00a0\u21a9\ufe0e", "year": "2016", "author": "Richard Rutter", "author_slug": "richardrutter", "published": "2016-12-09T00:00:00+00:00", "url": "https://24ways.org/2016/responsive-display-text/", "topic": "code"}
{"rowid": 308, "title": "How to Make a Chrome Extension to Delight (or Troll) Your Friends", "contents": "If you\u2019re like me, you grew up drawing mustaches on celebrities. Every photograph was subject to your doodling wrath, and your brilliance was taken to a whole new level with computer programs like Microsoft Paint. The advent of digital cameras meant that no one was safe from your handiwork, especially not your friends. And when you finally got your hands on Photoshop, you spent hours maniacally giggling at your artistic genius. \nBut today is different. You\u2019re a serious adult with important things to do and a reputation to uphold. You keep up with modern web techniques and trends, and have little time for fun other than a random Giphy on Slack\u2026 right? \nNope. \nIf there\u2019s one thing 2016 has taught me, it\u2019s that we\u2014the self-serious, world-changing tech movers and shakers of the universe\u2014haven\u2019t changed one bit from our younger, more delightable selves.\nHow do I know? This year I created a Chrome extension called Tabby Cat and watched hundreds of thousands of people ditch productivity for randomly generated cats. Tabby Cat replaces your new tab page with an SVG cat featuring a silly name like \u201cStinky Dinosaur\u201d or \u201cTiny Potato\u201d. Over time, the cats collect goodies that vary in absurdity from fishbones to lawn flamingos to Raybans. Kids and adults alike use this extension, and analytics show the majority of use happens Monday through Friday from 9-5. The popularity of Tabby Cat has convinced me there\u2019s still plenty of room in our big, grown-up hearts for fun.\n\n\nToday, we\u2019re going to combine the formula behind Tabby Cat with your intrinsic desire to delight (or troll) your friends, and create a web app that generates your friends with random objects and environments of your choosing. You can publish it as a Chrome extension to replace your new tab, or simply host it as a website and point to it with the New Tab Redirect extension. \nHere\u2019s a sneak peek at my final result featuring my partner, my cat, and I in cheerfully weird accessories. Your result will look however you want it to.\n\nAlong the way, we\u2019ll cover how to build a Chrome extension that replaces the new tab page, and explore ways to program randomness into your work to create something truly delightful. \nWhat you\u2019ll need\n\nAdobe Illustrator (or a similar illustration program to export PNG)\nSome images of your friends\nA text editor\n\nNote: This can be as simple or as complex as you want it to be. Most of the application is pre-built so you can focus on kicking back and getting in touch with your creative side. If you want to dive in deeper, you\u2019ll find ways to do it.\nGetting started\n\nDownload a local copy of the boilerplate for today\u2019s tutorial here, and open it in a text editor. Inside, you\u2019ll find a simple web app that you can run in Chrome. \nOpen index.html in Chrome. You should see a grey page that says \u201cNoname\u201d.\nOpen template.pdf in Adobe Illustrator or a similar program that can export PNG. The file contains an artboard measuring 800px x 800px, with a dotted blue outline of a face. This is your template.\n\nNote: We\u2019re using Google Chrome to build and preview this application because the end-result is a Chrome extension. This means that the application isn\u2019t totally cross-browser compatible, but that\u2019s okay.\nStep 1: Gather your friends\nThe first thing to do is choose who your muses are. Since the holidays are upon us, I\u2019d suggest finding inspiration in your family.\nCreate your artwork\nFor each person, find an image where their face is pointed as forward as possible. Place the image onto the Artwork layer of the Illustrator file, and line up their face with the template. Then, rename the artboard something descriptive like face_bob. Here\u2019s my crew:\nAs you can see, my use of the word \u201cfamily\u201d extends to cats. There\u2019s no judgement here.\nNotice that some of my photos don\u2019t completely fill the artboard\u2013that\u2019s fine. The images will be clipped into ovals when they\u2019re rendered in the application.\nNow, export your images by following these steps:\n\nTurn the Template layer off and export the images as PNGs. \nIn the Export dialog, tick the \u201cUse Artboards\u201d checkbox and enter the range with your faces. \nExport at 72ppi to keep things running fast. \nSave your images into the images/ folder in your project.\n\nAdd your images to config.js\nOpen scripts/config.js. This is where you configure your extension. \nAdd key value pairs to the faces object. The key should be the person\u2019s name, and the value should be the filepath to the image.\nfaces: {\n leslie: 'images/face_leslie.png',\n kyle: 'images/face_kyle.png',\n beep: 'images/face_beep.png'\n}\nThe application will choose one of these options at random each time you open a new tab. This pattern is used for everything in the config file. You give the application groups of choices, and it chooses one at random each time it loads. The only thing that\u2019s special about the faces object is that person\u2019s name will also be displayed when their face is chosen.\nNow, when you refresh the project in Chrome, you should see one of your friends along with their name, like this:\n\nCongrats, you\u2019re off and running!\nStep 2: Add adjectives\nNow that you\u2019ve loaded your friends into the application, it\u2019s time to call them names. This step definitely yields the most laughs for the least amount of effort.\nAdd a list of adjectives into the prefixes array in config.js. To get the words flowing, I took inspiration from ways I might describe some of my relatives during a holiday gathering\u2026\nprefixes: [\n 'Loving',\n 'Drunk',\n 'Chatty',\n 'Merry',\n 'Creepy',\n 'Introspective',\n 'Cheerful',\n 'Awkward',\n 'Unrelatable',\n 'Hungry',\n ...\n]\nWhen you refresh Chrome, you should see one of these words prefixed before your friend\u2019s name. Voila!\n\nStep 3: Choose your color palette\nReal talk: I\u2019m bad at choosing color palettes, so I have a trick up my sleeve that I want to share with you. If you\u2019ve been blessed with the gift of color aptitude, skip ahead.\nHow to choose colors\nTo create a color palette, I start by going to a Coolors.co, and I hit the spacebar until I find a palette that I like. We need a wide gamut of hues for our palette, so lock down colors you like and keep hitting the spacebar until you find a nice, full range. You can use as many or as few colors as you like.\nCopy these colors into your swatches in Adobe Illustrator. They\u2019ll be the base for any illustrations you create later.\nNow you need a set of background colors. Here\u2019s my trick to making these consistent with your illustration palette without completely blending in. Use the \u201cAdjust Palette\u201d tool in Coolors to dial up the brightness a few notches, and the saturation down just a tad to remove any neon effect. These will be your background colors.\n\nAdd your background colors to config.js\nCopy your hex codes into the bgColors array in config.js.\nbgColors: [\n '#FFDD77',\n '#FF8E72',\n '#ED5E84',\n '#4CE0B3',\n '#9893DA',\n ...\n]\nNow when you go back to Chrome and refresh the page, you\u2019ll see your new palette!\n\nStep 4: Accessorize\nThis is the fun part. We\u2019re going to illustrate objects, accessories, lizards\u2014whatever you want\u2014and layer them on top of your friends.\nYour objects will be categorized into groups, and one option from each group will be randomly chosen each time you load the page. Think of a group like \u201chats\u201d or \u201cglasses\u201d. This will allow combinations of accessories to show at once, without showing two of the same type on the same person.\nCreate a group of accessories\nTo get started, open up Illustrator and create a new artboard out of the template. Think of a group of objects that you can riff on. I found hats to be a good place to start. If you don\u2019t feel like illustrating, you can use cut-out images instead.\n\nNext, follow the same steps as you did when you exported the faces. Here they are again:\n\nTurn the Template layer off and export the images as PNGs. \nIn the Export dialog, tick the \u201cUse Artboards\u201d checkbox and enter the range with your hats. \nExport at 72ppi to keep things running fast. \nSave your images into the images/ folder in your project.\n\nAdd your accessories to config.js\nIn config.js, add a new key to the customProps object that describes the group of accessories that you just created. Its value should be an array of the filepaths to your images. This is my hats array:\ncustomProps: {\n hats: [ \n 'images/hat_crown.png',\n 'images/hat_santa.png',\n 'images/hat_tophat.png',\n 'images/hat_antlers.png'\n ]\n}\nRefresh Chrome and behold, accessories!\n\nCreate as many more accessories as you want\nRepeat the steps above to create as many groups of accessories as you want. I went on to make glasses and hairstyles, so my final illustrator file looks like this:\n\nThe last step is adding your new groups to the config object. List your groups in the order that you want them to be stacked in the DOM. My final output will be hair, then hats, then glasses:\ncustomProps: {\n hair: [ \n 'images/hair_bowl.png',\n 'images/hair_bob.png'\n ], \n hats: [ \n 'images/hat_crown.png',\n 'images/hat_santa.png',\n 'images/hat_tophat.png',\n 'images/hat_antlers.png'\n ],\n glasses: [\n 'images/glasses_aviators.png',\n 'images/glasses_monacle.png'\n ]\n}\nAnd, there you have it! Randomly generated friends with random accessories. \n\nFeel free to go much crazier than I did. I considered adding a whole group of animals in celebration of the new season of Planet Earth, or even adding Sir David Attenborough himself, or doing a bit of role reversal and featuring the animals with little safari hats! But I digress\u2026\nStep 5: Publish it\nIt\u2019s time to put this in your new tabs! You have two options:\n\nPublish it as a Chrome extension in the Chrome Web Store.\nHost it as a website and point to it with the New Tab Redirect extension.\n\nToday, we\u2019re going to cover Option #1 because I want to show you how to make the simplest Chrome extension possible. However, I recommend Option #2 if you want to keep your project private. Every Chrome extension that you publish is made publicly available, so unless your friends want their faces published to an extension that anyone can use, I\u2019d suggest sticking to Option #2.\nHow to make a simple Chrome extension to replace the new tab page\nAll you need to do to make your project into a Chrome extension is add a manifest.json file to the root of your project with the following contents. There are plenty of other properties that you can add to your manifest file, but these are the only ones that are required for a new tab replacement:\n{\n \"manifest_version\": 2,\n \"name\": \"Your extension name\",\n \"version\": \"1.0\",\n \"chrome_url_overrides\" : {\n \"newtab\": \"index.html\"\n }\n}\nTo test your extension, you\u2019ll need to run it in Developer Mode. Here\u2019s how to do that:\n\nGo to the Extensions page in Chrome by navigating to chrome://extensions/.\nTick the checkbox in the upper-right corner labelled \u201cDeveloper Mode\u201d.\nClick \u201cLoad unpacked extension\u2026\u201d and select this project.\nIf everything is running smoothly, you should see your project when you open a new tab. If there are any errors, they should appear in a yellow box on the Extensions page.\n\nVoila! Like I said, this is a very light example of a Chrome extension, but Google has tons of great documentation on how to take things further. Check it out and see what inspires you.\nShare the love\nNow that you know how to make a new tab extension, go forth and create! But wield your power responsibly. New tabs are opened so often that they\u2019ve become a part of everyday life\u2013just consider how many tabs you opened today. Some people prefer to-do lists in their tabs, and others prefer cats. \nAt the end of the day, let\u2019s make something that makes us happy. Cheers!", "year": "2016", "author": "Leslie Zacharkow", "author_slug": "lesliezacharkow", "published": "2016-12-08T00:00:00+00:00", "url": "https://24ways.org/2016/how-to-make-a-chrome-extension/", "topic": "code"}
{"rowid": 299, "title": "What the Heck Is Inclusive Design?", "contents": "Naming things is hard. And I don\u2019t just mean CSS class names and JSON properties. Finding the right term for what we do with the time we spend awake and out of bed turns out to be really hard too.\nI\u2019ve variously gone by \u201cfront-end developer\u201d, \u201cuser experience designer\u201d, and \u201caccessibility engineer\u201d, all clumsy and incomplete terms for labeling what I do as an\u2026 erm\u2026 see, there\u2019s the problem again.\nIt\u2019s tempting to give up entirely on trying to find the right words for things, but this risks summarily dispensing with thousands of years spent trying to qualify the world around us. So here we are again.\nRecently, I\u2019ve been using the term \u201cinclusive design\u201d and calling myself an \u201cinclusive designer\u201d a lot. I\u2019m not sure where I first heard it or who came up with it, but the terminology feels like a good fit for the kind of stuff I care to do when I\u2019m not at a pub or asleep.\nThis article is about what I think \u201cinclusive design\u201d means and why I think you might like it as an idea.\nIsn\u2019t \u2018inclusive design\u2019 just \u2018accessibility\u2019 by another name?\nNo, I don\u2019t think so. But that\u2019s not to say the two concepts aren\u2019t related. Note the \u2018design\u2019 part in \u2018inclusive design\u2019 \u2014 that\u2019s not just there by accident. Inclusive design describes a design activity; a way of designing things.\nThis sets it apart from accessibility \u2014 or at least our expectations of what \u2018accessibility\u2019 entails. Despite every single accessibility expert I know (and I know a lot) recommending that accessibility should be integrated into design process, it is rarely ever done. Instead, it is relegated to an afterthought, limiting its effect.\nThe term \u2018accessibility\u2019 therefore lacks the power to connote design process. It\u2019s not that we haven\u2019t tried to salvage the term, but it\u2019s beginning to look like a lost cause. So maybe let\u2019s use a new term, because new things take new names. People get that.\nThe \u2018access\u2019 part of accessibility is also problematic. Before we get ahead of ourselves, I don\u2019t mean access is a problem \u2014 access is good, and the more accessible something is the better. I mean it\u2019s not enough by itself.\nImagine a website filled with poorly written and lackadaisically organized information, including a bunch of convoluted and confusing functionality. To make this site accessible is to ensure no barriers prevent people from accessing the content. \nBut that doesn\u2019t make the content any better. It just means more people get to suffer it. \nWhoopdidoo.\nAccess is certainly a prerequisite of inclusion, but accessibility compliance doesn\u2019t get you all the way there. It\u2019s possible to check all the boxes but still be left with an unusable interface. And unusable interfaces are necessarily inaccessible ones. Sure, you can take an unusable interface and make it accessibility compliant, but that only placates stakeholders\u2019 lawyers, not users. Users get little value from it.\nSo where have we got to? Access is important, but inclusion is bigger than access. Inclusive design means making something valuable, not just accessible, to as many people as we can.\nSo inclusive design is kind of accessibility + UX?\nCloser, but there are some problems with this definition.\nUX is, you will have already noted, a broad term encompassing activities ranging from conducting research studies to optimizing the perceived affordance of interface elements. But overall, what I take from UX is that it\u2019s the pursuit of making interfaces understandable.\nAs it happens, WCAG 2.0 already contains an \u2018Understandable\u2019 principle covering provisions such as readability, predictability and feedback. So you might say accessibility \u2014 at least as described by WCAG \u2014 already covers UX.\nUnfortunately, the criteria are limited, plus some really important stuff (like readability) is relegated to the AAA level; essentially \u201cbonus points if you get the time (you won\u2019t).\u201d\nSo better to let UX folks take care of this kind of thing. It\u2019s what they do. Except, therein lies a danger. UX professionals don\u2019t tend to be well versed in accessibility, so their \u2018solutions\u2019 don\u2019t tend to work for that many people. My friend Billy Gregory coined the term SUX, or \u201cSome UX\u201d: if it doesn\u2019t work for different users, it\u2019s only doing part of the job it should be. \nSUX won\u2019t do, but it\u2019s not just a disability issue. All sorts of user circumstances go unchecked when you\u2019re shooting straight for what people like, and bypassing what people need: device type, device settings, network quality, location, native language, and available time to name just a few.\nIn short, inclusive design means designing things for people who aren\u2019t you, in your situation. In my experience, mainstream UX isn\u2019t very good at that. By bolting accessibility onto mainstream UX we labor under the misapprehension that most people have a \u2018normal\u2019 experience, a few people are exceptions, and that all of the exceptions pertain to disability directly.\nSo inclusive design isn\u2019t really about disability?\nIt is about disability, but not in the same way as accessibility. Accessibility (as it is typically understood, anyway) aims to make sure things work for people with clinically recognized disabilities. Inclusive design aims to make sure things work for people, not forgetting those with clinically recognized disabilities. A subtle, but not so subtle, difference.\nLet\u2019s go back to discussing readability, because that\u2019s a good example. Now: everyone benefits from readable text; text with concise sentences and widely-understood words. It certainly helps people with cognitive impairments, but it doesn\u2019t hinder folks who have less trouble with comprehension. In fact, they\u2019ll more than likely be thankful for the time saved and the clarity. Readable text covers the whole gamut. It\u2019s \u2014 you\u2019ve got it \u2014 inclusive.\nLegibility is another one. A clear, well-balanced typeface makes the reading experience less uncomfortable and frustrating for all concerned, including those who have various forms of visual dyslexia. Again, everyone\u2019s happy \u2014 so why even contemplate a squiggly, sketchy typeface? Leave well alone.\nContrast too. No one benefits from low contrast; everyone benefits from high contrast. Simple. There\u2019s no more work involved, it just entails better decision making. And that\u2019s what design is really: decision making.\nHow about zoom support? If you let your users pinch zoom on their phones they can compensate for poor eyesight, but they can also increase the touch area of controls, inspect detail in images, and compose better screen shots. Unobtrusively supporting options like zoom makes interfaces much more inclusive at very little cost.\nAnd when it comes to the underlying HTML code, you\u2019re in luck: it has already been designed, from the outset, to be inclusive. HTML is a toolkit for inclusion. Using the right elements for the job doesn\u2019t just mean the few who use screen readers benefit, but keyboard accessibility comes out-of-the-box, you can defer to browser behavior rather than writing additional scripts, the code is easier to read and maintain, and editors can create content that is effortlessly presentable. \nWait\u2026 are you talking about universal design?\nHmmm. Yes, I guess some folks might think of \u201cuniversal design\u201d and \u201cinclusive design\u201d as synonymous. I just really don\u2019t like the term universal in this context. \nThe thing is, it gives the impression that you should be designing for absolutely everyone in the universe. Though few would adopt a literal interpretation of \u201cuniversal\u201d in this context, there are enough developers who would deliberately misconstrue the term and decry universal design as an impossible task. I\u2019ve actually had people push back by saying, \u201cwhat, so I\u2019ve got to make it work for people who are allergic to computers? What about people in comas?\u201d\nFor everyone\u2019s sake, I think the term \u2018inclusive\u2019 is less misleading. Of course you can\u2019t make things that everybody can use \u2014 it\u2019s okay, that\u2019s not the aim. But with everything that\u2019s possible with web technologies, there\u2019s really no need to exclude people in the vast numbers that we usually are. \nAccessibility can never be perfect, but by thinking inclusively from planning, through prototyping to production, you can cast a much wider net. That means more and happier users at very little if any more effort.\nIf you like, inclusive design is the means and accessibility is the end \u2014 it\u2019s just that you get a lot more than just accessibility along the way.\nConclusion\nThat\u2019s inclusive design. Or at least, that\u2019s a definition for a thing I think is a good idea which I identify as inclusive design. I\u2019ll leave you with a few tips.\nInvolve code early\nWeb interfaces are made of code. If you\u2019re not working with code, you\u2019re not working on the interface. That\u2019s not to say there\u2019s anything wrong with sketching or paper prototyping \u2014 in fact, I recommend paper prototyping in my book on inclusive design. Just work with code as soon as you can, and think about code even before that. Maintain a pattern library of coded solutions and omit any solutions that don\u2019t adhere to basic accessibility guidelines.\nRespect conventions\nYour content should be fresh, inventive, radical. Your interface shouldn\u2019t. Adopt accepted conventions in the appearance, placement and coding of interface elements. Users aren\u2019t there to experience interface design; they\u2019re there to use an interface. In other words: stop showing off (unless, of course, the brief is to experiment with new paradigms in interface design, for an audience of interface design researchers).\nDon\u2019t be exact\n\u201cPerfection is the enemy of good\u201d. But the pursuit of perfection isn\u2019t just to be avoided because nothing ever gets finished. Exacting design also makes things inflexible and brittle. If your design depends on elements retaining precise coordinates, they\u2019ll break easily when your users start adjusting font settings or zooming. Choose not to position elements exactly or give them fixed, \u201cmagic number\u201d dimensions. Make less decisions in the interface so your users can make more decisions for it.\nEnforce simplicity\nThe virtue of simplicity is difficult to overestimate. The simpler an interface is, the easier it is to use for all kinds of users. Simpler interfaces require less code to make too, so there\u2019s an obvious performance advantage. There are many design decisions that require user research, but keeping things simple is always the right thing to do. Not simplified or simple-seeming or simplistic, but simple. \nDo a little and do it well, for as many people as you can.", "year": "2016", "author": "Heydon Pickering", "author_slug": "heydonpickering", "published": "2016-12-07T00:00:00+00:00", "url": "https://24ways.org/2016/what-the-heck-is-inclusive-design/", "topic": "process"}
{"rowid": 297, "title": "Public Speaking with a Buddy", "contents": "My book Demystifying Public Speaking focuses on the variety of fears we each have about giving a talk. From presenting to a client, to leading a team standup, to standing on a conference stage, there are lots of things we can do to prepare ourselves for the spotlight and reduce those fears.\nThough it didn\u2019t make it into the final draft, I wanted to highlight how helpful it can be to share that public speaking spotlight with another person, or a few more people. If you have fears about not knowing the answer to a question, fumbling your words, or making a mistake in the spotlight, then buddying up may be for you!\n\nTo some, adding more people to a presentation sounds like a recipe for on-stage disaster. To others, having a friendly face nearby\u2014a partner who can step in if you fumble\u2014is incredibly reassuring. As design director Yesenia Perez-Cruz writes, \u201cWhile public speaking is a deeply personal activity, you don\u2019t have to go it alone. Nothing has helped my speaking career more than turning it into a group effort.\u201d\nCo-presenting can level up a talk in two ways: an additional brain and presentation skill set can improve the content of the talk itself, and you may feel safer with the on-stage safety net of your buddy. \nFor example, when I started giving lengthy workshops about building mobile device labs with my co-worker Destiny Montague, we brought different experience to the table. I was able to talk about the user experience of our lab, and the importance of testing across different screen sizes. Destiny spoke about the hardware aspects of the lab, like power consumption and networking. Our audience benefitted from the spectrum of insight we included in the talk.\nMoreover, Destiny and I kept each other energized and engaging while teaching our audience, having way more fun onstage. Partnering up alleviated the risk (and fear!) of fumbling; where one person makes a mistake, the other person is right there to help. Buddy presentations can be helpful if you fear saying \u201cI don\u2019t know\u201d to a question, as there are other people around you who will be able to help answer it from the stage. By partnering with someone whom I trust and respect, and whose work and knowledge augments my own, it made the experience\u2014and the presentation!\u2014significantly better.\nCo-presenting won\u2019t work if you don\u2019t trust the person you\u2019re onstage with, or if you don\u2019t have good chemistry working together. It might also not work if there\u2019s an imbalance of responsibilities, both in preparing the talk and giving it. Read on for how to make partner talks work to your advantage!\nTrustworthiness\nIf you want to explore co-presenting, make sure that your presentation partner is trustworthy and can carry their weight; it can be stressful if you find yourself trying to meet deadlines and prepare well and your partner isn\u2019t being helpful. We\u2019re all about reducing the fears and stress levels surrounding being in that spotlight onstage; make sure that the person you\u2019re relying on isn\u2019t making the process harder.\nBefore you start working together, sketch out the breakdown of work and timeline you\u2019re each committing to. Have a conversation about your preferred work style so you each have a concrete understanding of the best ways to communicate (in what medium, and how often) and how to check in on each other\u2019s progress without micromanaging or worrying about radio silence. Ask your buddy how they prefer to receive feedback, and give them your own feedback preferences, so neither of you are surprised or offended when someone\u2019s work style or deliverable needs to be tweaked.\nThis should be a partnership in which you both feel supported; it\u2019s healthy to set all these expectations up front, and create a space in which you can each tweak things as the work progresses.\nTalk flow and responsibilities\nThere are a few different ways to organize the structure of your talk with multiple presenters. Start by thinking about the breakdown of the talk content\u2014are there discrete parts you and the other presenters can own or deliver? Or does it feel more appropriate to deliver the entirety of the content together?\nIf you\u2019re finding that you can break down the content into discrete chunks, figure out who should own which pieces, and what ownership means. Will you develop the content together but have only one person present the information? Or will one person research and prepare each content section in addition to delivering it solo onstage?\nRehearse how handoffs will go between sections so it feels natural, rather than stilted. I like breaking a presentation into \u201cchapters\u201d when I\u2019m passionate about particular aspects of a topic and can speak on those, but know that there are other aspects to be shared and there\u2019s someone else who can handle (and enjoy!) talking about them. When Destiny and I rehearsed our \u201cchapter\u201d handoffs, we developed little jingles that we\u2019d both sing together onstage; it indicated to the audience that it was a planned transition in the content, and tied our independent work together into a partnership.\n.embed-container { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; } .embed-container iframe, .embed-container object, .embed-container embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }\n\n\n\nAlternatively, you can give the presentation in a way that\u2019s close to having a rehearsed conversation, rather than independently presenting discrete parts of the talk. In this case, you\u2019ll both be sharing the spotlight at the same time, throughout the duration of the talk. Preparation is key, here, to make sure that you each understand what needs to be communicated, and you have a sense of who will be taking responsibility for communicating those different pieces of information. A poorly-prepared talk like this will look like the co-presenters are talking over each other, or hesitating awkwardly to give the other person more room to speak; the audience will feel how uncomfortable this is, and will probably be distracted from the talk content. Practice the talk the whole way through multiple times so you know what each person is planning on covering and how you want to interact with each other while you\u2019re both holding microphones; also figure out how you\u2019ll be standing in relation to each other. More on that next!\nSharing the stage\nIf you choose to give a talk with a partner, determine ahead of time how you\u2019ll stand (or sit). For example, if you each take \u201cchapters\u201d or major sections of the presentation, ensure that it\u2019s clear who the audience should focus their attention on. You could sit in a chair off to the side (or stand). I recommend placing yourself far enough away that you\u2019re not distracting to the audience; you don\u2019t want them watching you while your partner is speaking. If the audience can still see you, but their focus should be on your buddy, be sure to not look distracted; keep your eyes on your buddy, and don\u2019t just open your laptop and ignore what\u2019s happening! Feel free to smile, laugh, or react how the audience should be reacting as your partner is speaking.\nIf you\u2019re both sharing the spotlight at the same time and having a rehearsed conversation, make sure that your body language engages the audience and you\u2019re not just speaking to each other, ignoring the folks watching. Watch this talk with Guy Podjarny and Assaf Hefetz who have partnered up to talk about security; they have clearly identified roles onstage, and remain engaged with the audience.\n\nConsider whether or not you will share a microphone, or if you will both be mic\u2019d. (Be sure that the event organizer, or the A/V team, has a heads-up well in advance to ensure they have the equipment handy!) Also talk through how you\u2019d like to handle Q&A time during or after the talk, especially if you have clear \u201cchapters\u201d where Q&A might happen naturally during a handoff. The more clarity you and your partner have about who is responsible for which pieces of information sharing, the more you can feel and appear prepared.\nCo-presenting does take a lot of preparation and requires a ton of communication between you and your partner. But the rewards can be awesome: double the brains onstage to help answer questions and communicate information, and a friendly face to help comfort you if you feel nervous.", "year": "2016", "author": "Lara Hogan", "author_slug": "larahogan", "published": "2016-12-06T00:00:00+00:00", "url": "https://24ways.org/2016/public-speaking-with-a-buddy/", "topic": "process"}
{"rowid": 303, "title": "We Need to Talk About Technical Debt", "contents": "In my work with clients, a lot of time is spent assessing old, legacy, sprawling systems and identifying good code, bad code, and technical debt.\nOne thing that constantly strikes me is the frequency with which bad code and technical debt are conflated, so let me start by saying this:\nNot all technical debt is bad code, and not all bad code is technical debt.\nSometimes your bad code is just that: bad code. Calling it technical debt often feels like a more forgiving and friendly way of referring to what may have just been a poor implementation or a substandard piece of work.\nIt is an oft-misunderstood phrase, and when mistaken for meaning \u2018anything legacy or old hacky or nasty or bad\u2019, technical debt is swept under the carpet along with all of the other parts of the codebase we\u2019d rather not talk about, and therein lies the problem.\nWe need to talk about technical debt.\nWhat We Talk About When We Talk About Technical Debt\nThe thing that separates technical debt from the rest of the hacky code in our project is the fact that technical debt, by definition, is something that we knowingly and strategically entered into. Debt doesn\u2019t happen by accident: debt happens when we choose to gain something otherwise-unattainable immediately in return for paying it back (with interest) later on.\nAn Example\nYou\u2019re a front-end developer working on a SaaS product, and your sales team is courting a large customer \u2013 a customer so large that you can\u2019t really afford to lose them. The customer tells you that as long as you can allow them to theme your SaaS application according to their branding, they are willing to sign on the dotted line\u2026 the problem being that your CSS architecture was never designed to incorporate theming at all, and there isn\u2019t currently a nice, clean way to incorporate a theme into the codebase.\nYou and the business make the decision that you will hack a theme into the product in two days. It\u2019s going to be messy, it\u2019s going to be ugly, but you can\u2019t afford to lose a huge customer just because your CSS isn\u2019t quite right, right now. This is technical debt.\nYou deliver the theme, the customer signs up, and everyone is happy. Except you (and the business, because you are one and the same) have a decision to make:\n\nDo we go back and build theming into the CSS architecture as a first-class citizen, porting the hacked theme back into a codified and formal framework?\nDo we carry on as we are? Things are working okay, and the customer paid up, so is there any reason to invest time and effort into things after we (and the customer) got what we wanted?\n\nOption 1 is choosing to pay off your debts; Option 2 is ignoring your repayments.\nWith Option 1, you\u2019re acknowledging that you did what you could given the constraints, but, free of constraints, you\u2019d have done something different. Now, you are choosing to implement that something different.\nWith Option 2, however, you are avoiding your responsibility to repay your debt, and you are letting interest accrue. The problem here is that\u2026\n\nyour SaaS product now offers theming to one of your customers;\nanother potential customer might also demand the ability to theme their instance of your product;\nyou can\u2019t refuse them that request, nor can you quickly fulfil it;\nyou hack in another theme, thus adding to the balance of your existing debt;\nand so on (plus interest) for every subsequent theme you need to implement.\n\nHere you have increased entropy whilst making little to no attempt to address what you already knew to be problems.\nYour second, third, fourth, fifth request for theming will be hacked on top of your hack, further accumulating debt whilst offering nothing by way of a repayment. After a long enough period, the code involved will get so unwieldy, so hard to work with, that you are forced to tear it all down and start again, and the most painful part of this is that you\u2019re actually paying off even more than your debt repayments would have been in the first place. Two days of hacking plus, say, five days of subsequent refactoring, would still have been substantially less than the weeks you will now have to spend rewriting your CSS to fix and incorporate the themes properly. You\u2019ve made a loss; your strategic debt ultimately became a loss-making exercise.\nThe important thing to note here is that you didn\u2019t necessarily write bad code. You knew there were two options: the quick way and the correct way. The decision to take the quick route was a definite choice, because you knew there was a better way. Implementing the better way is your repayment.\nGood Debt and Bad Debt\nTechnical debt is acceptable as long as you have intentions to settle; it can be a valuable solution to a business problem, provided the right approach is taken afterwards. That doesn\u2019t, however, mean that all debt is born equal. Just as in real life, there is good debt and there is bad debt.\nGood debt might be\u2026\n\na mortgage;\na student loan, or;\na business loan.\n\nThese are types of debt that will secure you the means of repaying them. These are well considered debts whose very reason for being will allow you to make the money to pay them off\u2014they have real, tangible benefit.\nA business loan to secure some equipment and premises will allow you to start an enterprise whose revenue will allow you to pay that debt back; a student loan will allow you to secure the kind of job that has the ability to pay a student loan back.\nThese kinds of debt involve a considered and well-balanced decision to acquire something in the short term in the knowledge that you will have the means, in the long term, to pay it back.\nConversely, bad debt might be\u2026\n\nborrowing $1,000 from a loan shark so you can go to Vegas, or;\ntaking out a payday loan in order to buy a new television.\n\nBoth of these kinds of debt will leave you paying for things that didn\u2019t provide you a way of earning your own capital. That is to say, the loans taken did not secure anything that would help pay off said loans. These are bad debts that will usually provide a net loss. You really are only gaining the short term in exchange for a long term financial responsibility: i.e., was it worth it?\nA good litmus test for debt is to compare the gains of its immediate benefit with the cost of its long term commitment.\nThe earlier example of theming a site is a good debt, provided we are keeping up our repayments (all debt is bad debt if you don\u2019t). A calculated decision to do something \u2018wrong\u2019 in the short term with the promise of better payoffs later on.\nBad Technical Debt\nThe majority of my work is with front-end development teams\u2014CSS is what I do. To that end, the most succinct example of technical debt for that audience is simply:\n!important\nAll front-end developers know the horrors and dangers associated with using !important, yet we continue to use it. Why?\nIt\u2019s not necessarily because we\u2019re bad developers, but because we see a shortcut. !important is usually implemented as a quick way out of a sticky specificity situation. We could spend the rest of the day refactoring our CSS to fix the issue at its source, or we can spend mere seconds typing the word !important and patch over the symptoms.\nThis is us making an explicit decision to do something less than ideal now in exchange for immediate benefit. After all, refactoring our CSS will take a lot more time, and will still only leave us with the same outcome that the vastly quicker !important solution will, so it seems to make better business sense.\nHowever, this is a bad debt. !important takes seconds to implement but weeks to refactor. The cost of refactoring this back out later will be an order of magnitude higher than it would be to have done things properly the first time. The first !important usually sets a precedent, and subsequent developers are likely to have to use it themselves in order to get around the one that you left.\nSo many CSS projects deteriorate because of this one simple word, and rewrites become more and more imminent. That makes it possibly the most costly 10 bytes a CSS developer could ever write.\nBad Code\nNow we\u2019ve got a good idea of what constitutes technical debt, let\u2019s take a look at what constitutes bad code. Something I hear time and time again in my client work goes a little like this:\n\nWe\u2019ve amassed a lot of technical debt and we\u2019d like to get a strategy in place\nto begin dealing with it.\n\nWhilst I genuinely admire their willingness to identify and desire to fix problems in their code, sometimes they\u2019re not looking at technical debt at\nall\u2014sometimes they\u2019re just looking at bad code, plain and simple.\nWhere technical debt is knowing that there\u2019s a better way, but the quicker way makes more sense right now, bad code is not caring if there\u2019s a better way at all.\nAgain, looking at a CSS-specific world, a lot of bad code is contributed by non-front-end developers with little training, appreciation, or even respect for the front-end landscape. Writing code with reckless abandon should not be described as technical debt, because to do so would imply that\u2026\n\nthe developers knew they were implementing a sub-par solution, but\u2026\nthe developers also knew that a better solution was out there, which\u2026\nimplies that it can be tidied up relatively simply.\n\nDevelopers writing bad code is a larger and more cultural problem that requires a lot more effort to fix. Hopefully\u2014and usually\u2014bad code is in the minority, but it helps to be objective in identifying and solving it. Bad code usually doesn\u2019t happen for a good enough reason, and is therefore much harder to justify.\nTechnical debt often represents ability in judgement, whereas bad code often represents a gap in skills.\nTakeaway\nTake time to familiarise yourself with the true concepts underlying technical debt and why it exists. Understand that technical debt can be good or bad. Admit that sometimes code is just of poor quality.\nUnderstanding these points will allow you to make better calls around what you might need to refactor and when, and what skills gaps you might have in your team.\n\nSometimes it\u2019s okay to cut corners if there is a tangible gain to be had in the immediate term.\nTechnical debt is okay provided it is a sensible debt and you have intentions to pay it off.\nTechnical debt is not necessarily synonymous with bad code, and bad code isn\u2019t necessarily technical debt. Technical debt is code that was implemented given limited knowledge or resource, with the understanding that you would need to repay something in future.\nTechnical debt is not inherently bad\u2014failure to make repayments is. Periodically, it is justifiable\u2014encouraged, even\u2014to enter a debt in order to fulfil a more pressing matter. However, it is imperative that we begin making repayments as soon as we are capable, be that based on newly available time or knowledge.\nBad code is worse than technical debt as it represents a lack of knowledge or quality control within a team. It needs a much more fundamental fix.", "year": "2016", "author": "Harry Roberts", "author_slug": "harryroberts", "published": "2016-12-05T00:00:00+00:00", "url": "https://24ways.org/2016/we-need-to-talk-about-technical-debt/", "topic": "code"}
{"rowid": 302, "title": "Flexible Project Management in Inflexible Environments", "contents": "Handling unforeseen circumstances is an inevitable part of any project. It\u2019s also often the most uncomfortable, and there is no amount of skill or planning that will fully eradicate the need to adapt to change. The ability to be flexible, responsive, and unafraid of facing not only problems, but also potentially positive scope changes and new ideas, isn\u2019t an easy one to master. I am by no means saying that I have, but what I have learned is that there is often the temptation to shut out anything that might derail your plan, even sometimes at the cost of the quality you\u2019re committed to.\nThe reality is that as someone leading a project you know there will be challenges, but, in general, it\u2019s a hassle to try keep the landscape open. Problems are bridges we should cross when we come to them, but intentional changes to the plan, and adapting for the sake of improving your first idea, is harder. There are tight schedules, resource is planned miles ahead, and you\u2019re already juggling twenty other things. If you\u2019re passionate about the quality of work you deliver and are working somewhere that considers itself expert within the field of digital, then having an attitude of flexibility is extremely important. It\u2019s important when you\u2019re overcoming a challenge or problem, but it\u2019s also important for allowing ideas to evolve and be refined as much as they can be throughout the course of a project.\nWhere theory falls short\nThe premise of any Agile methodology, Scrum for example, is based around being able to work efficiently, react quickly and deliver relevant chunks of a product in manageable increments. It\u2019s often hailed as king of flexible management and it can work really well, especially for in-house software products developed over a long or even an indefinite period of time. It holds off defining scope too far ahead and lets teams focus on smaller amounts of work, and allows them to regularly reprioritise. Unfortunately though, not all environments lend themselves as easily to a fully Agile setup. Even the ones that do may be restrained from putting it fully into practice for an array of other internal reasons.\nDelivering digital services to clients\u2014within an agency setting or as a freelancer\u2014often demands a more rigid structure. You need clear sign-off points, there\u2019s a lot less flexibility in defining features, or working within budgets and timeframes. To start with, for a project to warrant a fully Agile team working on it, and especially for agencies, you need clients big enough and rich enough to justify the resource. You also need a lot of client trust to propose defining features and scope as you go. Although this is achievable\u2014and there are agencies that operate an agile setup\u2014it takes a long journey to reach that scale in the full sense of the word. Building a reputation that commands unconditional trust and reaching the point where your projects are consistently of a certain size often requires backing by long journey of success and excellence.\nSo there is a lot of room left for understanding how we can best strive to still deliver excellent projects within more constrained structures. We know that rigid waterfall planning, more often than not, falls over as soon as a project gets anything past a basic brochure site. There are many critiques of the system, but one of the main ones tends to be that nobody considers each other\u2019s work properly, which can result in very expensive and inefficient development.\nEqually, for reasons we\u2019ve already touched upon, running fully agile teams often isn\u2019t the right answer. So many companies, individuals, and organisations look for a middle-ground that balances being flexible and adaptive, but also provides enough upfront commitment to agree budgets, get client/stakeholder sign off, and effectively coordinate internal resource across multiple parallel projects.\nAlthough I don\u2019t have a perfect formula\u2014and can very much assert there is no one perfect way of managing a project because every project is different to the next\u2014I\u2019ve identified a few different ways you can approach flexibility that have really helped me in running projects more smoothly within more realistic constraints.\nPlanned Flexibility\nDrawing on some of the traditional methodologies such as PRINCE2, a good starting point for aspiring to be flexible is by planning for it from the start.\nPlanning flexibility comes in a few forms. For one, you can regularly identify and log potential risks as a generally good, on-going habit over the course of the project. This essentially just involves scanning the horizon for potential blips on a regular basis (for example weekly) by consulting with your team and documenting it somewhere. It means you have a checkpoint when you sit down and make sure you\u2019re minimising what will or may catch you by surprise. A good time to do this is in a weekly catch up meeting. It\u2019s not going to fix all your problems, but it will make sure you have a head start on the ones you can see coming.\nOn the subject of team meetings, setting up recurring project events, including a weekly call, a weekly team meeting and (depending on the size of the project) I like to try also do a stand-up as often as possible. Keeping everyone involved and bought in to a project is going to help you infinitely when you need to spot a problem or manage changes to the plan. It will be the difference between your designer spotting an issue and making a mental note to \u2018tell you later\u2019, and them actually coming over to tell you directly and immediately. Despite the overhead of meetings, and looping people into stages that they aren\u2019t directly responsible for, the business benefits are chances for success are drastically increased. Planning in, and being aware of how important your team is, will help you be flexible.\nBuilding contingency (formally know as slack) into your project plan from the word go is another well-known and essential way of planning to be flexible. Your project plan will change a lot over the course of a project, but there are still the days that you estimate a job will take, and the days you should actually plan in. Most sensible management teams understand that budgets need to be agreed with this slack in mind or you will not be able to deliver a quality service. I believe that commercial awareness is one of the most valuable skills a project manager can have, but penny pinching will ruin client and team relationships, destroy buy-in and creativity, and often end you up with a much more expensive, hacky, and resented product.\nIt\u2019s not a justification to let budgets spiral out of control, but a way of thinking about the bigger picture and wider plan of the company itself. It\u2019s unlikely you want high staff turnover because everyone fell out while you were screaming money at them and they didn\u2019t feel like they could do a good job. It\u2019s also unlikely that you will be able to deliver quality products, which will win you a strong reputation and subsequently bigger and better projects. Evaluating risk factors and building in the right amount of slack from the start will give you more wriggle room when you need to adapt and react. On the flip side, also keeping an overview of the wider workload (that you\u2019re not necessarily responsible for), and knowing who to talk if resource is becoming free or needs filling, is another handy way of being able to react quickly and ensuring your management system is respected. You want pockets of backup time planned in, but you also want everyone being as productive as they can most of the time. Never run at 100% capacity: as soon as something does need to change, you\u2019re left with nowhere to move.\nTransparency\nHaving a client or stakeholder that trusts you is a really powerful aid in any regard, but especially so when you need to communicate an issue or new suggestion. Positioning yourself and your team as experts and taking the time to delve into the wider picture\u2014and the goals surrounding your client\u2019s reasons to commission the project in the first place\u2014will make you more valuable to them. Clients and stakeholders will always be different, and sometimes you will get people who are just plain difficult, but more often than not people will listen if you\u2019re willing to talk and explain things.\nAs I\u2019m sure all of us have realised at one point or another, a lot of people think they know what they want, and it\u2019s usually the wrong thing. Managing key stakeholders in your project is arguably your biggest challenge, if they are on the your side and feel like the team is genuinely working to give them something of quality and value, then they will make your job easier. It\u2019s often down to you to educate them, and to help them recognise and understand the work involved and you and your team\u2019s reasoning behind your decisions.\nBeing overly submissive or overly secretive will foster a dynamic in which they feel expected to steer the project. In this situation they may not respect the team\u2019s suggestions or may come up with some unreasonable and counterproductive ideas that are likely to hinder progress and lower morale. Getting the stakeholder on board and making them feel a part of the wider picture will make things easier. Pushing back and challenging ideas or working hard to justify something they don\u2019t quite understand will often work in your favour and protects your team. On quite a basic level it also shows you care and are invested; on another, it shows you feel confident in your expertise within your field and that is ultimately the reason they hired you.\nTaking the time to think about and be aware of this relationship, will make it easier to be flexible and handle new ideas or suggestions that pop up as the project goes along. Change doesn\u2019t need to be \u2018scope creep\u2019 if it\u2019s raised in a practical, value-orientated, and level headed discussion. There is usually a way forward for new ideas, as long as they\u2019re valuable and support the wider goals. Maybe the deadline gets pushed back, maybe you get more budget, maybe the client is happy to forgo something else. As long as there\u2019s value and reason, it shows integrity to the project and respect for its success. You can\u2019t expect for this to go smoothly without having invested in the client relationship, so it\u2019s a large point in paving the way to handling change well.\nReactive Flexibility\nFinally, if you\u2019ve been doing this for a while, you\u2019ll know by now that you can\u2019t anticipate everything. Sometimes you will have to react and change the plan under circumstances that aren\u2019t easy. When an unexpected problem first rears its head\u2014a client\u2019s casual afterthought that\u2019s threatening the scope of the project, an internal resource conflict, a junior member of staff that\u2019s not grasping the ropes quite as quickly as you\u2019d hoped\u2014you have to react quickly.\nIn his book, \u2018Pitch Anything\u2019, Oren Klaff talks about people\u2019s first reactions being processed by their \u2018crocodile brain\u2019 before they\u2019ve had a chance to refine and digest the information more intelligibly. As project managers, product owners, or scrum masters, it\u2019s natural for our immediate reactions to an unexpected problem to cause a pang of stress. But after that initial jolt you need to turn to practical solutions and start racking your brain for different ways forward. It\u2019s here you need to remember to not let your imagination get the better of you, especially if you\u2019ve been putting in the legwork with your team and your client. There is always a way forward and moments like this can be a good opportunity to develop your negotiation and diplomacy skills. Don\u2019t let your immediate reaction be shutting the problem down; instead, take a second to think about it before you decide on the best direction. In a stressful situation, your first idea probably won\u2019t be your best one.\nFrom an internal point of view, it\u2019s very important that whatever went wrong doesn\u2019t turn into a finger pointing exercise and you don\u2019t lose your cool. Getting caught up in a blame game or a witch hunt is never productive. Relationship cultivating can sometimes be the pillar that gets you through a stressful blip. Biggest tip for staying flexible when you\u2019re reacting to a problem\u2014apart form obviously thinking of ways forward\u2014is to communicate. Don\u2019t go quiet until you feel like you have a plan, you\u2019ll often need to put everyone else at ease before you can move things forward. Problem solving is part of the job and will need to happen in even the most flexible of product delivery systems.\nIn conclusion, being flexible is never simple but there are things you can do to make your life easier. Owning a position of expertise, putting together a team that\u2019s involved in each other\u2019s work and cultivating a client/stakeholder relationship that\u2019s as transparent and respectful as possible will get you a long way. In times of crisis, believe in your skills and be open to adapting over getting frustrated.", "year": "2016", "author": "Gillian Sibthorpe", "author_slug": "gilliansibthorpe", "published": "2016-12-04T00:00:00+00:00", "url": "https://24ways.org/2016/flexible-project-management/", "topic": "process"}
{"rowid": 293, "title": "A Favor for Your Future Self", "contents": "We tend to think about the future when we build things. What might we want to be able to add later? How can we refactor this down the road? Will this be easy to maintain in six months, a year, two years? As best we can, we try to think about the what-ifs, and build our websites, systems, and applications with this lens. \nWe comment our code to explain what we knew at the time and how that impacted how we built something. We add to-dos to the things we want to change. These are all great things! Whether or not we come back to those to-dos, refactor that one thing, or add new features, we put in a bit of effort up front just in case to give us a bit of safety later.\nI want to talk about a situation that Past Alicia and Team couldn\u2019t even foresee or plan for. Recently, the startup I was a part of had to remove large sections of our website. Not just content, but entire pages and functionality. It wasn\u2019t a very pleasant experience, not only for the reason why we had to remove so much of what we had built, but also because it\u2019s the ultimate \u201cI really hope this doesn\u2019t break something else\u201d situation. It was a stressful and tedious effort of triple checking that the things we were removing weren\u2019t dependencies elsewhere. To be honest, we wouldn\u2019t have been able to do this with any amount of success or confidence without our test suite.\nWriting tests for code is one of those things that developers really, really don\u2019t want to do. It\u2019s one of the easiest things to cut in the development process, and there\u2019s often a struggle to have developers start writing tests in the first place. One of the best lessons the web has taught us is that we can\u2019t, in good faith, trust the happy path. We must make sure ourselves, and our users, aren\u2019t in a tough spot later on because we only thought of the best case scenarios.\nJavaScript\nRegardless of your opinion on whether or not everything needs to be built primarily with JavaScript, if you\u2019re choosing to build a JavaScript heavy app, you absolutely should be writing some combination of unit and integration tests.\nUnit tests are for testing extremely isolated and small pieces of code, which we refer to as the units themselves. Great for reused functions and small, scoped areas, this is the closest you examine your code with the testing microscope. For example, if we were to build a calculator, the most minute piece we could test could be the basic operations.\n/*\n * This example uses a test framework called Jasmine\n */\n\ndescribe(\"Calculator Operations\", function () {\n\n it(\"Should add two numbers\", function () {\n\n // Say we have a calculator\n Calculator.init();\n\n // We can run the function that does our addition calculation...\n var result = Calculator.addNumbers(7,3);\n\n // ...and ensure we're getting the right output\n expect(result).toBe(10);\n\n });\n});\nEven though these teeny bits work in isolation, we should ensure that connecting the large pieces work, as well. This is where integration tests excel. These tests ensure that two or more different areas of code, that may not directly know about each other, still behave in expected ways. Let\u2019s build upon our calculator - we may want the operations to be saved in memory after a calculation runs. This isn\u2019t as suited for a unit test because there are a few other moving pieces involved in the process (the calculations, checking if the result was an error, etc.).\n it(\u201cShould remember the last calculation\u201d, function () {\n\n // Run an operation\n Calculator.addNumbers(7,10);\n\n // Expect something else to have happened as a result\n expect(Calculator.updateCurrentValue).toHaveBeenCalled();\n expect(Calculator.currentValue).toBe(17);\n });\nUnit and integration tests provide assurance that your hand-rolled JavaScript should, for the most part, never fail in a grand fashion. Although it still might happen, you could be able to catch problems way sooner than without a test suite, and hopefully never push those failures to your production environment.\nInterfaces\nRegardless of how you\u2019re building something, it most definitely has some kind of interface. Whether you\u2019re using a very barebones structure, or you\u2019re leveraging a whole design system, these things can be tested as well.\nAcceptance testing helps us ensure that users can get from point A to point B within our web things, which can provide assurance that major features are always functioning properly. By simulating user input and data entry, we can go through whole user workflows to test for both success and failure scenarios. These are not necessarily for simulating edge-case scenarios, but rather ensuring that our core offerings are stable.\nFor example, if your site requires signup, you want to make sure the workflow is behaving as expected - allowing valid information to go through signup, while invalid information does not let you progress.\n/*\n * This example uses Jasmine along with an add-on called jasmine-integration\n */\n\ndescribe(\"Acceptance tests\", function () {\n\n // Go to our signup page\n var page = visit(\"/signup\");\n\n // Fill our signup form with invalid information\n page.fill_in(\"input[name='email']\", \"Not An Email\");\n page.fill_in(\"input[name='name']\", \"Alicia\");\n page.click(\"button[type=submit]\");\n\n // Check that we get an expected error message\n it(\"Shouldn't allow signup with invalid information\", function () {\n expect(page.find(\"#signupError\").hasClass(\"hidden\")).toBeFalsy();\n });\n\n // Now, fill our signup form with valid information\n page.fill_in(\"input[name='email']\", \"thisismyemail@gmail.com\");\n page.fill_in(\"input[name='name']\", \"Gerry\");\n page.click(\"button[type=submit]\");\n\n // Check that we get an expected success message and the error message is hidden\n it(\"Should allow signup with valid information\", function () {\n expect(page.find(\"#signupError\").hasClass(\"hidden\")).toBeTruthy();\n expect(page.find(\"#thankYouMessage\").hasClass(\"hidden\")).toBeFalsy();\n });\n});\nIn terms of visual design, we\u2019re now able to take snapshots of what our interfaces look like before and after any code changes to see what has changed. We call this visual regression testing. Rather than being a pass or fail test like our other examples thus far, this is more of an awareness test, intended to inform developers of all the visual differences that have occurred, intentional or not. Developers may accidentally introduce a styling change or fix that has unintended side effects on other areas of a website - visual regression testing helps us catch these sooner rather than later. These do require a bit more consistent grooming than other tests, but can be valuable in major CSS refactors or if your CSS is generally a bit like Jenga.\nTools like PhantomCSS will take screenshots of your pages, and do a visual comparison to check what has changed between two sets of images. The code would look something like this:\n/*\n * This example uses PhantomCSS\n */\n\ncasper.start(\"/home\").then(function(){\n\n // Initial state of form\n phantomcss.screenshot(\"#signUpForm\", \"sign up form\");\n\n // Hit the sign up button (should trigger error)\n casper.click(\"button#signUp\");\n\n // Take a screenshot of the UI component\n phantomcss.screenshot(\"#signUpForm\", \"sign up form error\");\n\n // Fill in form by name attributes & submit\n casper.fill(\"#signUpForm\", {\n name: \"Alicia Sedlock\",\n email: \"alicia@example.com\"\n }, true);\n\n // Take a second screenshot of success state\n phantomcss.screenshot(\"#signUpForm\", \"sign up form success\");\n});\nYou run this code before starting any development, to create your baseline set of screen captures. After you\u2019ve completed a batch of work, you run PhantomCSS again. This will create a second batch of screenshots, which are then put through an image comparison tool to display any differences that occurred. Say you changed your margins on our form elements \u2013 your image diff would look something like this:\n\nThis is a great tool for ensuring not just your site retains its expected styling, but it\u2019s also great for ensuring nothing accidentally changes in the living style guide or modular components you may have developed. It\u2019s hard to keep eagle eyes on every visual aspect of your site or app, so visual regression testing helps to keep these things monitored.\nConclusion\nThe shape and size of what you\u2019re testing for your site or app will vary. You may not need lots of unit or integration tests if you don\u2019t write a lot of JavaScript. You may not need visual regression testing for a one page site. It\u2019s important to assess your codebase to see which tests would provide the most benefit for you and your team.\nWriting tests isn\u2019t a joy for most developers, myself included. But I end up thanking Past Alicia a lot when there are tests, because otherwise I would have introduced a lot of issues into codebases. Shipping code that\u2019s broken breaks trust with our users, and it\u2019s our responsibility as developers to make sure that trust isn\u2019t broken. Testing shouldn\u2019t be considered a \u201cnice to have\u201d - it should be an integral piece of our workflow and our day-to-day job.", "year": "2016", "author": "Alicia Sedlock", "author_slug": "aliciasedlock", "published": "2016-12-03T00:00:00+00:00", "url": "https://24ways.org/2016/a-favor-for-your-future-self/", "topic": "code"}
{"rowid": 290, "title": "Creating a Weekly Research Cadence", "contents": "Working on a product team, it\u2019s 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.\nAs 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\u2014always 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.\nI wanted to find a way for our team to test ideas and validate assumptions sooner and more often\u2014but 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. \nSetting 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\u2014pushing us out of your comfort zone into a process of more rapid experimentation.\nBest 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 \u201cRemember what Jenna said last week, about not being able to customize her lists?\u201d 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.\nEstablishing an efficient recruitment process\nThe key to creating a regular cadence of ongoing user research is an efficient recruitment and scheduling process\u2014along 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. \nThe 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.\nPick a dedicated time each week for research\nIn 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\u2019t easy to do! Nevertheless, it\u2019s important to include as many people as possible in conversations with your users. Getting a second-hand summary of research results doesn\u2019t 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.\nI 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. \nDivide your time into several research slots\nAfter 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\u2019 busy schedules. Depending on your work, you may need schedule longer sessions\u2014but 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.\nI 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.\n\n\nInvite users to sign up for a time that\u2019s convenient for them\nWith 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\u2019re 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.\nSetting 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.\nIt may take a bit of experimentation to fine tune your process, but it\u2019s worth the effort to get it right. (The worst thing that\u2019s 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.\nGetting the most out of your research sessions\nAs you get comfortable with the rhythm of talking to users each week, you\u2019ll find more and more ways to get value out of your conversations. At first, you may prefer to just show work in progress\u2014such as mockups or a simple prototype\u2014and 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\u2014either 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\u2019s the best way to validate the assumptions your team is working from.\nWhatever you do, plan some time a day or two later to come back together and review what you\u2019ve 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. \nOver 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\u2019t 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\u2019re ready.", "year": "2016", "author": "Wren Lanier", "author_slug": "wrenlanier", "published": "2016-12-02T00:00:00+00:00", "url": "https://24ways.org/2016/creating-a-weekly-research-cadence/", "topic": "ux"}
{"rowid": 295, "title": "Internet of Stranger Things", "contents": "This year I\u2019ve 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\u2019m 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.\nWhat you\u2019ll see\nYou 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 \u201cSend a message\u201d button and wait your turn.)\n\n\n\n\nIt\u2019s all done with JavaScript, using Node.js running on both the Raspberry Pi and on the server. I\u2019m using WebSockets to communicate in real time between the browser, server and Raspberry Pi.\nWhat you\u2019ll need\n\nRaspberry Pi any of the following models: Zero (will need straight male header pins soldered2 and Micro USB OTG adaptor), A+, B+, 2, or 3\nMicro SD card at least 4Gb Class 10 speed3\nMicro USB power supply at least 2A\nUSB Wifi dongle (unless you have a Pi 3 - that has wifi built in). \nAddressable fairy lights\nLogic level shifter (with pins soldered unless you want to do it!)\nBreadboard\nJumper wires (3x male to male and 4x female to male)\n\nOptional but recommended\n\nBase board to hold the Pi and Breadboard (often comes with a breadboard!)\n\nFind links for where to buy all of these items that goes along with this tutorial. The total price should be around $1004.\nSetting up the Raspberry Pi\nYou\u2019ll need to install the SD card for the Raspberry Pi. You\u2019ll 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. \nNext 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\u2019s 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.\nnetwork={\n ssid=\"mywifi\"\n psk=\"mypassword\"\n}\nSave the file, eject the card from your computer and plug it into the Raspberry Pi. \nIf 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\u2019t plug it in yet!\nWiring!\nTime to wire everything up! \nFirst of all, push the Logic Level Converter into the middle of the breadboard:\n\nLogic Level Converter\nThe 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. \n\nRaspberry Pi pins only output 3.3v but the lights need 5v. That\u2019s why we need the logic level converter in there to boost up the signal.\nConnect the first two wires between the Raspberry Pi pins and the breadboard:\n\nNote 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\u2019t have to match but it\u2019s easier to follow (and check) if you use the same ones as in the diagram. \n\nThen the next two:\n\nThis is what you should have so far:\n\nLights\nNow 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.\n\n\n\nMake sure that you connect the right end of the lights, mine has a male connector at the wrong end so it\u2019s impossible to do this, but double check. \nAlso 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 \u2018-\u2019 or G) and DI (sometimes DIN for data in).\n\nYou 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\u2019s what takes the data along to the chip in the next light. Make sure that you\u2019re plugging into the data-in and not the data-out! \nThat\u2019s it! Everything\u2019s plugged in and ready to go! But before you plug power into your Pi, double check all your wires and make sure they\u2019re exactly right! You could damage your Raspberry Pi if it is not wired correctly. So triple check!\n\nThe Moment of Truth!\nPlug 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\u2019s your confirmation that it\u2019s connected to my WebSocket server and ready to receive messages from the upside-down! \n\nHowever, if the first light in the string is pulsing red, it means that you\u2019re not connected to the internet. So check the Troubleshooting section of the support document. If it\u2019s pulsing green then you\u2019re connected to the internet but can\u2019t connect to my server. It must have gone down. Sorry! The code will keep trying so leave it running and maybe it\u2019ll come back up. \nRig up the lights!\nFix the lights up on the wall however you want, pins, nails, tape. I\u2019ve used cable clips. Just be careful! I\u2019m using a 50 light string so I\u2019ve 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. \nCheck the photo here to see how the lights line up, note that there are spare unused lights in-between each row:\n\nNow visit lights.seb.ly and you\u2019ll see this : \n\nIf you\u2019re the only one online you\u2019ll 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\u2019ll need to click the button to join the queue and wait your turn. \nHow it works - the geeky details!\nElectronics:\nThe 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). \nAddressable LEDs or \u201cNeopixels\u201d\nWe\u2019re 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. \nThe 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.\nNeopixels with the chip and the LED all in one - it\u2019s the white square shaped component and the darker square inside is the chip. These are only 5mm wide!\nA Laser Light Synth! Covered with around 800 super bright neopixels!\nLogic Level Converter\nThe 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. \nPower\nNeopixels can often draw a lot of current so you need to be careful how you power them. I\u2019ve 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\u2019ll need to use a separate 5V power supply. If you want to learn more, check out Adafruit\u2019s Neopixel Uberguide. \nNode.js\nThere 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\u2019re hosted on npm as stranger-lights and stranger-lights-server. \nThe 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.\nWebSockets\nI\u2019m 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. \nWhen 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. \nThe Raspberry Pi code\nThe Node.js app runs automatically on startup, and I made this happen by adding this to the /etc/rc.local file: \nnode /home/pi/strangerthings/client.js > /dev/null &\nAnything 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\u2019t hold up the boot process. \nWorking with the Raspberry Pi headless\nYou might know that when a computer has no screen or keyboard, you would refer to it as \u201crunning headless\u201d. So just like most web servers, you need to configure it over the network with ssh10. If you\u2019re on a mac you can find your Pi on the network through the name raspberrypi.local11, otherwise you\u2019ll need to find its IP address. There\u2019s more on the guide to Remote Access instructions on the Raspberry Pi website. And if you\u2019re very new to the terminal, I highly recommend this great online Linux command line tutorial.\nImprovements\nThis is quite an early experiment and I\u2019m sure I\u2019ll 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\u2019ve just rigged up my lights with Post-it notes. It\u2019d be a lot nicer to get a paint brush and try to recreate the Winona-in-a-manic-state text style. \nWhere next?\nFinding 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\u2019s something you\u2019d be interested in, or sign up to my mailing list at st4i.com. \nThere 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\u2019ll be spoilt for choice! \nAlso take a look at Arduino - it\u2019s an incredibly popular platform for electronics and the internet is literally bursting with resources. \nI 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. \n\n\n\n\nNot a particularly original idea, but I don\u2019t think I\u2019ve 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\u00a0\u21a9\ufe0e\n\n\nVideo guide to soldering pins on to a Pi Zero and further soldering advice from Adafruit\u00a0\u21a9\ufe0e\n\n\nSlower cards will work but performance may suffer\u00a0\u21a9\ufe0e\n\n\nOr \u00a35,000 in UK money. Sorry, Brexit joke :)\u00a0\u21a9\ufe0e\n\n\nYou will need a card reader on your computer - most micro SD cards come with an adaptor that fits standard SD slots. \u00a0\u21a9\ufe0e\n\n\nSSID and password should be all that you need but you can see all the config options on this wpa supplicant guide\u00a0\u21a9\ufe0e\n\n\nRaspberry Pi Zero will require the OTG to USB adaptor to attach the wifi dongle\u00a0\u21a9\ufe0e\n\n\nThanks to Adafruit who invented the term neopixels so we don\u2019t have to refer to them as WS281x any more!\u00a0\u21a9\ufe0e\n\n\nSo you can see other people sending messages in the browser\u00a0\u21a9\ufe0e\n\n\nssh 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.\u00a0\u21a9\ufe0e\n\n\nYou can change this default hostname using raspi-config\u00a0\u21a9\ufe0e", "year": "2016", "author": "Seb Lee-Delisle", "author_slug": "sebleedelisle", "published": "2016-12-01T00:00:00+00:00", "url": "https://24ways.org/2016/internet-of-stranger-things/", "topic": "code"}
{"rowid": 66, "title": "Solve the Hard Problems", "contents": "So, here we find ourselves on the cusp of 2016. We\u2019ve had a good year \u2013 the web is still alive, no one has switched it off yet. Clients still have websites, teenagers still have phone apps, and there continue to be plenty of online brands to meaningfully engage with each day. Good job team, high fives all round.\nAs it\u2019s the time to make resolutions, I wanted to share three small ideas to take into the new year.\nGet good at what you do\n\u201cHow do you get to Carnegie Hall?\u201d the old joke goes. \u201cPractise, practise, practise.\u201d \nWe work in an industry where there is an awful lot to learn. There\u2019s a lot to learn to get started and then once you do, there\u2019s a lot more to learn to keep your skills current. Just when you think you\u2019ve mastered something, it changes.\nThis is true of many industries, of course, but the sheer pace of change for us makes learning not an annual activity, but daily. Learning takes time, and while I\u2019m not convinced that every skill takes the fabled ten thousand hours to master, there is certainly no escaping that to remain current we must reinvest time in keeping our skills up to date.\nPicking where to spend your time\nOne of the hardest aspects of this thing of ours is just choosing what to learn. If you, like me, invested any time in learning the Less CSS preprocessor over the last few years, you\u2019ll probably now be spending your time relearning Sass instead. If you spent time learning Grunt, chances are you\u2019ll now be thinking about whether you should switch to Gulp. It\u2019s not just that there are new types of tools, there are new tools and frameworks to do the things you\u2019re already doing, but, well, differently.\nDeciding what to learn is hard and the costs of backing the wrong horse can seriously mount up; so much so that by the time you\u2019ve learned and then relearned the tools everyone says you need for your job, there\u2019s rarely enough time to spend really getting to know how best to use them.\n\u00a0Practise, practise, practise\nDo you know how you don\u2019t get to Carnegie Hall? By learning a new instrument each week. It takes time and experience to really learn something well. That goes for a new JavaScript framework as much as a violin. If you flit from one shiny new thing to another, you\u2019re destined to produce amateurish work forever.\nLearn the new thing, but then stick with it long enough to get really good at it \u2013 even if Twitter trolls try to convince you it\u2019s not cool. What\u2019s really not cool is living as a forevernoob. \nIf you\u2019re still not sure what to learn, go back to basics. Considering a new CSS or JavaScript framework? Invest that time in learning the underlying CSS or JavaScript really well instead. Those skills will stand the test of time.\nAudience and purpose\nBack when I was in school, my English teacher (a nice Welsh lady, who I appreciate more now than I did back then) used to love to remind us that every piece of writing should have an audience and a purpose. So much so that audience and purpose almost became her catch phrase. For every essay, article or letter, we were reminded to consider who we were writing it for and what we were trying to achieve. \nIt\u2019s something I think about a lot; certainly when writing, but also in almost every other creative endeavour. Asking who is this for and what am I trying to achieve applies equally to designing a logo or website, through to composing music or writing software.\nBeing productive\nIt seems like everyone wants to have a product these days. As someone who used to do client services work and now has a product company, I often talk with people who are interested in taking something they\u2019ve built in-house and turning it into a product. You know the sort of thing: a design agency with its own CMS or project management web app; the very logical thought process of: if this helps our business, maybe others will find it valuable too; the question that inevitably follows: could we turn this into a product?\nWhether consciously or not, the audience and purpose influence nearly every aspect of your creative process. Once written or designed or developed or created, revising a work to change the audience and purpose can be quite a challenge. No matter how much you want to turn the tension-building, atmospheric music for a horror film into a catchy chart hit, it\u2019s going to be a struggle. Yes, it\u2019s music, but that\u2019s neither the audience nor purpose for which it was created.\nThe same is absolutely true for your in-house tools \u2013 those were also designed for a specific audience and purpose. Your in-house CMS would have been designed with an audience of your own development team, who are busy implementing sites for clients. The purpose is to make that team more productive overall, taking into account considerations of maintaining multiple sites on a common codebase, training clients, a more mature and stable platform and all the other benefits of reusing the same code for each project. The audience is your team and the purpose increased productivity.\nThat\u2019s very different from a customer who wants to buy a polished system to use off-the-shelf. If their needs perfectly aligned with yours then they wouldn\u2019t be in the market for your product \u2013 they would have built their own.\nSometimes you hear the advice to \u201cscratch your own itch\u201d when it comes to product design. I don\u2019t completely agree. Got an itch? Great. Find other itchy people and sell them a backscratcher.\nBuilding a product, like designing a website, is a lot of work. It requires knowing your audience and purpose inside out. You can\u2019t fudge it and you can\u2019t just hope you\u2019ll find an audience for some old thing you have lying around.\nAlways consider the audience and purpose for everything you create. It\u2019s often the difference between success and failure.\nSolve the hard problems\nHuman beings have a natural tendency to avoid hard problems. In digital design (websites, software, whatever) the received wisdom is often that we can get 80% of the way towards doing the hard thing by doing something that\u2019s not very hard.\nDo you know what you get at the end of it? Paid. But nothing really great ever happens that way.\nI worked on a client project a while back where one of the big challenges was making full use of the massive image library they had built up over the years. The client had tens of thousands of photographs, along with a fair amount of video and a large MP3 audio library too. If it wasn\u2019t managed carefully, storage sizes would get out of control, content would go unattributed, and everything would get very messy very quickly.\nI could tell from the outset that this aspect of the project was going to be a constant problem. So we tackled it head-on. We designed and built a media management system to hold and process all the assets, and added an API so the content management system could talk to it. Every time the site needed a photo at a new size, it made an API request to the system and everything was handled seamlessly.\nIt was a daunting job to invest all the time and effort in building that dedicated system and API, but it really paid off. Instead of having the constant troubles of a vast library of media, it became one of the strongest parts of the project.\nTurn your hardest problems into your biggest strengths\nThere\u2019s a funny thing about hard problems. The hardest problems are the most fun to solve and have the biggest impact.\nMaybe you\u2019re the sort of person who clocks in for work, does their job and clocks out at 5pm without another thought. But I don\u2019t think you are, because you\u2019re here reading this. If you really love what you do, I don\u2019t think you can be satisfied in your work unless you\u2019re seeking out and working on those hard problems. That\u2019s where the magic is.\n\nThe new year is a helpful time to think about breaking bad habits. Whether it\u2019s smoking a bit less, or going to the gym a bit more, the ticking over of the calendar can provide the motivation for a new start. I have some suggestions for you.\n\nGet good at what you do. Practise your skills and don\u2019t just flit from one shiny thing to the next.\nRemember who you\u2019re doing it for and why. Consider the audience and purpose for everything you create.\nSolve the hard problems. It\u2019s more interesting, more satisfying, and has a greater impact.\n\nAs we move into 2016, these are the things I\u2019m going to continue to work on. Maybe you\u2019d like to join me.", "year": "2015", "author": "Drew McLellan", "author_slug": "drewmclellan", "published": "2015-12-24T00:00:00+00:00", "url": "https://24ways.org/2015/solve-the-hard-problems/", "topic": "process"}
{"rowid": 51, "title": "Blow Your Own Trumpet", "contents": "Even if your own trumpet\u2019s tiny and fell out of a Christmas cracker, blowing it isn\u2019t something that everyone\u2019s good at. Some people find selling themselves and what they do difficult. But, you know what? Boo hoo hoo. If you want people to buy something, the reality is you\u2019d better get good at selling, especially if that something is you.\nFor web professionals, the best place to tell potential business customers or possible employers about what you do is on your own website. You can write what you want and how you want, but that doesn\u2019t make knowing what to write any easier. As a matter of fact, writing for yourself often proves harder than writing for someone else.\nI spent this autumn thinking about what I wanted to say about Stuff & Nonsense on the website we relaunched recently. While I did that, I spoke to other designers about how they struggled to write about their businesses.\nIf you struggle to write well, don\u2019t worry. You\u2019re not on your own. Here are five ways to hit the right notes when writing about yourself and your work.\nBe genuine about who you are\nI\u2019ve known plenty of talented people who run a successful business pretty much single-handed. Somehow they still feel awkward presenting themselves as individuals. They wonder whether describing themselves as a company will give them extra credibility. They especially agonise over using \u201cwe\u201d rather than \u201cI\u201d when describing what they do. These choices get harder when you\u2019re a one-man band trading as a limited company or LLC business entity.\nIf you mainly work alone, don\u2019t describe yourself as anything other than \u201cI\u201d. You might think that saying \u201cwe\u201d makes you appear larger and will give you a better chance of landing bigger and better work, but the moment a prospective client asks, \u201cHow many people are you?\u201d you\u2019ll have some uncomfortable explaining to do. This will distract them from talking about your work and derail your sales process. There\u2019s no need to be anything other than genuine about how you describe yourself. You should be proud to say \u201cI\u201d because working alone isn\u2019t something that many people have the ability, business acumen or talent to do.\nExplain what you actually do\nHow many people do precisely the same job as you? Hundreds? Thousands? The same goes for companies. If yours is a design studio, development team or UX consultancy, there are countless others saying exactly what you\u2019re saying about what you do. Simply stating that you code, design or \u2013 God help me \u2013 \u201chandcraft digital experiences\u201d isn\u2019t enough to make your business sound different from everyone else. Anyone can and usually does say that, but people buy more than deliverables. They buy something that\u2019s unique about you and your business.\nPotentially thousands of companies deliver code and designs the same way as Stuff & Nonsense, but our clients don\u2019t just buy page designs, prototypes and websites from us. They buy our taste for typography, colour and layout, summed up by our \u201cIt\u2019s the taste\u201d tagline and bowler hat tip to the PG Tips chimps. We hope that potential clients will understand what\u2019s unique about us. Think beyond your deliverables to what people actually buy, and sell the uniqueness of that.\nDescribe work in progress\nIt\u2019s sad that current design trends have made it almost impossible to tell one website from another. So many designers now demonstrate finished responsive website designs by pasting them onto iMac, MacBook, iPad and iPhone screens that their portfolios don\u2019t fare much better. Every designer brings their own experience, perspective and process to a project. In my experience, it\u2019s understanding those differences which forms a big part of how a prospective client makes a decision about who to work with. Don\u2019t simply show a prospective client the end result of a previous project; explain your process, the development of your thinking and even the wrong turns you took.\nTraditional case studies, like the one I\u2019ve just written about Stuff & Nonsense\u2019s work for WWF UK, can take a lot of time. That\u2019s probably why many portfolios get out of date very quickly. Designers make new work all the time, so there must be a better way to show more of it more often, to give prospective clients a clearer understanding of what we do. At Stuff & Nonsense our solution was to create a feed where we could post fragments of design work throughout a project. This also meant rewriting our Contract Killer to give us permission to publish work before someone signs it off.\nOutline a client\u2019s experience\nRecently a client took me to one side and offered some valuable advice. She told me that our website hadn\u2019t described anything about the experience she\u2019d had while working with us. She said that knowing more about how we work would\u2019ve helped her make her buying decision.\nWhen a client chooses your business, they\u2019re hoping for more than a successful outcome. They want their project to run smoothly. They want to feel that they made a correct decision when they chose you. If they work for an organisation, they\u2019ll want their good judgement to be recognised too. Our client didn\u2019t recognise her experience because we hadn\u2019t made our own website part of it. Remember, the challenge of creating a memorable user experience starts with selling to the people paying you for it.\nAddress your ideal client\nIt\u2019s important to understand that a portfolio\u2019s job isn\u2019t to document your work, it\u2019s to attract new work from clients you want. Make sure that work you show reflects the work you want, because what you include in your portfolio often leads to more of the same.\nWhen you\u2019re writing for your portfolio and elsewhere on your website, imagine that you\u2019re addressing your ideal client. Picture them sitting opposite and answer the questions they\u2019d ask as you would in conversation. Be direct, funny if that\u2019s appropriate and serious when it\u2019s not. If it helps, ask a friend to read the questions aloud and record what you say in response. This will help make what you write sound natural. I\u2019ve found this technique helps clients write copy too.\nToot your own horn\nSome people confuse expressing confidence in yourself and your work as boastfulness, but in a competitive world the reality is that if you are to succeed, you need to show confidence so that others can show their confidence in you. If you want people to hear you, pick up your trumpet and blow it.", "year": "2015", "author": "Andy Clarke", "author_slug": "andyclarke", "published": "2015-12-23T00:00:00+00:00", "url": "https://24ways.org/2015/blow-your-own-trumpet/", "topic": "business"}
{"rowid": 55, "title": "How Tabs Should Work", "contents": "Tabs in browsers (not browser tabs) are one of the oldest custom UI elements in a browser that I can think of. They\u2019ve been done to death. But, sadly, most of the time I come across them, the tabs have been badly, or rather partially, implemented.\nSo this post is my definition of how a tabbing system should work, and one approach of implementing that.\nBut\u2026 tabs are easy, right?\nI\u2019ve 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:\nvar tabs = $('.tab').click(function () {\n tabs.hide().filter(this.hash).show();\n}).map(function () {\n return $(this.hash)[0];\n});\n\n$('.tab:first').click();\nSimple, right? Nearly fits in a tweet (ignoring the whole jQuery library\u2026). Still, it\u2019s riddled with problems that make it a far from perfect solution.\nRequirements: what makes the perfect tab?\n\nAll content is navigable and available without JavaScript (crawler-compatible and low JS-compatible).\nARIA roles.\nThe tabs are anchor links that:\n\nare clickable\nhave block layout\nhave their href pointing to the id of the panel element\nuse the correct cursor (i.e. cursor: pointer).\n\nSince tabs are clickable, the user can open in a new tab/window and the page correctly loads with the correct tab open.\nRight-clicking (and Shift-clicking) doesn\u2019t cause the tab to be selected.\nNative 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).\n\nThe first three points are all to do with the semantics of the markup and how the markup has been styled. I think it\u2019s 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.\nThe last three points are JavaScript problems. Let\u2019s investigate that.\nThe shitmus test\nLike a litmus test, here\u2019s a couple of quick ways you can tell if a tabbing system is poorly implemented:\n\nChange tab, then use the Back button (or keyboard shortcut) and it breaks\nThe tab isn\u2019t a link, so you can\u2019t open it in a new tab\n\nThese two basic things are, to me, the bare minimum that a tabbing system should have.\nWhy is this important?\nThe people who push their so-called native apps on users can\u2019t have more reasons why the web sucks. If something as basic as a tab doesn\u2019t work, obviously there\u2019s more ammo to push a closed native app or platform on your users.\nIf you\u2019re going to be a web developer, one of your responsibilities is to maintain established interactivity paradigms. This doesn\u2019t mean don\u2019t innovate. But it does mean: stop fucking up my scrolling experience with your poorly executed scroll effects. :breath:\nURI fragment, absolute URL or query string?\nA 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.\nThis decision really depends on the context of your tabbing system. For something like GitHub\u2019s tabs to view a pull request, it makes sense that the full URL changes.\nFor our problem though, I want to solve the issue when the page doesn\u2019t do a full URL update; that is, your regular run-of-the-mill tabbing system.\nI used to be from the school of using the hash to show the correct tab, but I\u2019ve recently been exploring whether the query string can be used. The biggest reason is that multiple hashes don\u2019t work, and comma-separated hash fragments don\u2019t make any sense to control multiple tabs (since it doesn\u2019t actually link to anything).\nFor this article, I\u2019ll keep focused on using a single tabbing system and a hash on the URL to control the tabs.\nMarkup\nI\u2019m going to assume subcontent, so my markup would look like this (yes, this is a cat demo\u2026):\n\n\n\n \n
\n\n \n
\n\n \n
\nIt\u2019s 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\u2019ll see once we\u2019re on to writing the code.\nURL-driven tabbing systems\nInstead of making the code responsive to the user\u2019s input, we\u2019re 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.\nWith that in mind, let\u2019s start building up our code. I\u2019ll assume we have the jQuery library, but I\u2019ve 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).\nNote that I\u2019ll start with the simplest solution, and I\u2019ll refactor the code as I go along, like in places where I keep calling jQuery selectors.\nfunction show(id) {\n // remove the selected class from the tabs,\n // and add it back to the one the user selected\n $('.tab').removeClass('selected').filter(function () {\n return (this.hash === id);\n }).addClass('selected');\n\n // now hide all the panels, then filter to\n // the one we're interested in, and show it\n $('.panel').hide().filter(id).show();\n}\n\n$(window).on('hashchange', function () {\n show(location.hash);\n});\n\n// initialise by showing the first panel\nshow('#dizzy');\nThis works pretty well for such little code. Notice that we don\u2019t have any click handlers for the user and the Back button works right out of the box.\nHowever, there\u2019s a number of problems we need to fix:\n\nThe initialised tab is hard-coded to the first panel, rather than what\u2019s on the URL.\nIf there\u2019s no hash on the URL, all the panels are hidden (and thus broken).\nIf you scroll to the bottom of the example, you\u2019ll find a \u201ctop\u201d link; clicking that will break our tabbing system.\nI\u2019ve purposely made the page long, so that when you click on a tab, you\u2019ll see the page scrolls to the top of the tab. Not a huge deal, but a bit annoying.\n\nFrom our criteria at the start of this post, we\u2019ve already solved items 4 and 5. Not a terrible start. Let\u2019s solve items 1 through 3 next.\nUsing the URL to initialise correctly and protect from breakage\nInstead of arbitrarily picking the first panel from our collection, the code should read the current location.hash and use that if it\u2019s available.\nThe problem is: what if the hash on the URL isn\u2019t actually for a tab?\nThe solution here is that we need to cache a list of known panel IDs. In fact, well-written DOM scripting won\u2019t 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.\nSo now the code will collect all the tabs, then find the related panels from those tabs, and we\u2019ll use that list to double the values we give the show function (during initialisation, for instance).\n// collect all the tabs\nvar tabs = $('.tab');\n\n// get an array of the panel ids (from the anchor hash)\nvar targets = tabs.map(function () {\n return this.hash;\n}).get();\n\n// use those ids to get a jQuery collection of panels\nvar panels = $(targets.join(','));\n\nfunction show(id) {\n // if no value was given, let's take the first panel\n if (!id) {\n id = targets[0];\n }\n // remove the selected class from the tabs,\n // and add it back to the one the user selected\n tabs.removeClass('selected').filter(function () {\n return (this.hash === id);\n }).addClass('selected');\n\n // now hide all the panels, then filter to\n // the one we're interested in, and show it\n panels.hide().filter(id).show();\n}\n\n$(window).on('hashchange', function () {\n var hash = location.hash;\n if (targets.indexOf(hash) !== -1) {\n show(hash);\n }\n});\n\n// initialise\nshow(targets.indexOf(location.hash) !== -1 ? location.hash : '');\nThe 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.\nThe second breakage we saw in the original demo was that clicking the \u201ctop\u201d link would break our tabs. This was due to the hashchange event firing and the code didn\u2019t validate the hash that was passed. Now this happens, the panels don\u2019t break.\nSo far we\u2019ve got a tabbing system that:\n\nWorks without JavaScript.\nSupports right-click and Shift-click (and doesn\u2019t select in these cases).\nLoads the correct panel if you start with a hash.\nSupports native browser navigation.\nSupports the keyboard.\n\nThe only annoying problem we have now is that the page jumps when a tab is selected. That\u2019s 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\u2019s all for a good cause.\nRemoving the jump to tab\nYou\u2019d be forgiven for thinking you just need to hook a click handler and return false. It\u2019s what I started with. Only that\u2019s not the solution. If we add the click handler, it breaks all the right-click and Shift-click support.\nThere may be another way to solve this, but what follows is the way I found \u2013 and it works. It\u2019s just a bit\u2026 hairy, as I said.\nWe\u2019re 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\u2019t jump the page.\nThe change involves the following:\n\nAdd a click handle that removes the id from the target panel, and cache this in a target variable that we\u2019ll use later in hashchange (see point 4).\nIn the same click handler, set the location.hash to the current link\u2019s 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).\nFor each panel, put a backup copy of the id attribute in a data property (I\u2019ve called it old-id).\nWhen the hashchange event fires, if we have a target value, let\u2019s put the id back on the panel.\n\nThese changes result in this final code:\n/*global $*/\n\n// a temp value to cache *what* we're about to show\nvar target = null;\n\n// collect all the tabs\nvar tabs = $('.tab').on('click', function () {\n target = $(this.hash).removeAttr('id');\n\n // if the URL isn't going to change, then hashchange\n // event doesn't fire, so we trigger the update manually\n if (location.hash === this.hash) {\n // but this has to happen after the DOM update has\n // completed, so we wrap it in a setTimeout 0\n setTimeout(update, 0);\n }\n});\n\n// get an array of the panel ids (from the anchor hash)\nvar targets = tabs.map(function () {\n return this.hash;\n}).get();\n\n// use those ids to get a jQuery collection of panels\nvar panels = $(targets.join(',')).each(function () {\n // keep a copy of what the original el.id was\n $(this).data('old-id', this.id);\n});\n\nfunction update() {\n if (target) {\n target.attr('id', target.data('old-id'));\n target = null;\n }\n\n var hash = window.location.hash;\n if (targets.indexOf(hash) !== -1) {\n show(hash);\n }\n}\n\nfunction show(id) {\n // if no value was given, let's take the first panel\n if (!id) {\n id = targets[0];\n }\n // remove the selected class from the tabs,\n // and add it back to the one the user selected\n tabs.removeClass('selected').filter(function () {\n return (this.hash === id);\n }).addClass('selected');\n\n // now hide all the panels, then filter to\n // the one we're interested in, and show it\n panels.hide().filter(id).show();\n}\n\n$(window).on('hashchange', update);\n\n// initialise\nif (targets.indexOf(window.location.hash) !== -1) {\n update();\n} else {\n show();\n}\nThis 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.\nARIA roles\nThis article on ARIA tabs made it very easy to get the tabbing system working as I wanted.\nThe tasks were simple:\n\nAdd aria-role set to tab for the tabs, and tabpanel for the panels.\nSet aria-controls on the tabs to point to their related panel (by id).\nI use JavaScript to add tabindex=0 to all the tab elements.\nWhen 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.\nWhen I hide the panels I add aria-hidden=true, and when I show the specific panel I set aria-hidden=false.\n\nAnd that\u2019s it. Very small changes to get full sign-off that the tabbing system is bulletproof and accessible.\nCheck out the final version (and the non-jQuery version as promised).\nIn conclusion\nThere\u2019s a lot of tab implementations out there, but there\u2019s an equal amount that break the browsing paradigm and the simple linkability of content. Clearly there\u2019s a special hell for those tab systems that don\u2019t even use links, but I think it\u2019s clear that even in something that\u2019s relatively simple, it\u2019s the small details that make or break the user experience.\nObviously there are corners I\u2019ve not explored, like when there\u2019s 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\u2019s for another year!", "year": "2015", "author": "Remy Sharp", "author_slug": "remysharp", "published": "2015-12-22T00:00:00+00:00", "url": "https://24ways.org/2015/how-tabs-should-work/", "topic": "code"}
{"rowid": 60, "title": "What\u2019s Ahead for Your Data in 2016?", "contents": "Who owns your data? Who decides what can you do with it? Where can you store it? What guarantee do you have over your data\u2019s privacy? Where can you publish your work? Can you adapt software to accommodate your disability? Is your tiny agency subject to corporate regulation? Does another country have rights over your intellectual property?\nIf you aren\u2019t the kind of person who is interested in international politics, I hate to break it to you: in 2016 the legal foundations which underpin our work on the web are being revisited in not one but three major international political agreements, and every single one of those questions is up for grabs. These agreements \u2013 the draft EU Data Protection Regulation (EUDPR), the Trans-Pacific Partnership (TPP), and the draft Transatlantic Trade and Investment Partnership (TTIP) \u2013 stand poised to have a major impact on your data, your workflows, and your digital rights. While some proposed changes could protect the open web for the future, other provisions would set the internet back several decades.\nIn this article we will review the issues you need to be aware of as a digital professional. While each of these agreements covers dozens of topics ranging from climate change to food safety, we will focus solely on the aspects which pertain to the work we do on the web.\nThe Trans-Pacific Partnership\nThe Trans-Pacific Partnership (TPP) is a free trade agreement between the US, Japan, Malaysia, Vietnam, Singapore, Brunei, Australia, New Zealand, Canada, Mexico, Chile and Peru \u2013 a bloc comprising 40% of the world\u2019s economy. The agreement is expected to be signed by all parties, and thereby to come into effect, in 2016. This agreement is ostensibly about the bloc and its members working together for their common interests. However, the latest draft text of the TPP, which was formulated entirely in secret, has only been made publicly available on a Medium blog published by the U.S. Trade Representative which features a patriotic banner at the top proclaiming \u201cTPP: Made in America.\u201d The message sent about who holds the balance of power in this agreement, and whose interests it will benefit, is clear.\nBy far the most controversial area of the TPP has centred around the provisions on intellectual property. These include copyright terms of up to 120 years, mandatory takedowns of allegedly infringing content in response to just one complaint regardless of that complaint\u2019s validity, heavy and disproportionate penalties for alleged violations, and \u2013 most frightening of all \u2013 government seizures of equipment allegedly used for copyright violations. All of these provisions have been raised without regard for the fact that a trade agreement is not the appropriate venue to negotiate intellectual property law.\nOther draft TPP provisions would restrict the digital rights of people with disabilities by banning the workarounds they use every day. These include no exemptions for the adaptations of copywritten works for use in accessible technology (such as text-to-speech in ebook readers), a ban on circumventing DRM or digital locks in order to convert a file to an accessible format, and requiring the takedown of adapted works, such as a video with added subtitles, even if that adaptation would normally have fallen under the definition of fair use.\nThe e-commerce provisions would prohibit data localisation, the practice of requiring data to be physically stored on servers within a country\u2019s borders. Data localisation is growing in popularity following the Snowden revelations, and some of your own personal data may have been recently \u201clocalised\u201d in response to the Safe Harbor verdict. Prohibiting data localisation through the TPP would address the symptom but not the cause.\nThe Electronic Frontier Foundation has published an excellent summary of the digital rights issues raised by the agreement along with suggested actions American readers can take to speak out.\nTransatlantic Trade and Investment Partnership\nTTIP stands for the Transatlantic Trade and Investment Partnership, a draft free trade agreement between the United States and the EU. The plan has been hugely controversial and divisive, and the internet and digital provisions of the draft form just a small part of that contention.\nThe most striking digital provision of TTIP is an attempt to circumvent and override European data protection law. As EDRI, a European digital rights organisation, noted:\n\n\u201cthe US proposal would authorise the transfer of EU citizens\u2019 personal data to any country, trumping the EU data protection framework, which ensures that this data can only be transferred in clearly defined circumstances. For years, the US has been trying to bypass the default requirement for storage of personal data in the EU. It is therefore not surprising to see such a proposal being {introduced} in the context of the trade negotiations.\u201d\n\nThis draft provision was written before the Safe Harbor data protection agreement between the EU and US was invalidated by the Court of Justice of the European Union. In other words, there is no longer any protective agreement in place, and our data is as vulnerable as this political situation. However, data protection is a matter of its own law, the acting Data Protection Directive and the draft EU Data Protection Reform. A trade agreement, be it the TTIP or the TPP, is not the appropriate place to revamp a law on data protection.\nOther digital law issues raised by TTIP include the possibility of renegotiating standards on encryption (which in practice means lowering them) and renegotiating intellectual property rights such as copyright. The spectre of net neutrality has even put in an appearance, with an attempt to introduce rules on access to the internet itself being introduced as provisions.\nTTIP is still under discussion, and this month the EU trade representative said that \u201cwe agreed to further intensify our work during 2016 to help negotiations move forward rapidly.\u201d This has been cleverly worded: this means the agreement has little chance of being passed or coming into effect in 2016, which buys civil society more precious time to speak out.\nThe EU Data Protection Regulation\nOn 15 December 2015 the European Commission announced their agreement on the text of the draft General Data Protection Regulation. This law will replace its predecessor, the EU Data Protection Regulation of 1995, which has done a remarkable job of protecting data privacy across the continent throughout two decades of constant internet evolution.\nThe goal of the reform process has been to return power over data, and its uses, to citizens. Users will have more control over what data is captured about them, how it is used, how it is retained, and how it can be deleted. Businesses and digital professionals, in turn, will have to restructure their relationships with client and customer data. Compliance obligations will increase, and difficult choices will have to be made. However, this time should be seen as an opportunity to rethink our relationship with data. After Snowden, Schrems, and Safe Harbor, it is clear that we cannot go back to the way things were before. In an era of where every one of our heartbeats is recorded on a wearable device and uploaded to a surveilled data centre in another country, the need for reform has never been more acute.\nWhile texts of the draft GDPR are available, there is not enough mulled wine in the world that will help you get through them. Instead, the law firm Fieldfisher Waterhouse has produced this helpful infographic which will give you a good idea of the changes we can expect to see (view full size):\n\nThe most surprising outcome announced on 15 December was the new regulation\u2019s teeth. Under the new law, companies that fail to heed the updated data protection rules will face fines of up to 4% of their global turnover. Additionally, the law expands the liability for data protection to both the controller (the company hosting the data) and the data processor (the company using the data). The new law will also introduce a one-stop shop for resolving concerns over data misuse. Companies will no longer be able to headquarter their European operations in countries which are perceived to have relatively light-touch data protection enforcement (that means you, Ireland) as a means of automatically rejecting any complaints filed by citizens outside that country.\nFor digital professionals, the most immediate concern is analytics. In fact, I am going to make a prediction: in 2016 we will begin to see the same misguided war on analytics that we saw on cookies. By increasing the legal liabilities for both data processors and controllers \u2013 in other words, the company providing the analytics as well as the site administrator studying them \u2013 the new regulation risks creating disproportionate burdens as well as the same \u201cguilt by association\u201d risks we saw in 2012. There have already been statements made by some within the privacy community that analytics are tracking, and tracking is surveillance, therefore analytics are evil. Yet \u201cjust don\u2019t use analytics,\u201d as was suggested by one advocate, is simply not an option. European regulators should consult with the web community to gain a clear understanding of why analytics are vital to everyday site administrators, and must find a happy medium that protects users\u2019 data without criminalising every website by default. No one wants a repeat of the crisis of consent, as well as the scaremongering, caused by the cookie law.\nAssuming the text is adopted in 2016, the new EU Data Protection Regulation would not come into effect until 2018. We have a considerable challenge ahead, but we also have plenty of time to get it right.", "year": "2015", "author": "Heather Burns", "author_slug": "heatherburns", "published": "2015-12-21T00:00:00+00:00", "url": "https://24ways.org/2015/whats-ahead-for-your-data-in-2016/", "topic": "business"}
{"rowid": 50, "title": "Make a Comic", "contents": "For something slightly different over Christmas, why not step away from your computer and make a comic? \nDefinitely 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.\nWhy make a comic?\nFirst of all, it\u2019s truly fun and it\u2019s not that difficult. If you\u2019re 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 \u2013 or not.\nIf you\u2019re an interaction designer, it\u2019s likely you\u2019ve 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. \nIt\u2019s not a client deliverable but something that stands by itself, and you\u2019ve nobody\u2019s criteria to meet except those that exist in your imagination! \nThanks 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: \n\n\u201cThere 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.\u201d \n\nHere\u2019s an example of a non sequitur from Scott McCloud\u2019s Understanding Comics \u2013 the images bear no relation to one another, but since they\u2019re in a sequence our brains do their best to understand it: \n\nOnce you know this it takes the pressure off somewhat. It\u2019s a fun thing to keep in mind and experiment with in your comics! \nMaterials needed\n\nA4 copy/printing paper \nHB pencil for light drawing\nDip pen and waterproof Indian ink \nBristol board (or any good quality card with a smooth, durable surface) \n\nStep 1: Get ideas\nYou\u2019d 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. \nOne way to keep track of ideas is to keep a sketch diary, capturing funny conversations and other events you could use in comics later. \nYou 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.\nStep 2: Edit your story using thumbnails\nHow thumbnailing works.\nWhy use thumbnails? You can move them around or get rid of them! \nDrawings are harder and much slower to edit than words, so you need to draw something very quick and very rough. You don\u2019t have to care about drawing quality at this point. \nYou might already have a drafted comic from the previous step; now you can split each panel up into a thumbnail like the image above. \nGet 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\u2019s 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. \nStep 3: Plan a layout\nSo you\u2019ve got the story more or less down: you now need to know how they\u2019ll look on the page. Sketch a layout and arrange the thumbnails into the layout.\nThe simplest way to do this is to divide an A4 page into equal panels \u2014 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.\nStep 4: Draw the comic\nI 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. \nUsing your thumbnails for reference, draw the comic lightly using an HB pencil. Don\u2019t make the line so heavy that it can\u2019t be erased (since you\u2019ll ink over the lines later).\nStep 5: Ink the comic\nImage before colour was added.\nYou\u2019ve drawn your story. Well done!\nNow 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. \nIf you don\u2019t 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\u2019s unfortunately easy to smudge the ink from the dip pen, so I recommend practising first. \nYou\u2019ve made a comic! \nStep 6: Adding colour\nComics traditionally had a limited colour palette before computers (here\u2019s an in-depth explanation if you\u2019re curious). You can actually do a huge amount with a restricted colour palette. Ellice Weaver\u2019s 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. \nOnce the ink is completely dry, erase the pencilled lines and you\u2019ll be left with a beautiful inked black and white drawing. \nYou could use a computer for this part. You could also photocopy it and paint straight on the copy. If you\u2019re feeling really brave, you could paint straight on the original. But I\u2019d suggest not doing this if it\u2019s your first try at painting! \nWhat 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. \nHow to paint your comic using Photoshop\n\nScan the drawing and open it in Photoshop. You can adjust the levels (Image \u2192 Adjustments \u2192 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. \nAdd 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.\nStart blocking in colour. And once you\u2019re happy with that, experiment with adding tone and texture.\n\nChristmas comic challenge!\nWhy not challenge yourself to make a short comic over Christmas? If you make one, share it in the comments. Or show me on Twitter \u2014 I\u2019d love to see it.\n\nCredit: Many of these techniques were learned on the Royal Drawing School\u2019s brilliant \u2018Drawing the Graphic Novel\u2019 course.", "year": "2015", "author": "Rebecca Cottrell", "author_slug": "rebeccacottrell", "published": "2015-12-20T00:00:00+00:00", "url": "https://24ways.org/2015/make-a-comic/", "topic": "design"}
{"rowid": 64, "title": "Being Responsive to the Small Things", "contents": "It\u2019s that time of the year again to trim the tree with decorations. Or maybe a DOM tree?\nAny web page is made of HTML elements that lay themselves out in a tree structure. We start at the top and then have multiple branches with branches that branch out from there. \n\nTo decorate our tree, we use CSS to specify which branches should receive the tinsel we wish to adorn upon it. It\u2019s all so lovely.\nIn years past, this was rather straightforward. But these days, our trees need to be versatile. They need to be responsive!\nResponsive web design is pretty wonderful, isn\u2019t it? Based on our viewport, we can decide how elements on the page should change their appearance to accommodate various constraints using media queries.\nClearleft have a delightfully clean and responsive site\nAlas, it\u2019s not all sunshine, lollipops, and rainbows. \nWith complex layouts, we may have design chunks \u2014 let\u2019s call them components \u2014 that appear in different contexts. Each context may end up providing its own constraints on the design, both in its default state and in its possibly various responsive states.\n\nMedia queries, however, limit us to the context of the entire viewport, not individual containers on the page. For every container our component lives in, we need to specify how to rearrange things in that context. The more complex the system, the more contexts we need to write code for.\n@media (min-width: 800px) {\n .features > .component { }\n .sidebar > .component {}\n .grid > .component {}\n}\nEach new component and each new breakpoint just makes the entire system that much more difficult to maintain. \n@media (min-width: 600px) {\n .features > .component { }\n .grid > .component {}\n}\n\n@media (min-width: 800px) {\n .features > .component { }\n .sidebar > .component {}\n .grid > .component {}\n}\n\n@media (min-width: 1024px) {\n .features > .component { }\n}\nEnter container queries\nContainer queries, also known as element queries, allow you to specify conditional CSS based on the width (or maybe height) of the container that an element lives in. In doing so, you no longer have to consider the entire page and the interplay of all the elements within. \nWith container queries, you\u2019ll be able to consider the breakpoints of just the component you\u2019re designing. As a result, you end up specifying less code and the components you develop have fewer dependencies on the things around them. (I guess that makes your components more independent.)\nAwesome, right?\nThere\u2019s only one catch.\nBrowsers can\u2019t do container queries. There\u2019s not even an official specification for them yet. The Responsive Issues (n\u00e9e Images) Community Group is looking into solving how such a thing would actually work. \nSee, container queries are tricky from an implementation perspective. The contents of a container can affect the size of the container. Because of this, you end up with troublesome circular references. \nFor example, if the width of the container is under 500px then the width of the child element should be 600px, and if the width of the container is over 500px then the width of the child element should be 400px. \nCan you see the dilemma? When the container is under 500px, the child element resizes to 600px and suddenly the container is 600px. If the container is 600px, then the child element is 400px! And so on, forever. This is bad.\nI guess we should all just go home and sulk about how we just got a pile of socks when we really wanted the Millennium Falcon. \nOur saviour this Christmas: JavaScript\nThe three wise men \u2014 Tim Berners-Lee, H\u00e5kon Wium Lie, and Brendan Eich \u2014 brought us the gifts of HTML, CSS, and JavaScript. \nTo date, there are a handful of open source solutions to fill the gap until a browser implementation sees the light of day.\n\nElementary by Scott Jehl\nElementQuery by Tyson Matanich\nEQ.js by Sam Richards\nCSS Element Queries from Marcj\n\nUsing any of these can sometimes feel like your toy broke within ten minutes of unwrapping it.\nEach take their own approach on how to specify the query conditions. For example, Elementary, the smallest of the group, only supports min-width declarations made in a :before selector.\n.mod-foo:before {\n content: \u201c300 410 500\u201d;\n}\nThe script loops through all the elements that you specify, reading the content property and then setting an attribute value on the HTML element, allowing you to use CSS to style that condition. \n.mod-foo[data-minwidth~=\"300\"] {\n background: blue;\n}\nTo get the script to run, you\u2019ll need to set up event handlers for when the page loads and for when it resizes. \nwindow.addEventListener( \"load\", window.elementary, false );\nwindow.addEventListener( \"resize\", window.elementary, false );\nThis works okay for static sites but breaks down on pages where elements can expand or contract, or where new content is dynamically inserted.\nIn the case of EQ.js, the implementation requires the creation of the breakpoints in the HTML. That means that you have implementation details in HTML, JavaScript, and CSS. (Although, with the JavaScript, once it\u2019s in the build system, it shouldn\u2019t ever be much of a concern unless you\u2019re tracking down a bug.)\nAnother problem you may run into is the use of content delivery networks (CDNs) or cross-origin security issues. The ElementQuery and CSS Element Queries libraries need to be able to read the CSS file. If you are unable to set up proper cross-origin resource sharing (CORS) headers, these libraries won\u2019t help.\nAt Shopify, for example, we had all of these problems. The admin that store owners use is very dynamic and the CSS and JavaScript were being loaded from a CDN that prevented the JavaScript from reading the CSS. \nTo go responsive, the team built their own solution \u2014 one similar to the other scripts above, in that it loops through elements and adds or removes classes (instead of data attributes) based on minimum or maximum width.\nThe caveat to this particular approach is that the declaration of breakpoints had to be done in JavaScript. \n elements = [\n { \u2018module\u2019: \u201c.carousel\u201d, \u201cclassName\u201d:\u2019alpha\u2019, minWidth: 768, maxWidth: 1024 },\n { \u2018module\u2019: \u201c.button\u201d, \u201cclassName\u201d:\u2019beta\u2019, minWidth: 768, maxWidth: 1024 } ,\n { \u2018module\u2019: \u201c.grid\u201d, \u201cclassName\u201d:\u2019cappa\u2019, minWidth: 768, maxWidth: 1024 }\n ]\nWith that done, the script then had to be set to run during various events such as inserting new content via Ajax calls. This sometimes reveals itself in flashes of unstyled breakpoints (FOUB). An unfortunate side effect but one largely imperceptible.\nUsing this approach, however, allowed the Shopify team to make the admin responsive really quickly. Each member of the team was able to tackle the responsive story for a particular component without much concern for how all the other components would react. \n\nEach element responds to its own breakpoint that would amount to dozens of breakpoints using traditional breakpoints. This approach allows for a truly fluid and adaptive interface for all screens.\nChristmas is over\nI wish I were the bearer of greater tidings and cheer. It\u2019s not all bad, though. We may one day see browsers implement container queries natively. At which point, we shall all rejoice!", "year": "2015", "author": "Jonathan Snook", "author_slug": "jonathansnook", "published": "2015-12-19T00:00:00+00:00", "url": "https://24ways.org/2015/being-responsive-to-the-small-things/", "topic": "code"}
{"rowid": 57, "title": "Cooking Up Effective Technical Writing", "contents": "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\u2019s not get into that argument), and your Christmas cake has been baked and is now quietly absorbing regular doses of alcohol.\nSome of you may be reading this and scoffing Of course! I\u2019ve 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\u2019t cook to save my life.\nFor beginners, recipes are the step-by-step instructions that hand-hold us through the cooking process, but even as a seasoned expert you\u2019re 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\u2019s 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.\nThe \u2018just\u2019ification of documentation\nLately it feels like we\u2019re starting to consider the importance of our words, and the impact they can have on others. Brad Frost warned us of the dangers of \u201cJust\u201d when it comes to offering up solutions to queries:\n\n\u201cJust use this software/platform/toolkit/methodology\u2026\u201d\n\u201cJust\u201d makes me feel like an idiot. \u201cJust\u201d 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. \u201cJust\u201d is a dangerous word.\n\u201cJust\u201d by Brad Frost\n\nI 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\u00a0 ASP and pinch of Java. I\u2019d 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\u2019t 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.\nI have often found myself bemoaning the lack of tutorials or courses that cater for the middle level \u2013 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\u2019t 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.\nI\u2019m caught in the place between snoozing off when \u2018Using the Instagram API with Ruby\u2019 hand-holds me through what REST is, and feeling like I\u2019m stupid and need to go back to dev school when I can\u2019t get my environment and dependencies set up, let alone work out how I\u2019m meant to get any code to run.\nIt\u2019s seems I\u2019m not alone with this \u2013 Erin McKean seems to have been here too:\n\n\u201cSome tutorials (especially coding tutorials) like to begin things in media res. Great for a sense of dramatic action, bad for getting to \u201cStep 1\u201d 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\u2019t even know about.\u201d\n\u201cTips for Learning What You Don\u2019t Know You Don\u2019t Know\u201d by Erin McKean\n\nI\u2019m sure you\u2019ve been here too. Many tutorials suffer badly from the fabled \u2018how to draw an owl\u2019-itis.\n\nIt\u2019s 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\u2019re trying to sous vide a steak using your bathtub and a Ziploc bag.\nDon\u2019t be a turkey, use your loaf!\nMy mum is a great cook in my eyes (aren\u2019t 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.\n\nDepending on your level of baking knowledge, you may ask: What\u2019s SR flour? What\u2019s 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 \u201cwell spaced\u201d? How much leeway do I have for \u201c(ish!!)\u201d? Does the \u201c20\u201d on the other cookie note mean I\u2019ll 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\u2019t cook mentality.\nYou 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.\nHowever, if we look at good examples of recipes, I think there\u2019s a lot we can apply when it comes to technical writing on the web. I\u2019ve 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.\n1. Structure and standardise your information\nThink 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.\u00a0\n\nGreat 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\u2019ve 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.\u00a0\nBy breaking down your technical writing into similar sections, you can help your audience understand the elements they\u2019ll be working with, what they need to do once they have these, and how they can move on from your self-contained illustration.\nTitle\n \n Ensure your title is suitably descriptive and representative of the result. Getting Started with Python perhaps isn\u2019t as helpful as Learn Python: General Syntax and Basics.\n \n Result\n \n Many recipes include a couple of lines as an overview of what you\u2019ll end up with, and many include a photo of the finished dish. With our technical writing we can do the same:\n In this tutorial we\u2019re going to learn how to set up our development environment, and we\u2019ll then undertake some exercises to explore the general syntax, finishing by building a mini calculator.\n \n Ingredients\n \n What are the components we\u2019ll be working with, whether in terms of versions, environment, languages or the software packages and libraries you\u2019ll need along the way? Listing these up front gives the reader a great summary of the things they\u2019ll be using, and any gotchas.\n 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\u2019re using it.\n \n Prep\n \n 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\u2019t clear. Be sure to include information around any environment set-up, installation or config you\u2019ll need to have done before you start.\nStu Robson\u2019s Simple Sass documentation aims to do this before getting into specifics, although ideally this would also include setting up Sass itself.\n \n Instructions\n \nThe body of the tutorial itself is the whole point of our writing. The next four tips will hopefully make your tutorial much more successful.\n \n Variations\n \n Like our ingredients section, as important as explaining why we\u2019re using something in this context is, it\u2019s also great to explain alternatives that could be used instead, and the impact of doing so.\n 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.\n While not in a separate section, the source code for GreenSock\u2019s GSAP JS basics explains:\n We\u2019ll use a window.onload for simplicity, but typically it is best to use either jQuery\u2019s $(document).ready() or $(window).load() or cross-browser event listeners so that you\u2019re not limited to one.\n Keep in mind to both:\n Explain what variations are possible.\n Explain why certain options may be more desirable than others in different situations.\n \n \n2. Small, reusable components\nReusable components are for life, not just for Christmas, and they\u2019re certainly not just for development. If you start to apply the structure above to your writing, you\u2019re 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\u2019t need to be told how to beat an egg for the hundredth time.\u00a0\nInstead, 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.\n\nThis 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.\n\n3. Provide context to aid accessibility\nHere I\u2019m talking about accessibility in the broadest sense. Small, isolated snippets can be frustrating to those who don\u2019t fully understand the wider context of how our examples work.\nShowing 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.\u00a0\n4. Be your own tech editor\nA good editor can be invaluable to your work, and wherever possible I\u2019d 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.\nThere 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\u2019d like to encourage you to think about the following:\n\nExplain what things are. For example, instead of referencing Grunt, in the first instance perhaps reference \u201cGrunt (a JavaScript task runner that minimises repetitive activities through automation).\u201d\nExplain how you get things, even if this is a link to official installers and documentation. Don\u2019t leave your readers having to search.\nWhy are you using this approach/technology over other options?\nWhat happens if I use something else? What depends on this?\nAvoid exclusionary lingo or acronyms.\n\nAirbnb\u2019s JavaScript Style Guide includes useful pointers around their reasoning:\n\nUse computed property names when creating objects with dynamic property names.\nWhy? They allow you to define all the properties of an object in one place.\n\nThe language we use often makes assumptions, as we saw with \u201cjust\u201d. An article titled \u201cES6 for Beginners\u201d 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?\nThis doesn\u2019t necessarily mean supporting everyone \u2013 your audience may need to have advanced skills \u2013 but even if you\u2019re providing low-level, deep-dive, reference material, trying not to make assumptions or take shortcuts will hopefully lead to better, clearer writing.\n5. A picture is worth a thousand words\u2026\n\u2026or 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\u2019re doing, what they should expect as interaction responses, and what the process looks like at different points.\nThere are many, many options for recording your screen, including QuickTime Player on Mac OS X (File \u2192 New Screen Recording), GifGrabber, or Giffing Tool on Windows.\nPaul Swain, a UX designer, uses GIFs to provide additional context within his documentation, improving communication:\n\n\u201cMy colleagues (from across the organisation) love animated GIFs. Any time an interaction is referenced, it\u2019s accompanied by a GIF and a shared understanding of what\u2019s being designed. The humble GIF is worth so much more than a thousand words; and it\u2019s great for cats.\u201d\nPaul Swain\n\n\nNext time you\u2019re 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\u2019t scrimp on the GIFs. And above all, have a great Christmas!", "year": "2015", "author": "Sally Jenkinson", "author_slug": "sallyjenkinson", "published": "2015-12-18T00:00:00+00:00", "url": "https://24ways.org/2015/cooking-up-effective-technical-writing/", "topic": "content"}
{"rowid": 65, "title": "The Accessibility Mindset", "contents": "Accessibility is often characterized as additional work, hard to learn and only affecting a small number of people. Those myths have no logical foundation and often stem from outdated information or misconceptions.\nIndeed, it is an additional skill set to acquire, quite like learning new JavaScript frameworks, CSS layout techniques or new HTML elements. But it isn\u2019t particularly harder to learn than those other skills.\nA World Health Organization (WHO) report on disabilities states that,\n\n[i]ncluding children, over a billion people (or about 15% of the world\u2019s population) were estimated to be living with disability.\n\nBeing disabled is not as unusual as one might think. Due to chronic health conditions and older people having a higher risk of disability, we are also currently paving the cowpath to an internet that we can still use in the future.\nAccessibility has a very close relationship with usability, and advancements in accessibility often yield improvements in the usability of a website. Websites are also more adaptable to users\u2019 needs when they are built in an accessible fashion.\nBeyond the bare minimum\nIn the time of table layouts, web developers could create code that passed validation rules but didn\u2019t adhere to the underlying semantic HTML model. We later developed best practices, like using lists for navigation, and with HTML5 we started to wrap those lists in nav elements. Working with accessibility standards is similar. The Web Content Accessibility Guidelines (WCAG) 2.0 can inform your decision to make websites accessible and can be used to test that you met the success criteria. What it can\u2019t do is measure how well you met them. \nW3C developed a long list of techniques that can be used to make your website accessible, but you might find yourself in a situation where you need to adapt those techniques to be the most usable solution for your particular problem.\nThe checkbox below is implemented in an accessible way: The input element has an id and the label associated with the checkbox refers to the input using the for attribute. The hover area is shown with a yellow background and a black dotted border:\nOpen video\n \nThe label is clickable and the checkbox has an accessible description. Job done, right? Not really. Take a look at the space between the label and the checkbox:\nOpen video\n \nThe gutter is created using a right margin which pushes the label to the right. Users would certainly expect this space to be clickable as well. The simple solution is to wrap the label around the checkbox and the text:\nOpen video\n \nYou can also set the label to display:block; to further increase the clickable area:\nOpen video\n \nAnd while we\u2019re at it, users might expect the whole box to be clickable anyway. Let\u2019s apply the CSS that was on a wrapping div element to the label directly:\nOpen video\n \nThe result enhances the usability of your form element tremendously for people with lower dexterity, using a voice mouse, or using touch interfaces. And we only used basic HTML and CSS techniques; no JavaScript was added and not one extra line of CSS.\n \nButton Example\nThe button below looks like a typical edit button: a pencil icon on a real button element. But if you are using a screen reader or a braille keyboard, the button is just read as \u201cbutton\u201d without any indication of what this button is for.\nOpen video\n A screen reader announcing a button. Contains audio.\nThe code snippet shows why the button is not properly announced:\n\n \n \nAn icon font is used to display the icon and no text alternative is given. A possible solution to this problem is to use the title or aria-label attributes, which solves the alternative text use case for screen reader users:\nOpen video\n A screen reader announcing a button with a title.\nHowever, screen readers are not the only way people with and without disabilities interact with websites. For example, users can reset or change font families and sizes at will. This helps many users make websites easier to read, including people with dyslexia. Your icon font might be replaced by a font that doesn\u2019t include the glyphs that are icons. Additionally, the icon font may not load for users on slow connections, like on mobile phones inside trains, or because users decided to block external fonts altogether. The following screenshots show the mobile GitHub view with and without external fonts:\nThe mobile GitHub view with and without external fonts.\nEven if the title/aria-label approach was used, the lack of visual labels is a barrier for most people under those circumstances. One way to tackle this is using the old-fashioned img element with an appropriate alt attribute, but surprisingly not every browser displays the alternative text visually when the image doesn\u2019t load.\n\n \n \nProviding always visible text is an alternative that can work well if you have the space. It also helps users understand the meaning of the icons.\n\n Edit\n \nThis also reads just fine in screen readers:\nOpen video\n A screen reader announcing the revised button.\nClever usability enhancements don\u2019t stop at a technical implementation level. Take the BBC iPlayer pages as an example: when a user navigates the \u201ccaptioned videos\u201d or \u201caudio description\u201d categories and clicks on one of the videos, captions or audio descriptions are automatically switched on. Small things like this enhance the usability and don\u2019t need a lot of engineering resources. It is more about connecting the usability dots for people with disabilities. Read more about the BBC iPlayer accessibility case study.\nMore information\nW3C has created several documents that make it easier to get the gist of what web accessibility is and how it can benefit everyone. You can find out \u201cHow People with Disabilities Use the Web\u201d, there are \u201cTips for Getting Started\u201d for developers, designers and content writers. And for the more seasoned developer there is a set of tutorials on web accessibility, including information on crafting accessible forms and how to use images in an accessible way.\nConclusion\nYou can only produce a web project with long-lasting accessibility if accessibility is not an afterthought. Your organization, your division, your team need to think about accessibility as something that is the foundation of your website or project. It needs to be at the same level as performance, code quality and design, and it needs the same attention. Users often don\u2019t notice when those fundamental aspects of good website design and development are done right. But they\u2019ll always know when they are implemented poorly.\nIf you take all this into consideration, you can create accessibility solutions based on the available data and bring accessibility to people who didn\u2019t know they\u2019d need it:\nOpen video\n \nIn this video from the latest Apple keynote, the Apple TV is operated by voice input through a remote. When the user asks \u201cWhat did she say?\u201d the video jumps back fifteen seconds and captions are switched on for a brief time. All three, the remote, voice input and captions have their roots in assisting people with disabilities. Now they benefit everyone.", "year": "2015", "author": "Eric Eggert", "author_slug": "ericeggert", "published": "2015-12-17T00:00:00+00:00", "url": "https://24ways.org/2015/the-accessibility-mindset/", "topic": "code"}
{"rowid": 58, "title": "Beyond the Style Guide", "contents": "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).\nDon\u2019t worry, this isn\u2019t 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.\nThe auteur\u2019s style guide\nAlthough 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.\nIn straddling the realms of graphic design and programming, it\u2019s 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.\nPainting by numbers\nIn 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 \u2013 perhaps one reason why we\u2019re seeing the homogenisation of web design.\nIn 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 \u2018Design Machines\u2019 Travis Gertz argued that (emphasis added):\n\nDesign 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\u2019re pretty good at using them to build repeatable components and site-wide standards, but that\u2019s sort of where it ends. [\u2026] But to stop there is to ignore the true purpose and potential of a design system.\n\nUnless 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.\nAnatomy of a button\nLet\u2019s 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.\nThe different layers of our button component.\nContent\nThe 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 \u2018Submit form\u2019, or adopt a more friendly tone, perhaps \u2018Send us your message\u2019) and appropriate language. For an internationalised interface, this may also impact word length and text direction or orientation.\nStructure\nHTML 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:\nButton text \nButton text \nNote: One of the reasons I prefer to use instead of , 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.\nWe 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.\nPresentation\nThe 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.\nBehaviour\nA 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.\nTranscending layers\nThis overview reinforces Ethan\u2019s note from earlier in this series:\n\nI\u2019ve found that thinking about my design as existing in broad experience tiers \u2013 in layers \u2013 is one of the best ways of designing for the modern web.\n\nWhile it\u2019s 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.\nVisual design language: documenting the missing piece\nEven 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?\nThese 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.\nWhereas 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!\nType pairings in the US Web Design Standards guide.\nFor 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:\nColour palettes in the US Web Design Standards guide.\nA visual language in code form\nProperly 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.\nIn 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.\nTake this simple example, an article summary on a website counting down the best Christmas movies:\nThe design for our simple component example.\nOur markup is as follows, using appropriate semantic HTML elements and incorporating the vocabulary from our collection of design patterns (expressed using the BEM methodology):\n\n \n\n \n
It\u2019s unlikely that Bill Murray could ever have got through his career without playing a version of Scrooge\u2026
\n
\n\n \n \nWe 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:\n.summary {\n margin-bottom: ($baseline * 4)\n}\n\n.summary__title {\n @include font-family(display-serif);\n @include font-size(title);\n color: palette(neutral, dark);\n margin-bottom: ($baseline * 4);\n border-top: $rule-height solid palette(primary, purple);\n padding-top: ($baseline * 2);\n}\n\n.summary__position {\n @include font-family(display-sans, 300);\n color: palette(neutral, mid);\n}\n\n.summary__body {\n @include font-family(text-serif);\n @include font-size(body);\n margin-bottom: ($baseline * 2);\n}\n\n.summary__meta {\n @include font-family(text-sans);\n @include font-size(caption);\n}\nOf 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:\nThe design of a component on the Guardian website, described in terms of its Sass-powered design system.\nUnlocking possibility\nAlongside tools like preprocessors, newer CSS layout modules like flexbox and grid layout mean the friction we\u2019ve 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\u2019re fully represented in both documentation and code. That way, together, we can build systems that allow for greater visual expression. After all, there\u2019s more than one way to bake a Christmas cake.", "year": "2015", "author": "Paul Lloyd", "author_slug": "paulrobertlloyd", "published": "2015-12-16T00:00:00+00:00", "url": "https://24ways.org/2015/beyond-the-style-guide/", "topic": "design"}
{"rowid": 68, "title": "Grid, Flexbox, Box Alignment: Our New System for Layout", "contents": "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.\nGrid 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.\nAnother 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. \nOwing 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. \nIf 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\u2019ll be easily able to date a website to circa 2015 by seeing or
in the markup.\nIn this article, I\u2019m 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.\nTo 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. \nRelationship\nItems 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\u2019s 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.\nAt a very simple level, the relationship between elements means that we can easily achieve full-height columns. In flexbox:\nSee the Pen Flexbox equal height columns by rachelandrew (@rachelandrew) on CodePen.\n\nAnd in grid layout (requires a CSS grid-supporting browser):\nSee the Pen Grid equal height columns by rachelandrew (@rachelandrew) on CodePen.\n\nAlignment\nFull-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\u2019d like to have under your tree this Christmas, then this is the box you\u2019ll want to unwrap first.\nThe 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.\nOur 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.\nThe 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.\nTake a look at an example in flexbox:\nSee the Pen Flexbox alignment by rachelandrew (@rachelandrew) on CodePen.\n\nAnd also in grid layout (requires a CSS grid-supporting browser):\nSee the Pen Grid alignment by rachelandrew (@rachelandrew) on CodePen.\n\nThe alignment properties used with CSS grid layout.\nFluid grids\nA cornerstone of responsive design is the concept of fluid grids.\n\n\u201c[\u2026]every aspect of the grid\u2014and the elements laid upon it\u2014can be expressed as a proportion relative to its container.\u201d\n\u2014Ethan Marcotte, \u201cFluid Grids\u201d\n\nThe 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.\nh1 {\n margin-left: 14.575%; /*\u00a0144px / 988px = 0.14575\u00a0*/\n width: 70.85%; /*\u00a0700px / 988px = 0.7085\u00a0*/\n}\nIn more recent years, we\u2019ve 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.\nThe most basic of flexbox demos shows this fluidity in action. The justify-content property \u2013 another property defined in the box alignment module \u2013 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.\nIn 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.\nSee the Pen Flexbox: justify-content by rachelandrew (@rachelandrew) on CodePen.\n\nFor 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.\nThe flexbox flex property is a shorthand for:\n\nflex-grow\nflex-shrink\nflex-basis\n\nThe 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.\n\nflex: 1 1 200px: a flexible box that can grow and shrink from a 200px basis.\nflex: 0 0 200px: a box that will be 200px and cannot grow or shrink.\nflex: 1 0 200px: a box that can grow bigger than 200px, but not shrink smaller.\n\nIn this example, I have a set of boxes that can all grow and shrink equally from a 100 pixel basis.\nSee the Pen Flexbox: flex-grow by rachelandrew (@rachelandrew) on CodePen.\n\nWhat 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.\nIf 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:\nSee the Pen Flexbox: flex-grow by rachelandrew (@rachelandrew) on CodePen.\n\nOnce 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.\nIn 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.\ngrid-template-columns: 1fr 2fr 2fr 2fr;\nSee the Pen Grid fraction units by rachelandrew (@rachelandrew) on CodePen.\n\nThe four-track grid.\nSeparation of concerns\nMy 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.\nBrowsers 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.\nHere is a snippet from the Bootstrap grid examples \u2013 two columns with two nested columns:\n
\n
\n .col-md-8\n
\n
\n .col-md-6\n
\n
\n .col-md-6\n
\n
\n
\n
\n .col-md-4\n
\n
\nNot a million miles away from something I might have written in 1999.\n
\n \n \n .col-md-8\n \n \n \n .col-md-6\n \n \n .col-md-6\n \n \n
\n \n \n .col-md-4\n \n \n
\nGrid 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.\nFlexbox 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.\nSee the Pen Flexbox: order by rachelandrew (@rachelandrew) on CodePen.\n\nGrid 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):\nSee the Pen Grid positioning in two dimensions by rachelandrew (@rachelandrew) on CodePen.\n\nLaying out our items in two dimensions using grid layout.\nAs 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.\nA note on accessibility and reordering\nThe 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\u2019s draft states\n\n\u201cAuthors must use order only for visual, not logical, reordering of content. Style sheets that use order to perform logical reordering are non-conforming.\u201d\n\u2014CSS Flexible Box Layout Module Level 1, Editor\u2019s Draft (3 December 2015)\n\nThis 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.\nAutomatic content placement with rules\nHaving 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.\nSomething 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, \u201cDisplay this content, using these rules.\u201d\nAs 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.\nThe poem is displayed first in the source as a set of paragraphs. I\u2019ve 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\u2019ve added a class of landscape to the landscape ones.\nThe 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.\nAt wider screen widths, I declare a four-track grid, and position my poem around the grid, keeping it in a readable order.\nI 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.\nTake a look and play around with the full demo (requires a CSS grid layout-supporting browser):\nSee the Pen Grid auto-flow with rules by rachelandrew (@rachelandrew) on CodePen.\n\nThe final automatic placement example.\nMy wish for 2016\nI 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 \u2014 that we can start to move away from using the wrong tools for the job.\nHowever, I also hope that we\u2019ll 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.\nSome further reading\n\nI maintain a site of grid layout examples and resources at Grid by Example.\nThe three CSS specifications I\u2019ve discussed can be found as editor\u2019s drafts: CSS grid, flexbox, box alignment.\nI wrote about the last three years of my interest in CSS grid layout, which gives something of a history of the specification.\nMore examples of box alignment and grid layout.\nMy presentation at Fronteers earlier this year, in which I explain more about these concepts.", "year": "2015", "author": "Rachel Andrew", "author_slug": "rachelandrew", "published": "2015-12-15T00:00:00+00:00", "url": "https://24ways.org/2015/grid-flexbox-box-alignment-our-new-system-for-layout/", "topic": "code"}
{"rowid": 67, "title": "What I Learned about Product Design This Year", "contents": "2015 was a humbling year for me. In September of 2014, I joined a tiny but established startup called SproutVideo as their third employee and first designer. The role interests me because it affords the opportunity to see how design can grow a solid product with a loyal user-base into something even better. \nThe work I do now could also have a real impact on the brand and user experience of our product for years to come, which is a thrilling prospect in an industry where much of what I do feels small and temporary. I got in on the ground floor of something special: a small, dedicated, useful company that cares deeply about making video hosting effortless and rewarding for our users.\nI had (and still have) grand ideas for what thoughtful design can do for a product, and the smaller-scale product design work I\u2019ve done or helped manage over the past few years gave me enough eager confidence to dive in head first. Readers who have experience redesigning complex existing products probably have a knowing smirk on their face right now. As I said, it\u2019s been humbling. A year of focused product design, especially on the scale we are trying to achieve with our small team at SproutVideo, has taught me more than any projects in recent memory. I\u2019d like to share a few of those lessons.\nProduct design is very different from marketing design\nThe majority of my recent work leading up to SproutVideo has been in marketing design. These projects are so fun because their aim is to communicate the value of the product in a compelling and memorable way. In order to achieve this goal, I spent a lot of time thinking about content strategy, responsive design, and how to create striking visuals that tell a story. These are all pursuits I love.\nProduct design is a different beast. When designing a homepage, I can employ powerful imagery, wild gradients, and somewhat-quirky fonts. When I began redesigning the SproutVideo product, I wanted to draw on all the beautiful assets I\u2019ve created for our marketing materials, but big gradients, textures, and display fonts made no sense in this new context.\nThat\u2019s because the product isn\u2019t about us, and it isn\u2019t about telling our story. Product design is about getting out of the way so people can do their job. The visual design is there to create a pleasant atmosphere for people to work in, and to help support the user experience. Learning to take \u201cus\u201d out of the equation took some work after years of creating gorgeous imagery and content for the sales-driven side of businesses.\nI\u2019ve learned it\u2019s very valuable to design both sides of the experience, because marketing and product design flex different muscles. If you\u2019re currently in an environment where the two are separate, consider switching teams in 2016. Designing for product when you\u2019ve mostly done marketing, or vice versa, will deepen your knowledge as a designer overall. You\u2019ll face new unexpected challenges, which is the only way to grow.\nProduct design can not start with what looks good on Dribbble\nI have an embarrassing confession: when I began the redesign, I had a secret goal of making something that would look gorgeous in my portfolio. I have a collection of product shots that I admire on Dribbble; examples of beautiful dashboards and widgets and UI elements that look good enough to frame. I wanted people to feel the same way about the final outcome of our redesign. Mistakenly, this was a factor in my initial work. I opened Photoshop and crafted pixel-perfect static buttons and form elements and color palettes that\u200a\u2014\u200awhen applied to our actual product\u200a\u2014\u200alooked like a toddler beauty pageant. It added up to a lot of unusable shininess, noise, and silliness.\nI was disappointed; these elements seemed so lovely in isolation, but in context, they felt tacky and overblown. I realized: I\u2019m not here to design the world\u2019s most beautiful drop down menu. Good design has nothing to do with ego, but in my experience designers are, at least a little bit, secret divas. I\u2019m no exception. I had to remind myself that I am not working in service of a bigger Dribbble following or to create the most Pinterest-ing work. My function is solely to serve the users\u200a\u2014\u200ato make life a little better for the good people who keep my company in business.\nThis meant letting go of pixel-level beauty to create something bigger and harder: a system of elements that work together in harmony in many contexts. The visual style exists to guide the users. When done well, it becomes a language that users understand, so when they encounter a new feature or have a new goal, they already feel comfortable navigating it. This meant stripping back my gorgeous animated menu into something that didn\u2019t detract from important neighboring content, and could easily fit in other parts of the app. In order to know what visual style would support the users, I had to take a wider view of the product as a whole.\nJust accept that designing a great product \u2013 like many worthwhile pursuits \u2013 is initially laborious and messy\nOnce I realized I couldn\u2019t start by creating the most Dribbble-worthy thing, I knew I\u2019d have to begin with the unglamorous, frustrating, but weirdly wonderful work of mapping out how the product\u2019s content could better be structured. Since we\u2019re redesigning an existing product, I assumed this would be fairly straightforward: the functionality was already in place, and my job was just to structure it in a more easily navigable way.\nI started by handing off a few wireframes of the key screens to the developer, and that\u2019s when the questions began rolling in: \u201cIf we move this content into a modal, how will it affect this similar action here?\u201d \u201cWhat happens if they don\u2019t add video tags, but they do add a description?\u201d \u201cWhat if the user has a title that is 500 characters long?\u201d \u201cWhat if they want their video to be private to some users, but accessible to others?\u201d.\nHow annoying (but really, fantastic) that people use our product in so many ways. Turns out, product design isn\u2019t about laying out elements in the most ideal scenario for the user that\u2019s most convenient for you. As product designers, we have to foresee every outcome, and anticipate every potential user need.\nWhich brings me to another annoying epiphany: if you want to do it well, and account for every user, product design is so much more snarly and tangled than you\u2019d expect going in. I began with a simple goal: to improve the experience on just one of our key product pages. However, every small change impacts every part of the product to some degree, and that impact has to be accounted for. Every decision is based on assumptions that have to be tested; I test my assumptions by observing users, talking to the team, wireframing, and prototyping. Many of my assumptions are wrong. There are days when it\u2019s incredibly frustrating, because an elegant solution for users with one goal will complicate life for users with another goal. It\u2019s vital to solve as many scenarios as possible, even though this is slow, sometimes mind-bending work.\nAs a side bonus, wireframing and prototyping every potential state in a product is tedious, but your developers will thank you for it. It\u2019s not their job to solve what happens when there\u2019s an empty state, error, or edge case. Showing you\u2019ve accounted for these scenarios will win a developer\u2019s respect; failing to do so will frustrate them.\nWhen you\u2019ve created and tested a system that supports user needs, it will be beautiful\nRemember what I said in the beginning about wanting to create a Dribbble-worthy product? When I stopped focusing on the visual details of the design (color, spacing, light and shadow, font choices) and focused instead on structuring the content to maximize usability and delight, a beautiful design began to emerge naturally.\nI began with grayscale, flat wireframes as a strategy to keep me from getting pulled into the visual style before the user experience was established. As I created a system of elements that worked in harmony, the visual style choices became obvious. Some buttons would need to be brighter and sit off the page to help the user spot important actions. Some elements would need line separators to create a hierarchy, where others could stand on their own as an emphasized piece of content. As the user experience took shape, the visual style emerged naturally to support it. The result is a product that feels beautiful to use, because I was thoughtful about the experience first.\n\nA big takeaway from this process has been that my assumptions will often be proven wrong. My assumptions about how to design a great product, and how users will interact with that product, have been tested and revised repeatedly. At SproutVideo we\u2019re about to undertake the biggest test of our work; we\u2019re going to launch a small part of the product redesign to our users. If I\u2019ve learned anything, it\u2019s that I will continue to be humbled by the ongoing effort of making the best product I can, which is a wonderful thing.\nNext year, I hope you all get to do work that takes you out of our comfort zone. Be regularly confounded and embarrassed by your wrong assumptions, learn from them, and come back and tell us what you learned in 2016.", "year": "2015", "author": "Meagan Fisher", "author_slug": "meaganfisher", "published": "2015-12-14T00:00:00+00:00", "url": "https://24ways.org/2015/what-i-learned-about-product-design-this-year/", "topic": "design"}
{"rowid": 72, "title": "Designing with Contrast", "contents": "When an appetite for aesthetics over usability becomes the bellwether of user interface design, it\u2019s time to reconsider who we\u2019re designing for.\nOver the last few years, we have questioned the signifiers that gave obvious meaning to the function of interface elements. Strong textures, deep shadows, gradients \u2014 imitations of physical objects \u2014 were discarded. And many, rightfully so. Our audiences are now more comfortable with an experience that feels native to the technology, so we should respond in kind.\nYet not all of the changes have benefitted users. Our efforts to simplify brought with them a trend of ultra-minimalism where aesthetics have taken priority over legibility, accessibility and discoverability. The trend shows no sign of losing popularity \u2014 and it is harming our experience of digital content.\n\nA thin veneer\nWe are in a race to create the most subdued, understated interface. Visual contrast is out. In its place: the thinnest weights of a typeface and white text on bright color backgrounds. Headlines, text, borders, backgrounds, icons, form controls and inputs: all grey.\nWhile we can look back over the last decade and see minimalist trends emerging on the web, I think we can place a fair share of the responsibility for the recent shift in priorities on Apple. The release of iOS 7 ushered in a radical change to its user interface. It paired mobile interaction design to the simplicity and eloquence of Apple\u2019s marketing and product design. It was a catalyst. We took what we saw, copied and consumed the aesthetics like pick-and-mix.\nNew technology compounds this trend. Computer monitors and mobile devices are available with screens of unprecedented resolutions. Ultra-light type and subtle hues, difficult to view on older screens, are more legible on these devices. It would be disingenuous to say that designers have always worked on machines representative of their audience\u2019s circumstances, but the gap has never been as large as it is now. We are running the risk of designing VIP lounges where the cost of entry is a Mac with a Retina display.\nMinimalist expectations\nLike progressive enhancement in an age of JavaScript, many good and sensible accessibility practices are being overlooked or ignored. We\u2019re driving unilateral design decisions that threaten accessibility. We\u2019ve approached every problem with the same solution, grasping on to the integrity of beauty, focusing on expression over users\u2019 needs and content. \nSomeone once suggested to me that a client\u2019s website should include two states. The first state would be the ideal experience, with low color contrast, light font weights and no differentiation between links and text. It would be the default. The second state would be presented in whatever way was necessary to meet accessibility standards. Users would have to opt out of the default state via a toggle if it wasn\u2019t meeting their needs. A sort of first-class, upper deck cabin equivalent of graceful degradation. That this would divide the user base was irrelevant, as the aesthetics of the brand were absolute. \nIt may seem like an unusual anecdote, but it isn\u2019t uncommon to see this thinking in our industry. Again and again, we place the burden of responsibility to participate in a usable experience on others. We view accessibility and good design as mutually exclusive. Taking for granted what users will tolerate is usually the forte of monopolistic services, but increasingly we apply the same arrogance to our new products and services.\n\nImitation without representation\nAll of us are influenced in one way or another by one another\u2019s work. We are consciously and unconsciously affected by the visual and audible activity around us. This is important and unavoidable. We do not produce work in a vacuum. We respond to technology and culture. We channel language and geography. We absorb the sights and sounds of film, television, news. To mimic and copy is part and parcel of creating something an audience of many can comprehend and respond to. Our clients often look first to their competitors\u2019 products to understand their success.\nHowever, problems arise when we focus on style without context; form without function; mimicry as method. Copied and reused without any of the ethos of the original, stripped of deliberate and informed decision-making, the so-called look and feel becomes nothing more than paint on an empty facade.\nThe typographic and color choices so in vogue today with our popular digital products and services have little in common with the brands they are meant to represent.\n\nFor want of good design, the message was lost\nThe question to ask is: does the interface truly reflect the product? Is it an accurate characterization of the brand and organizational values? Does the delivery of the content match the tone of voice?\nThe answer is: probably not. Because every organization, every app or service, is unique. Each with its own personality, its own values and wonderful quirks. Design is communication. We should do everything in our role as professionals to use design to give voice to the message. Our job is to clearly communicate the benefits of a service and unreservedly allow access to information and content. To do otherwise, by obscuring with fashionable styles and elusive information architecture, does a great disservice to the people who chose to engage with and trust our products.\nWe can achieve hierarchy and visual rhythm without resorting to extreme reduction. We can craft a beautiful experience with fine detail and curiosity while meeting fundamental standards of accessibility (and strive to meet many more).\nStandards of excellence\nIt isn\u2019t always comfortable to step back and objectively question our design choices. We get lost in the flow of our work, using patterns and preferences we\u2019ve tried and tested before. That our decisions often seem like second nature is a gift of experience, but sometimes it prevents us from finding our blind spots.\nI was first caught out by my own biases a few years ago, when designing an interface for the Bank of England. After deciding on the colors for the typography and interactive elements, I learned that the site had to meet AAA accessibility standards. My choices quickly fell apart. It was eye-opening. I had to start again with restrictions and use size, weight and placement instead to construct the visual hierarchy.\nEven now, I make mistakes. On a recent project, I used large photographs on an organization\u2019s website to promote their products. Knowing that our team had control over the art direction, I felt confident that we could compose the photographs to work with text overlays. Despite our best effort, the cropped images weren\u2019t always consistent, undermining the text\u2019s legibility. If I had the chance to do it again, I would separate the text and image.\nSo, what practical things can we consider to give our users the experience they deserve?\nPut guidelines in place\n\nThink about your brand values. Write down keywords and use them as a framework when choosing a typeface. Explore colors that convey the organization\u2019s personality and emotional appeal.\nDefine a color palette that is web-ready and meets minimum accessibility standards. Note which colors are suitable for use with text. Only very dark hues of grey are consistently legible so keep them for non-essential text (for example, as placeholders in form inputs).\nFind which background colors you can safely use with white text, and consider integrating contrast checks into your workflow.\nUse roman and medium weights for body copy. Reserve lighter weights of a typeface for very large text. Thin fonts are usually the first to break down because of aliasing differences across platforms and screens.\nCheck that the size, leading and length of your type is always legible and readable. Define lower and upper limits. Small text is best left for captions and words in uppercase.\nAvoid overlaying text on images unless it\u2019s guaranteed to be legible. If it\u2019s necessary to optimize space in the layout, give the text a container. Scrims aren\u2019t always reliable: the text will inevitably overlap a part of the photograph without a contrasting ground.\n\nTest your work\n\nReview legibility and contrast on different devices. It\u2019s just as important as testing the layout of a responsive website. If you have a local device lab, pay it a visit.\nFind a computer monitor near a window when the sun is shining. Step outside the studio and try to read your content on a mobile device with different brightness levels. \nAsk your friends and family what they use at home and at work. It\u2019s one way of making sure your feedback isn\u2019t always coming from a closed loop.\n\nPush your limits\n\nYou define what the user sees. If you\u2019ve inherited brand guidelines, question them. If you don\u2019t agree with the choices, make the case for why they should change.\nExperiment with size, weight and color to find contrast. Objects with low contrast appear similar to one another and undermine the visual hierarchy. Weak relationships between figure and ground diminish visual interest. A balanced level of contrast removes ambiguity and creates focal points. It captures and holds our attention.\nIf you\u2019re lost for inspiration, look to graphic design in print. We have a wealth of history, full of examples that excel in using contrast to establish visual hierarchy.\nEmbrace limitations. Use boundaries as an opportunity to explore possibilities.\n\nMore than just a facade\nDesigning with standards encourages legibility and helps to define a strong visual hierarchy. Design without exclusion (through neither negligence or intent) gets around discussions of demographics, speaks to a larger audience and makes good business sense. Following the latest trends not only weakens usability but also hinders a cohesive and distinctive brand.\nUsers will make means when they need to, by increasing browser font sizes or enabling system features for accessibility. But we can do our part to take as much of that burden off of the user and ask less of those who need it most.\nIn architecture, it isn\u2019t buildings that mimic what is fashionable that stand the test of time. Nor do we admire buildings that tack on separate, poorly constructed extensions to meet a bare minimum of safety regulations. We admire architecture that offers well-considered, remarkable, usable spaces with universal access.\nPerhaps we can take inspiration from these spaces. Let\u2019s give our buildings a bold voice and make sure the doors are open to everyone.", "year": "2015", "author": "Mark Mitchell", "author_slug": "markmitchell", "published": "2015-12-13T00:00:00+00:00", "url": "https://24ways.org/2015/designing-with-contrast/", "topic": "design"}
{"rowid": 63, "title": "Be Fluid with Your Design Skills: Build Your Own Sites", "contents": "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 \u2018Designers Vs Developers\u2019, an infographic that showed us the differences between the men(!) who created websites. \nDesigners 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.\nThankfully, 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 \u2013 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.\nSo 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! \nOK, 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\u2019s how we should think of our skills, our interests and even our job titles. After all, Steve Jobs told us that \u201cDesign is not just what it looks like and feels like. Design is how it works.\u201d Sorry skinny-jean-wearing designers \u2013 this means we\u2019re all designing something together. And it\u2019s 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.\nLike 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\u2019ve never built their own site? I\u2019m not talking the big stuff, I\u2019m talking about your portfolio site, your mate\u2019s business website, a website for that great idea you\u2019ve had. I\u2019m talking about doing it yourself to get an unique insight into how it feels.\nWe all know that designers and developers alike love an
, so here it is.\nTen reasons designers should be fluid with their skills and build their own sites\n1. It\u2019s never been easier\nNow here\u2019s where the definition of \u2018build\u2019 is going to get a bit loose and people are going to get angry, but when I say it\u2019s never been easier I mean because of the existence of apps and software like WordPress, Squarespace, Tumblr, et al. It\u2019s easy to make something and get it out there into the world, and these are all gateway drugs to hard coding!\n2. You\u2019ll understand how it feels\nHow it feels to be so proud that something actually works that you momentarily don\u2019t notice if the kerning is off or the padding is inconsistent. How it feels to see your site appear when you\u2019ve redirected a URL. How it feels when you just can\u2019t work out where that one extra space is in a line of PHP that has killed your whole site.\n3. It makes you a designer\nNot a better designer, it makes you a designer when you are designing how things look and how they work. \n4. You learn about movement\nPhotoshop and Sketch just don\u2019t cut it yet. Until you see your site in a browser or your app on a phone, it\u2019s hard to imagine how it moves. Building your own sites shows you that it\u2019s not just about how the content looks on the screen, but how it moves, interacts and feels.\n5. You make techie friends\nAll the tutorials and forums in the world can\u2019t 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\u2019ve 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. \n6. You will own domain names\nWhen something is paid for, online and searchable then it\u2019s real and you\u2019ve 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.\n7. People will ask you to do things\u2028\nLearning 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 \u201cMake me a website for free\u201d, but more often it\u2019s cool things like \u201cCome and speak at my conference\u201d, \u201cWrite an article for my magazine\u201d and \u201cCollaborate with me.\u201d\n8. The young people are coming!\nThey love typography, they love print, they love layout, but they\u2019ve known how to put a website together since they started their first blog aged five and they show me clever apps they\u2019ve knocked together over the weekend! They\u2019re new, they\u2019re fluid, and they\u2019re better than us!\n9. Your portfolio is your portfolio\nOK, it\u2019s 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\u2019s bothered to work out how to change the Squarespace favicon!) \n10. It keeps you fluid!\nBuilding your own websites is tough. You\u2019ll never be happy with it, you\u2019ll constantly be updating it to keep up with technology and fashion, and by the time you\u2019ve finished it you\u2019ll want to start all over again. Perfect for forcing you to stay up-to-date with what\u2019s going on in the industry.\n ", "year": "2015", "author": "Ros Horner", "author_slug": "roshorner", "published": "2015-12-12T00:00:00+00:00", "url": "https://24ways.org/2015/be-fluid-with-your-design-skills-build-your-own-sites/", "topic": "code"}
{"rowid": 71, "title": "Upping Your Web Security Game", "contents": "When I started working in web security fifteen years ago, web development looked very different. The few non-static web applications were built using a waterfall process and shipped quarterly at best, making it possible to add security audits before every release; applications were deployed exclusively on in-house servers, allowing Info Sec to inspect their configuration and setup; and the few third-party components used came from a small set of well-known and trusted providers. And yet, even with these favourable conditions, security teams were quickly overwhelmed and called for developers to build security in.\nIf the web security game was hard to win before, it\u2019s doomed to fail now. In today\u2019s web development, every other page is an application, accepting inputs and private data from users; software is built continuously, designed to eliminate manual gates, including security gates; infrastructure is code, with servers spawned with little effort and even less security scrutiny; and most of the code in a typical application is third-party code, pulled in through open source repositories with rarely a glance at who provided them.\nSecurity teams, when they exist at all, cannot solve this problem. They are vastly outnumbered by developers, and cannot keep up with the application\u2019s pace of change. For us to have a shot at making the web secure, we must bring security into the core. We need to give it no less attention than that we give browser compatibility, mobile design or web page load times. More broadly, we should see security as an aspect of quality, expecting both ourselves and our peers to address it, and taking pride when we do it well.\nWhere To Start?\nEmbracing security isn\u2019t something you do overnight.\nA good place to start is by reviewing things you\u2019re already doing \u2013 and trying to make them more secure. Here are three concrete steps you can take to get going.\nHTTPS\nThreats begin when your system interacts with the outside world, which often means HTTP. As is, HTTP is painfully insecure, allowing attackers to easily steal and manipulate data going to or from the server. HTTPS adds a layer of crypto that ensures the parties know who they\u2019re talking to, and that the information exchanged can be neither modified nor sniffed.\nHTTPS is relevant to any site. If your non-HTTPS site holds opinions, reading it may get your users in trouble with employers or governments. If your users believe what you say, attackers can modify your non-HTTPS to take advantage of and abuse that trust. If you want to use new browser technologies like HTTP2 and service workers, your site will need to be HTTPS. And if you want to be discovered on the web, using HTTPS can help your Google ranking. For more details on why I think you should make the switch to HTTPS, check out this post, these slides and this video.\nUsing HTTPS is becoming easier and cheaper. Here are a few free tools that can help:\n\nGet free and easy HTTPS delivery from Cloudflare (be sure to use \u201cFull SSL\u201d!)\nGet a free and automation-friendly certificate from Let\u2019s Encrypt (now in open beta).\nTest how well your HTTPS is set up using SSLTest.\n\nOther vendors and platforms are rapidly simplifying and reducing the cost of their HTTPS offering, as demand and importance grows.\nTwo-Factor Authentication\nThe most sensitive data is usually stored behind a login, and the authentication process is the primary gate in front of this data. Making this process secure has many aspects, including using HTTPS when accepting credentials, having a strong password policy, never storing the password, and more.\nAll of these are important, but the best single step to boost your authentication security is to introduce two-factor authentication (2FA). Adding 2FA usually means prompting users for an additional one-time code when logging in, which they get via SMS or a mobile app (e.g. Google Authenticator). This code is short-lived and is extremely hard for a remote attacker to guess, thus vastly reducing the risk a leaked or easily guessed password presents.\nThe typical algorithm for 2FA is based on an IETF standard called the time-based one-time password (TOTP) algorithm, and it isn\u2019t that hard to implement. Joel Franusic wrote a great post on implementing 2FA; modules like speakeasy make it even easier; and you can swap SMS with Google Authenticator or your own app if you prefer. If you don\u2019t want to build 2FA support yourself, you can purchase two/multi-factor authentication services from vendors such as DuoSecurity, Auth0, Clef, Hypr and others.\nIf implementing 2FA still feels like too much work, you can also choose to offload your entire authentication process to an OAuth-based federated login. Many companies offer this today, including Facebook, Google, Twitter, GitHub and others. These bigger players tend to do authentication well and support 2FA, but you should consider what data you\u2019re sharing with them in the process.\nTracking Known Vulnerabilities\nMost of the code in a modern application was actually written by third parties, and pulled into your app as frameworks, modules and libraries. While using these components makes us much more productive, along with their functionality we also adopt their security flaws. To make things worse, some of these flaws are well-known vulnerabilities, making it easy for hackers to take advantage of them in an attack.\nThis is a real problem and happens on pretty much every platform. Do you develop in Java? In 2014, over 6% of Java modules downloaded from Maven had a known severe security issue, the typical Java applications containing 24 flaws. Are you coding in Node.js? Roughly 14% of npm packages carry a known vulnerability, and over 60% of dev shops find vulnerabilities in their code. 30% of Docker Hub containers include a high priority known security hole, and 60% of the top 100,000 websites use client-side libraries with known security gaps.\nTo find known security issues, take stock of your dependencies and match them against language-specific lists such as Snyk\u2019s vulnerability DB for Node.js, rubysec for Ruby, victims-db for Python and OWASP\u2019s Dependency Check for Java. Once found, you can fix most issues by upgrading the component in question, though that may be tricky for indirect dependencies. \nThis process is still way too painful, which means most teams don\u2019t do it. The Snyk team and I are hoping to change that by making it as easy as possible to find, fix and monitor known vulnerabilities in your dependencies. Snyk\u2019s wizard will help you find and fix these issues through guided upgrades and patches, and adding Snyk\u2019s test to your continuous integration and deployment (CI/CD) will help you stay secure as your code evolves.\nNote that newly disclosed vulnerabilities usually impact old code \u2013 the one you\u2019re running in production. This means you have to stay alert when new vulnerabilities are disclosed, so you can fix them before attackers can exploit them. You can do so by subscribing to vulnerability lists like US-CERT, OSVDB and NVD. Snyk\u2019s monitor will proactively let you know about new disclosures relevant to your code, but only for Node.js for now \u2013 you can register to get updated when we expand.\nSecuring Yourself\nIn addition to making your application secure, you should make the contributors to that application secure \u2013 including you. Earlier this year we\u2019ve seen attackers target mobile app developers with a malicious Xcode. The real target, however, wasn\u2019t these developers, but rather the users of the apps they create. That you create. Securing your own work environment is a key part of keeping your apps secure, and your users from being compromised.\nThere\u2019s no single step that will make you fully secure, but here are a few steps that can make a big impact:\n\nUse 2FA on all the services related to the application, notably source control (e.g. GitHub), cloud platform (e.g. AWS), CI/CD, CDN, DNS provider and domain registrar. If an attacker compromises any one of those, they could modify or replace your entire application. I\u2019d recommend using 2FA on all your personal services too.\nUse a password manager (e.g. 1Password, LastPass) to ensure you have a separate and complex password for each service. Some of these services will get hacked, and passwords will leak. When that happens, don\u2019t let the attackers access your other systems too.\nSecure your workstation. Be careful what you download, lock your screen when you walk away, change default passwords on services you install, run antivirus software, etc. Malware on your machine can translate to malware in your applications.\nBe very wary of phishing. Smart attackers use \u2018spear phishing\u2019 techniques to gain access to specific systems, and can trick even security savvy users. There are even phishing scams targeting users with 2FA. Be alert to phishy emails.\nDon\u2019t install things through curl
| sudo bash, especially if the URL is on GitHub, meaning someone else controls it. Don\u2019t do it on your machines, and definitely don\u2019t do it in your CI/CD systems. Seriously.\n\nStaying secure should be important to you personally, but it\u2019s doubly important when you have privileged access to an application. Such access makes you a way to reach many more users, and therefore a more compelling target for bad actors.\nA Culture of Security\nUsing HTTPS, enabling two-factor authentication and fixing known vulnerabilities are significant steps in building security at your core. As you implement them, remember that these are just a few steps in a longer journey.\nThe end goal is to embrace security as an aspect of quality, and accept we all share the responsibility of keeping ourselves \u2013 and our users \u2013 safe.", "year": "2015", "author": "Guy Podjarny", "author_slug": "guypodjarny", "published": "2015-12-11T00:00:00+00:00", "url": "https://24ways.org/2015/upping-your-web-security-game/", "topic": "code"}
{"rowid": 54, "title": "Putting My Patterns through Their Paces", "contents": "Over the last few years, the conversation around responsive design has shifted subtly, focusing not on designing pages, but on patterns: understanding the small, reusable elements that comprise a larger design system. And given that many of those patterns are themselves responsive, learning to manage these small layout systems has become a big part of my work.\nThe thing is, the more pattern-driven work I do, the more I realize my design process has changed in a number of subtle, important ways. I suppose you might even say that pattern-driven design has, in a few ways, redesigned me.\nMeet the Teaser\nHere\u2019s a recent example. A few months ago, some friends and I redesigned The Toast. (It was a really, really fun project, and we learned a lot.) Each page of the site is, as you might guess, stitched together from a host of tiny, reusable patterns. Some of them, like the search form and footer, are fairly unique, and used once per page; others are used more liberally, and built for reuse. The most prevalent example of these more generic patterns is the teaser, which is classed as, uh, .teaser. (Look, I never said I was especially clever.)\nIn its simplest form, a teaser contains a headline, which links to an article:\n\nFairly straightforward, sure. But it\u2019s just the foundation: from there, teasers can have a byline, a description, a thumbnail, and a comment count. In other words, we have a basic building block (.teaser) that contains a few discrete content types \u2013 some required, some not. In fact, very few of those pieces need to be present; to qualify as a teaser, all we really need is a link and a headline. But by adding more elements, we can build slight variations of our teaser, and make it much, much more versatile.\n\n Nearly every element visible on this page is built out of our generic \u201cteaser\u201d pattern.\n \nBut the teaser variation I\u2019d like to call out is the one that appears on The Toast\u2019s homepage, on search results or on section fronts. In the main content area, each teaser in the list features larger images, as well as an interesting visual treatment: the byline and comment count were the most prominent elements within each teaser, appearing above the headline.\n\n The approved visual design of our teaser, as it appears on lists on the homepage and the section fronts.\n \nAnd this is, as it happens, the teaser variation that gave me pause. Back in the old days \u2013 you know, like six months ago \u2013 I probably would\u2019ve marked this module up to match the design. In other words, I would\u2019ve looked at the module\u2019s visual hierarchy (metadata up top, headline and content below) and written the following HTML:\n\n
By Author Name
\n \n
\n
Lorem ipsum dolor sit amet, consectetur\u2026
\n
\nBut then I caught myself, and realized this wasn\u2019t the best approach.\nMoving Beyond Layout\nSince I\u2019ve started working responsively, there\u2019s a question I work into every step of my design process. Whether I\u2019m working in Sketch, CSSing a thing, or researching a project, I try to constantly ask myself:\n\nWhat if someone doesn\u2019t browse the web like I do?\n\n\u2026Okay, that doesn\u2019t seem especially fancy. (And maybe you came here for fancy.) But as straightforward as that question might seem, it\u2019s been invaluable to so many aspects of my practice. If I\u2019m working on a widescreen layout, that question helps me remember the constraints of the small screen; if I\u2019m working on an interface that has some enhancements for touch, it helps me consider other input modes as I work. It\u2019s also helpful as a reminder that many might not see the screen the same way I do, and that accessibility (in all its forms) should be a throughline for our work on the web.\nAnd that last point, thankfully, was what caught me here. While having the byline and comment count at the top was a lovely visual treatment, it made for a terrible content hierarchy. For example, it\u2019d be a little weird if the page was being read aloud in a speaking browser: the name of the author and the number of comments would be read aloud before the title of the article with which they\u2019re associated.\nThat\u2019s why I find it\u2019s helpful to begin designing a pattern\u2019s hierarchy before its layout: to move past the visual presentation in front of me, and focus on the underlying content I\u2019m trying to support. In other words, if someone\u2019s encountering my design without the CSS I\u2019ve written, what should their experience be?\nSo I took a step back, and came up with a different approach:\n\n
\n
\n
\n Lorem ipsum dolor sit amet, consectetur\u2026\n \n
\n
\nMuch, much better. This felt like a better match for the content I was designing: the headline \u2013 easily most important element \u2013 was at the top, followed by the author\u2019s name and an excerpt. And while the comment count is visually the most prominent element in the teaser, I decided it was hierarchically the least critical: that\u2019s why it\u2019s at the very end of the excerpt, the last element within our teaser. And with some light styling, we\u2019ve got a respectable-looking hierarchy in place:\n\nYeah, you\u2019re right \u2013 it\u2019s not our final design. But from this basic-looking foundation, we can layer on a bit more complexity. First, we\u2019ll bolster the markup with an extra element around our title and byline:\n\nWith that in place, we can use flexbox to tweak our layout, like so:\n.teaser-hed {\n display: flex;\n flex-direction: column-reverse;\n}\nflex-direction: column-reverse acts a bit like a change in gravity within our teaser-hed element, vertically swapping its two children.\n\nGetting closer! But as great as flexbox is, it doesn\u2019t do anything for elements outside our container, like our little comment count, which is, as you\u2019ve probably noticed, still stranded at the very bottom of our teaser.\nFlexbox is, as you might already know, wonderful! And while it enjoys incredibly broad support, there are enough implementations of old versions of Flexbox (in addition to plenty of bugs) that I tend to use a feature test to check if the browser\u2019s using a sufficiently modern version of flexbox. Here\u2019s the one we used:\nvar doc = document.body || document.documentElement;\nvar style = doc.style;\n\nif ( style.webkitFlexWrap == '' ||\n style.msFlexWrap == '' ||\n style.flexWrap == '' ) {\n doc.className += \" supports-flex\";\n}\nEagle-eyed readers will note we could have used @supports feature queries to ask browsers if they support certain CSS properties, removing the JavaScript dependency. But since we wanted to serve the layout to IE we opted to write a little question in JavaScript, asking the browser if it supports flex-wrap, a property used elsewhere in the design. If the browser passes the test, then a class of supports-flex gets applied to our html element. And with that class in place, we can safely quarantine our flexbox-enabled layout from less-capable browsers, and finish our teaser\u2019s design:\n.supports-flex .teaser-hed {\n display: flex;\n flex-direction: column-reverse;\n}\n.supports-flex .teaser .comment-count {\n position: absolute;\n right: 0;\n top: 1.1em;\n}\nIf the supports-flex class is present, we can apply our flexbox layout to the title area, sure \u2013 but we can also safely use absolute positioning to pull our comment count out of its default position, and anchor it to the top right of our teaser. In other words, the browsers that don\u2019t meet our threshold for our advanced styles are left with an attractive design that matches our HTML\u2019s content hierarchy; but the ones that pass our test receive the finished, final design.\n\nAnd with that, our teaser\u2019s complete.\nDiving Into Device-Agnostic Design\nThis is, admittedly, a pretty modest application of flexbox. (For some truly next-level work, I\u2019d recommend Heydon Pickering\u2019s \u201cFlexbox Grid Finesse\u201d, or anything Zoe Mickley Gillenwater publishes.) And for such a simple module, you might feel like this is, well, quite a bit of work. And you\u2019d be right! In fact, it\u2019s not one layout, but two: a lightly styled content hierarchy served to everyone, with the finished design served conditionally to the browsers that can successfully implement it. But I\u2019ve found that thinking about my design as existing in broad experience tiers \u2013 in layers \u2013 is one of the best ways of designing for the modern web. And what\u2019s more, it works not just for simple modules like our teaser, but for more complex or interactive patterns as well.\nOpen video\n \n Even a simple search form can be conditionally enhanced, given a little layered thinking.\n \nThis more layered approach to interface design isn\u2019t a new one, mind you: it\u2019s been championed by everyone from Filament Group to the BBC. And with all the challenges we keep uncovering, a more device-agnostic approach is one of the best ways I\u2019ve found to practice responsive design. As Trent Walton once wrote,\n\nLike cars designed to perform in extreme heat or on icy roads, websites should be built to face the reality of the web\u2019s inherent variability.\n\nWe have a weird job, working on the web. We\u2019re designing for the latest mobile devices, sure, but we\u2019re increasingly aware that our definition of \u201csmartphone\u201d is much too narrow. Browsers have started appearing on our wrists and in our cars\u2019 dashboards, but much of the world\u2019s mobile data flows over sub-3G networks. After all, the web\u2019s evolution has never been charted along a straight line: it\u2019s simultaneously getting slower and faster, with devices new and old coming online every day. With all the challenges in front of us, including many we don\u2019t yet know about, a more device-agnostic, more layered design process can better prepare our patterns \u2013 and ourselves \u2013 for the future.\n(It won\u2019t help you get enough to eat at holiday parties, though.)", "year": "2015", "author": "Ethan Marcotte", "author_slug": "ethanmarcotte", "published": "2015-12-10T00:00:00+00:00", "url": "https://24ways.org/2015/putting-my-patterns-through-their-paces/", "topic": "code"}
{"rowid": 61, "title": "Animation in Responsive Design", "contents": "Animation and responsive design can sometimes feel like they\u2019re at odds with each other. Animation often needs space to do its thing, but RWD tells us that the amount of space we\u2019ll have available is going to change a lot. Balancing that can lead to some tricky animation situations. \nEmbracing the squishiness of responsive design doesn\u2019t 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.\nFocused art direction\nSmaller 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\u2019re battling for space. An effect that looked great on big viewports can become muddled and confusing when it\u2019s reframed in a smaller space.\nMaking 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\u2019ll 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\u2019s message down to the essentials. \nFor example, Rally Interactive\u2019s 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\u2019t make much sense. \nOpen video\n\nThe 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\u2019s 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. \nOpen video\n\nSi 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\u2019t contain critical content.\nOpen video\n\nAt first, it looks like Si Digital just turned off the animation of the illustration for smaller viewports. But they\u2019ve actually been a little cleverer than that. They\u2019ve 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.\nOpen video\n\nThe most interesting thing about these two examples is that they\u2019re 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. \nResponsive choreography\nStatic 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\u2019s 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\u2019 choreography to change which animation starts when, or even which animations play at all, keeps your animated content readable on smaller viewports. \nIn 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. \nOpen video\n\nWhat 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\u2019ve put the animated parts in this demo if you want to peek under the hood.) \nOpen video\n\nI 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. \nEven 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\u2019s 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. \nSarah 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\u2019re after, it\u2019s also possible to make all of an SVG\u2019s 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! \nOpen video\n\nBake performance into your design decisions\nIt\u2019s 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. \nThe translate3D \u201chack\u201d, 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.\nPick a technology that matches your needs\nOne 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\u2019re using to get the job done. \nLoading in the full weight of a robust JavaScript animation library is going to be overkill if you\u2019re only animating a few small elements here and there. That extra overhead will have an impact on performance. Performance budgets will not be pleased. \nAlways 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\u2019s 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.\nAnimate the most performant properties\nWhether you\u2019re animating in CSS or JavaScript, you\u2019re 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. \nBrowsers 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\u2019t many animated effects that can\u2019t 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\u2026 to find out how much of an additional impact it might have.\nOffset animation start times\nOffsets (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\u2019s rendering abilities even in the best cases. Adding short delays to offset these animations in time, so they don\u2019t all start at once, can improve rendering performance. \nGo explore the responsive animation possibilities for yourself!\nWith 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\u2019ll pull off your animations with style at any viewport size!", "year": "2015", "author": "Val Head", "author_slug": "valhead", "published": "2015-12-09T00:00:00+00:00", "url": "https://24ways.org/2015/animation-in-responsive-design/", "topic": "design"}
{"rowid": 56, "title": "Helping VIPs Care About Performance", "contents": "Making a site feel super fast is the easy part of performance work. Getting people around you to care about site speed is a much bigger challenge. How do we keep the site fast beyond the initial performance work? Keeping very important people like your upper management or clients invested in performance work is critical to keeping a site fast and empowering other designers and developers to contribute.\nThe work to get others to care is so meaty that I dedicated a whole chapter to the topic in my book Designing for Performance. When I speak at conferences, the majority of questions during Q&A are on this topic. When I speak to developers and designers who care about performance, getting other people at one\u2019s organization or agency to care becomes the most pressing question.\nMy primary response to folks who raise this issue is the question: \u201cWhat metric(s) do your VIPs care about?\u201d This is often met with blank stares and raised eyebrows. But it\u2019s also our biggest clue to what we need to do to help empower others to care about performance and work on it. Every organization and executive is different. This means that three major things vary: the primary metrics VIPs care about; the language they use about measuring success; and how change is enacted. By clueing in to these nuances within your organization, you can get a huge leg up on crafting a successful pitch about performance work.\nLet\u2019s start with the metric that we should measure. Sure, (most) everybody cares about money - but is that really the metric that your VIPs are looking at each day to measure the success or efficacy of your site? More likely, dollars are the end game, but the metrics or key performance indicators (KPIs) people focus on might be:\n\nrate of new accounts created/signups\ncost of acquiring or retaining a customer\nvisitor return rate\nvisitor bounce rate\nfavoriting or another interaction rate\n\nThese are just a few examples, but they illustrate how wide-ranging the options are that people care about. I find that developers and designers haven\u2019t necessarily investigated this when trying to get others to care about performance. We often reach for the obvious \u2013 money! \u2013 but if we don\u2019t use the same kind of language our VIPs are using, we might not get too far. You need to know this before you can make the case for performance work.\nTo find out these metrics or KPIs, start reading through the emails your VIPs are sending within your company. What does it say on company wikis? Are there major dashboards internally that people are looking at where you could find some good metrics? Listen intently in team meetings or thoroughly read annual reports to see what these metrics could be.\nThe second key here is to pick up on language you can effectively copy and paste as you make the case for performance work. You need to be able to reflect back the metrics that people already find important in a way they\u2019ll be able to hear. Once you know your key metrics, it\u2019s time to figure out how to communicate with your VIPs about performance using language that will resonate with them.\nLet\u2019s start with visit traffic as an example metric that a very important person cares about. Start to dig up research that other people and companies have done that correlates performance and your KPI. For example, cite studies:\n\n\u201cWhen the home page of Google Maps was reduced from 100KB to 70\u201380KB, traffic went up 10% in the first week, and an additional 25% in the following three weeks.\u201d (source).\n\nRead through websites like WPOStats, which collects the spectrum of studies on the impact of performance optimization on user experience and business metrics. Tweet and see if others have done similar research that correlates performance and your site\u2019s main KPI.\nOnce you have collected some research that touches on the same kind of language your VIPs use about the success of your site, it\u2019s time to present it. You can start with something simple, like a qualitative description of the work you\u2019re actively doing to improve the site that translates to improved metrics that your VIPs care about. It can be helpful to append a performance budget to any proposal so you can compare the budget to your site\u2019s reality and how it might positively impact those KPIs folks care about.\nWords and graphs are often only half the battle when it comes to getting others to care about performance. Often, videos appeal to folks\u2019 emotions in a way that is missed when glancing through charts and graphs. On A List Apart I recently detailed how to create videos of how fast your site loads. Let\u2019s say that your VIPs care about how your site loads on mobile devices; it\u2019s time to show them how your site loads on mobile networks.\nOpen video\n\nYou can use these videos to make a number of different statements to your VIPs, depending on what they care about:\n\nLook at how slow our site loads versus our competitor!\nLook at how slow our site loads for users in another country!\nLook at how slow our site loads on mobile networks!\n\nAgain, you really need to know which metrics your VIPs care about and tune into the language they\u2019re using. If they don\u2019t care about the overall user experience of your site on mobile devices, then showing them how slow your site loads on 3G isn\u2019t going to work. This will be your sales pitch; you need to practice and iterate on the language and highlights that will land best with your audience. \nTo make your sales pitch as solid as possible, gut-check your ideas on how to present it with other co-workers to get their feedback. Read up on how to construct effective arguments and deliver them; do some research and see what others have done at your company when pitching to VIPs. Are slides effective? Memos or emails? Hallway conversations? Sometimes the best way to change people\u2019s minds is by mentioning it in informal chats over coffee. Emulate the other leaders in your organization who are successful at this work. \nEvery organization and very important person is different. Learn what metrics folks truly care about, study the language that they use, and apply what you\u2019ve learned in a way that\u2019ll land with those individuals. It may take time to craft your pitch for performance work over time, but it\u2019s important work to do. If you\u2019re able to figure out how to mirror back the language and metrics VIPs care about, and connect the dots to performance for them, you will have a huge leg up on keeping your site fast in the long run.", "year": "2015", "author": "Lara Hogan", "author_slug": "larahogan", "published": "2015-12-08T00:00:00+00:00", "url": "https://24ways.org/2015/helping-vips-care-about-performance/", "topic": "business"}
{"rowid": 52, "title": "Git Rebasing: An Elfin Workshop Workflow", "contents": "This year Santa\u2019s helpers have been tasked with making a garland. It\u2019s a pretty simple task: string beads onto yarn in a specific order. When the garland reaches a specific length, add it to the main workshop garland. Each elf has a specific sequence they\u2019re supposed to chain, which is given to them via a work order. (This is starting to sound like one of those horrible calculus problems. I promise it isn\u2019t. It\u2019s worse; it\u2019s about Git.)\nFor the most part, the system works really well. The elves are able to quickly build up a shared chain because each elf specialises on their own bit of garland, and then links the garland together. Because of this they\u2019re able to work independently, but towards the common goal of making a beautiful garland.\nAt first the elves are really careful with each bead they put onto the garland. They check with one another before merging their work, and review each new link carefully. As time crunches on, the elves pour a little more cheer into the eggnog cooler, and the quality of work starts to degrade. Tensions rise as mistakes are made and unkind words are said. The elves quickly realise they\u2019re going to need a system to change the beads out when mistakes are made in the chain.\nThe first common mistake is not looking to see what the latest chain is that\u2019s been added to the main garland. The garland is huge, and it sits on a roll in one of the corners of the workshop. It\u2019s a big workshop, so it is incredibly impractical to walk all the way to the roll to check what the last link is on the chain. The elves, being magical, have set up a monitoring system that allows them to keep a local copy of the main garland at their workstation. It\u2019s an imperfect system though, so the elves have to request a manual refresh to see the latest copy. They can request a new copy by running the command\ngit pull --rebase=preserve\n(They found that if they ran git pull on its own, they ended up with weird loops of extra beads off the main garland, so they\u2019ve opted to use this method.) This keeps the shared garland up to date, which makes things a lot easier. A visualisation of the rebase process is available.\nThe next thing the elves noticed is that if they worked on the main workshop garland, they were always running into problems when they tried to share their work back with the rest of the workshop. It was fine if they were working late at night by themselves, but in the middle of the day, it was horrible. (I\u2019ve been asked not to talk about that time the fight broke out.) Instead of trying to share everything on their local copy of the main garland, the elves have realised it\u2019s a lot easier to work on a new string and then knot this onto the main garland when their pattern repeat is finished. They generate a new string by issuing the following commands:\ngit checkout master\ngit checkout -b 1234_pattern-name\n1234 represents the work order number and pattern-name describes the pattern they\u2019re adding. Each bead is then added to the new link (git add bead.txt) and locked into place (git commit). Each elf repeats this process until the sequence of beads described in the work order has been added to their mini garland.\nTo combine their work with the main garland, the elves need to make a few decisions. If they\u2019re making a single strand, they issue the following commands:\ngit checkout master\ngit merge --ff-only 1234_pattern-name\nTo share their work they publish the new version of the main garland to the workshop spool with the command git push origin master.\nSometimes this fails. Sharing work fails because the workshop spool has gotten new links added since the elf last updated their copy of the main workshop spool. This makes the elves both happy and sad. It makes them happy because it means the other elves have been working too, but it makes them sad because they now need to do a bit of extra work to close their work order. \nTo update the local copy of the workshop spool, the elf first unlinks the chain they just linked by running the command:\ngit reset --merge ORIG_HEAD\nThis works because the garland magic notices when the elves are doing a particularly dangerous thing and places a temporary, invisible bookmark to the last safe bead in the chain before the dangerous thing happened. The garland no longer has the elf\u2019s work, and can be updated safely. The elf runs the command git pull --rebase=preserve and the changes all the other elves have made are applied locally.\nWith these new beads in place, the elf now has to restring their own chain so that it starts at the right place. To do this, the elf turns back to their own chain (git checkout 1234_pattern-name) and runs the command git rebase master. Assuming their bead pattern is completely unique, the process will run and the elf\u2019s beads will be restrung on the tip of the main workshop garland.\nSometimes the magic fails and the elf has to deal with merge conflicts. These are kind of annoying, so the elf uses a special inspector tool to figure things out. The elf opens the inspector by running the command git mergetool to work through places where their beads have been added at the same points as another elf\u2019s beads. Once all the conflicts are resolved, the elf saves their work, and quits the inspector. They might need to do this a few times if there are a lot of new beads, so the elf has learned to follow this update process regularly instead of just waiting until they\u2019re ready to close out their work order.\nOnce their link is up to date, the elf can now reapply their chain as before, publish their work to the main workshop garland, and close their work order:\ngit checkout master\ngit merge --ff-only 1234_pattern-name\ngit push origin master\nGenerally this process works well for the elves. Sometimes, though, when they\u2019re tired or bored or a little drunk on festive cheer, they realise there\u2019s a mistake in their chain of beads. Fortunately they can fix the beads without anyone else knowing. These tools can be applied to the whole workshop chain as well, but it causes problems because the magic assumes that elves are only ever adding to the main chain, not removing or reordering beads on the fly. Depending on where the mistake is, the elf has a few different options.\nLet\u2019s pretend the elf has a sequence of five beads she\u2019s been working on. The work order says the pattern should be red-blue-red-blue-red.\n\nIf the sequence of beads is wrong (for example, blue-blue-red-red-red), the elf can remove the beads from the chain, but keep the beads in her workstation using the command git reset --soft HEAD~5.\n\nIf she\u2019s been using the wrong colours and the wrong pattern (for example, green-green-yellow-yellow-green), she can remove the beads from her chain and discard them from her workstation using the command git reset --hard HEAD~5.\n\nIf one of the beads is missing (for example, red-blue-blue-red), she can restring the beads using the first method, or she can use a bit of magic to add the missing bead into the sequence.\n\nUsing a tool that\u2019s a bit like orthoscopic surgery, she first selects a sequence of beads which contains the problem. A visualisation of this process is available.\nStart the garland surgery process with the command:\ngit rebase --interactive HEAD~4\nA new screen comes up with the following information (the oldest bead is on top):\npick c2e4877 Red bead\npick 9b5555e Blue bead\npick 7afd66b Blue bead\npick e1f2537 Red bead\nThe elf adjusts the list, changing \u201cpick\u201d to \u201cedit\u201d next to the first blue bead:\npick c2e4877 Red bead\nedit 9b5555e Blue bead\npick 7afd66b Blue bead\npick e1f2537 Red bead\nShe then saves her work and quits the editor. The garland magic has placed her back in time at the moment just after she added the first blue bead.\n\nShe needs to manually fix up her garland to add the new red bead. If the beads were files, she might run commands like vim beads.txt and edit the file to make the necessary changes.\nOnce she\u2019s finished her changes, she needs to add her new bead to the garland (git add --all) and lock it into place (git commit). This time she assigns the commit message \u201cRed bead \u2013 added\u201d so she can easily find it.\n\nThe garland magic has replaced the bead, but she still needs to verify the remaining beads on the garland. This is a mostly automatic process which is started by running the command git rebase --continue.\nThe new red bead has been assigned a position formerly held by the blue bead, and so the elf must deal with a merge conflict. She opens up a new program to help resolve the conflict by running git mergetool.\n\nShe knows she wants both of these beads in place, so the elf edits the file to include both the red and blue beads.\n\nWith the conflict resolved, the elf saves her changes and quits the mergetool.\nBack at the command line, the elf checks the status of her work using the command git status.\nrebase in progress; onto 4a9cb9d\nYou are currently rebasing branch '2_RBRBR' on '4a9cb9d'.\n (all conflicts fixed: run \"git rebase --continue\")\n\nChanges to be committed:\n (use \"git reset HEAD ...\" to unstage)\n\n modified: beads.txt\n\nUntracked files:\n (use \"git add ...\" to include in what will be committed)\n\n beads.txt.orig\nShe removes the file added by the mergetool with the command rm beads.txt.orig and commits the edits she just made to the bead file using the commands:\ngit add beads.txt\ngit commit --message \"Blue bead -- resolved conflict\"\n\nWith the conflict resolved, the elf is able to continue with the rebasing process using the command git rebase --continue. There is one final conflict the elf needs to resolve. Once again, she opens up the visualisation tool and takes a look at the two conflicting files.\n\nShe incorporates the changes from the left and right column to ensure her bead sequence is correct.\n\nOnce the merge conflict is resolved, the elf saves the file and quits the mergetool. Once again, she cleans out the backup file added by the mergetool (rm beads.txt.orig) and commits her changes to the garland:\ngit add beads.txt\ngit commit --message \"Red bead -- resolved conflict\"\nand then runs the final verification steps in the rebase process (git rebase --continue).\n\nThe verification process runs through to the end, and the elf checks her work using the command git log --oneline.\n9269914 Red bead -- resolved conflict\n4916353 Blue bead -- resolved conflict\naef0d5c Red bead -- added\n9b5555e Blue bead\nc2e4877 Red bead\nShe knows she needs to read the sequence from bottom to top (the oldest bead is on the bottom). Reviewing the list she sees that the sequence is now correct.\nSometimes, late at night, the elf makes new copies of the workshop garland so she can play around with the bead sequencer just to see what happens. It\u2019s made her more confident at restringing beads when she\u2019s found real mistakes. And she doesn\u2019t mind helping her fellow elves when they run into trouble with their beads. The sugar cookies they leave her as thanks don\u2019t hurt either. If you would also like to play with the bead sequencer, you can get a copy of the branches the elf worked.\n\nOur lessons from the workshop:\n\nBy using rebase to update your branches, you avoid merge commits and keep a clean commit history.\nIf you make a mistake on one of your local branches, you can use reset to take commits off your branch. If you want to save the work, but uncommit it, add the parameter --soft. If you want to completely discard the work, use the parameter, --hard.\nIf you have merged working branch changes to the local copy of your master branch and it is preventing you from pushing your work to a remote repository, remove these changes using the command reset with the parameter --merge ORIG_HEAD before updating your local copy of the remote master branch.\nIf you want to make a change to work that was committed a little while ago, you can use the command rebase with the parameter --interactive. You will need to include how many commits back in time you want to review.", "year": "2015", "author": "Emma Jane Westby", "author_slug": "emmajanewestby", "published": "2015-12-07T00:00:00+00:00", "url": "https://24ways.org/2015/git-rebasing/", "topic": "code"}
{"rowid": 70, "title": "Bringing Your Code to the Streets", "contents": "\u2014 or How to Be a Street VJ\nOur 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\u2019ve 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.\nYou 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\u2019s not enough \u2018outside the browser\u2019 implementations, Node.js servers can even be found in aircraft!\nI previously mentioned VR and with three.js\u2019s extra StereoEffect.js module it\u2019s relatively simple to get browser 3D goodness to be Google Cardboard-ready, and thus set the stage for all things JavaScript and VR. It\u2019s been pretty popular in the art world too, with interactive works such as Seb Lee-Delisle\u2019s 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\u2019s not even the connectivity of the web that\u2019s being showcased; we can even take things offline and use web code for amazing things, such as fighting Ebola.\nOne 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!\nNow it\u2019s our turn\nSo I wanted to create a little project influenced by this theme, and as it\u2019s Christmas, take it to the streets for a little bit of party fun! Something that could take code anywhere. Here\u2019s how I made a portable visual projection pack, a piece of video mixing software and created some web-coded street art.\nStep one: The equipment\nYou will need:\n\nOne laptop: with HDMI output and a modern browser installed, such as Google Chrome.\nOne battery-powered mini projector: I\u2019ve used a Texas Instruments DLP; for its 120 lumens it was the best cost-to-lumens ratio I could find.\nOne 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\u2019ll see in the article, this is optional as it can be emulated within the software.\nA case to carry it all around in.\n\n\nStep two: The software\nThe 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.\nYou 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 \u2013 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\u2019ve put together for this, there\u2019s a showcase on CodePen.\nThe 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\u2019s start with two divs, both absolutely positioned so they\u2019re on top of each other, but at the start the second screen\u2019s opacity is set to zero.\nNow all we need is a slider, which when moved from one side to the other slowly sets the second screen\u2019s opacity to 1, thereby fading it in.\nSee the Pen Mixing Screens (Software Version) by Rumyra (@Rumyra) on CodePen.\nMixing Screens (CodePen)\n\nAs you saw above, I have a MIDI controller and although the software method works great, I\u2019d quite like to make use of this nifty piece of kit. That\u2019s 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\u2019ve 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.\nvar midi, data;\n// start talking to MIDI controller\nif (navigator.requestMIDIAccess) {\n navigator.requestMIDIAccess({\n sysex: false\n }).then(onMIDISuccess, onMIDIFailure);\n} else {\n alert(\u201cNo MIDI support in your browser.\u201d);\n}\n\n// on success\nfunction onMIDISuccess(midiData) {\n // this is all our MIDI data\n midi = midiData;\n\n var allInputs = midi.allInputs.values();\n // loop over all available inputs and listen for any MIDI input\n for (var input = allInputs.next(); input && !input.done; input = allInputs.next()) {\n // when a MIDI value is received call the onMIDIMessage function\n input.value.onmidimessage = onMIDIMessage;\n }\n}\n\nfunction onMIDIMessage(message) {\n // data comes in the form [command/channel, note, velocity]\n data = message.data;\n\n // Opacity change for screen. The cross fader values are [176, 8, {0-127}]\n if ( (data[0] === 176) && (data[1] === 8) ) {\n // this value will change as the fader is moved\n var opacity = data[2]/127;\n screenTwo.style.opacity = opacity;\n }\n}\n\nThe 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\u2019s a very rough-and-ready first version of the software on GitHub.\nPhew, Great! Now we need to get all this to the streets!\nStep three: Portable kit\nDid 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\u2026\n\nI 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\u2019ve 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\u2019t resist hacking my own :)\nStep four: Take to the streets\nFirst, make sure everything is charged \u2013 everything \u2013 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\u2019ll 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.\nI 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.\nMy 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!\n\n\nYou 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.\nMy favourite part? When I was projecting into a water feature in Millennium Square. For those who are familiar, you\u2019ll know it\u2019s 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, \u2018Oh wow! That\u2019s so cool!\u2019\nYes\u2026 yes, kid, it was cool. Making things with code is cool.\nMassive 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.", "year": "2015", "author": "Ruth John", "author_slug": "ruthjohn", "published": "2015-12-06T00:00:00+00:00", "url": "https://24ways.org/2015/bringing-your-code-to-the-streets/", "topic": "code"}
{"rowid": 49, "title": "Universal React", "contents": "One of the libraries to receive a huge amount of focus in 2015 has been ReactJS, a library created by Facebook for building user interfaces and web applications.\nMore generally we\u2019ve seen an even greater rise in the number of applications built primarily on the client side with most of the logic implemented in JavaScript. One of the main issues with building an app in this way is that you immediately forgo any customers who might browse with JavaScript turned off, and you can also miss out on any robots that might visit your site to crawl it (such as Google\u2019s search bots). Additionally, we gain a performance improvement by being able to render from the server rather than having to wait for all the JavaScript to be loaded and executed.\nThe good news is that this problem has been recognised and it is possible to build a fully featured client-side application that can be rendered on the server. The way in which these apps work is as follows:\n\nThe user visits www.yoursite.com and the server executes your JavaScript to generate the HTML it needs to render the page.\nIn the background, the client-side JavaScript is executed and takes over the duty of rendering the page.\nThe next time a user clicks, rather than being sent to the server, the client-side app is in control.\nIf the user doesn\u2019t have JavaScript enabled, each click on a link goes to the server and they get the server-rendered content again.\n\nThis means you can still provide a very quick and snappy experience for JavaScript users without having to abandon your non-JS users. We achieve this by writing JavaScript that can be executed on the server or on the client (you might have heard this referred to as isomorphic) and using a JavaScript framework that\u2019s clever enough handle server- or client-side execution. Currently, ReactJS is leading the way here, although Ember and Angular are both working on solutions to this problem.\nIt\u2019s worth noting that this tutorial assumes some familiarity with React in general, its syntax and concepts. If you\u2019d like a refresher, the ReactJS docs are a good place to start.\n\u00a0Getting started\nWe\u2019re going to create a tiny ReactJS application that will work on the server and the client. First we\u2019ll need to create a new project and install some dependencies. In a new, blank directory, run:\nnpm init -y\nnpm install --save ejs express react react-router react-dom\nThat will create a new project and install our dependencies:\n\nejs is a templating engine that we\u2019ll use to render our HTML on the server.\nexpress is a small web framework we\u2019ll run our server on.\nreact-router is a popular routing solution for React so our app can fully support and respect URLs.\nreact-dom is a small React library used for rendering React components.\n\nWe\u2019re also going to write all our code in ECMAScript 6, and therefore need to install BabelJS and configure that too.\nnpm install --save-dev babel-cli babel-preset-es2015 babel-preset-react\nThen, create a .babelrc file that contains the following:\n{\n \"presets\": [\"es2015\", \"react\"]\n}\nWhat we\u2019ve done here is install Babel\u2019s command line interface (CLI) tool and configured it to transform our code from ECMAScript 6 (or ES2015) to ECMAScript 5, which is more widely supported. We\u2019ll need the React transforms when we start writing JSX when working with React.\nCreating a server\nFor now, our ExpressJS server is pretty straightforward. All we\u2019ll do is render a view that says \u2018Hello World\u2019. Here\u2019s our server code:\nimport express from 'express';\nimport http from 'http';\n\nconst app = express();\n\napp.use(express.static('public'));\n\napp.set('view engine', 'ejs');\n\napp.get('*', (req, res) => {\n res.render('index');\n});\n\nconst server = http.createServer(app);\n\nserver.listen(3003);\nserver.on('listening', () => {\n console.log('Listening on 3003');\n});\nHere we\u2019re using ES6 modules, which I wrote about on 24 ways last year, if you\u2019d like a reminder. We tell the app to render the index view on any GET request (that\u2019s what app.get('*') means, the wildcard matches any route).\nWe now need to create the index view file, which Express expects to be defined in views/index.ejs:\n\n\n \n My App \n \n\n \n Hello World\n \n\nFinally, we\u2019re ready to run the server. Because we installed babel-cli earlier we have access to the babel-node executable, which will transform all your code before running it through node. Run this command:\n./node_modules/.bin/babel-node server.js\nAnd you should now be able to visit http://localhost:3003 and see \u2018Hello World\u2019 right there:\n\nBuilding the React app\nNow we\u2019ll build the React application entirely on the server, before adding the client-side JavaScript right at the end. Our app will have two routes, / and /about which will both show a small amount of content. This will demonstrate how to use React Router on the server side to make sure our React app plays nicely with URLs.\nFirstly, let\u2019s update views/index.ejs. Our server will figure out what HTML it needs to render, and pass that into the view. We can pass a value into our view when we render it, and then use EJS syntax to tell it to output that data. Update the template file so the body looks like so:\n\n <%- markup %>\n\nNext, we\u2019ll define the routes we want our app to have using React Router. For now we\u2019ll just define the index route, and not worry about the /about route quite yet. We could define our routes in JSX, but I think for server-side rendering it\u2019s clearer to define them as an object. Here\u2019s what we\u2019re starting with:\nconst routes = {\n path: '',\n component: AppComponent,\n childRoutes: [\n {\n path: '/',\n component: IndexComponent\n }\n ]\n}\nThese are just placed at the top of server.js, after the import statements. Later we\u2019ll move these into a separate file, but for now they are fine where they are.\nNotice how I define first that the AppComponent should be used at the '' path, which effectively means it matches every single route and becomes a container for all our other components. Then I give it a child route of /, which will match the IndexComponent. Before we hook these routes up with our server, let\u2019s quickly define components/app.js and components/index.js. app.js looks like so:\nimport React from 'react';\n\nexport default class AppComponent extends React.Component {\n render() {\n return (\n \n
Welcome to my App \n { this.props.children }\n \n );\n }\n}\nWhen a React Router route has child components, they are given to us in the props under the children key, so we need to include them in the code we want to render for this component. The index.js component is pretty bland:\nimport React from 'react';\n\nexport default class IndexComponent extends React.Component {\n render() {\n return (\n \n
This is the index page
\n
\n );\n }\n}\nServer-side routing with React Router\nHead back into server.js, and firstly we\u2019ll need to add some new imports:\nimport React from 'react';\nimport { renderToString } from 'react-dom/server';\nimport { match, RoutingContext } from 'react-router';\n\nimport AppComponent from './components/app';\nimport IndexComponent from './components/index';\nThe ReactDOM package provides react-dom/server which includes a renderToString method that takes a React component and produces the HTML string output of the component. It\u2019s this method that we\u2019ll use to render the HTML from the server, generated by React. From the React Router package we use match, a function used to find a matching route for a URL; and RoutingContext, a React component provided by React Router that we\u2019ll need to render. This wraps up our components and provides some functionality that ties React Router together with our app. Generally you don\u2019t need to concern yourself about how this component works, so don\u2019t worry too much.\nNow for the good bit: we can update our app.get('*') route with the code that matches the URL against the React routes:\napp.get('*', (req, res) => {\n // routes is our object of React routes defined above\n match({ routes, location: req.url }, (err, redirectLocation, props) => {\n if (err) {\n // something went badly wrong, so 500 with a message\n res.status(500).send(err.message);\n } else if (redirectLocation) {\n // we matched a ReactRouter redirect, so redirect from the server\n res.redirect(302, redirectLocation.pathname + redirectLocation.search);\n } else if (props) {\n // if we got props, that means we found a valid component to render\n // for the given route\n const markup = renderToString( );\n\n // render `index.ejs`, but pass in the markup we want it to display\n res.render('index', { markup })\n\n } else {\n // no route match, so 404. In a real app you might render a custom\n // 404 view here\n res.sendStatus(404);\n }\n });\n});\nWe call match, giving it the routes object we defined earlier and req.url, which contains the URL of the request. It calls a callback function we give it, with err, redirectLocation and props as the arguments. The first two conditionals in the callback function just deal with an error occuring or a redirect (React Router has built in redirect support). The most interesting bit is the third conditional, else if (props). If we got given props and we\u2019ve made it this far it means we found a matching component to render and we can use this code to render it:\n...\n} else if (props) {\n // if we got props, that means we found a valid component to render\n // for the given route\n const markup = renderToString( );\n\n // render `index.ejs`, but pass in the markup we want it to display\n res.render('index', { markup })\n} else {\n ...\n}\nThe renderToString method from ReactDOM takes that RoutingContext component we mentioned earlier and renders it with the properties required. Again, you need not concern yourself with what this specific component does or what the props are. Most of this is data that React Router provides for us on top of our components.\nNote the {...props}, which is a neat bit of JSX syntax that spreads out our object into key value properties. To see this better, note the two pieces of JSX code below, both of which are equivalent:\n \n\n// OR:\n\nconst props = { a: \"foo\", b: \"bar\" };\n \nRunning the server again\nI know that felt like a lot of work, but the good news is that once you\u2019ve set this up you are free to focus on building your React components, safe in the knowledge that your server-side rendering is working. To check, restart the server and head to http://localhost:3003 once more. You should see it all working!\n\nRefactoring and one more route\nBefore we move on to getting this code running on the client, let\u2019s add one more route and do some tidying up. First, move our routes object out into routes.js:\nimport AppComponent from './components/app';\nimport IndexComponent from './components/index';\n\nconst routes = {\n path: '',\n component: AppComponent,\n childRoutes: [\n {\n path: '/',\n component: IndexComponent\n }\n ]\n}\n\nexport { routes };\nAnd then update server.js. You can remove the two component imports and replace them with:\nimport { routes } from './routes';\nFinally, let\u2019s add one more route for ./about and links between them. Create components/about.js:\nimport React from 'react';\n\nexport default class AboutComponent extends React.Component {\n render() {\n return (\n \n
A little bit about me.
\n
\n );\n }\n}\nAnd then you can add it to routes.js too:\nimport AppComponent from './components/app';\nimport IndexComponent from './components/index';\nimport AboutComponent from './components/about';\n\nconst routes = {\n path: '',\n component: AppComponent,\n childRoutes: [\n {\n path: '/',\n component: IndexComponent\n },\n {\n path: '/about',\n component: AboutComponent\n }\n ]\n}\n\nexport { routes };\nIf you now restart the server and head to http://localhost:3003/about` you\u2019ll see the about page!\n\nFor the finishing touch we\u2019ll use the React Router link component to add some links between the pages. Edit components/app.js to look like so:\nimport React from 'react';\nimport { Link } from 'react-router';\n\nexport default class AppComponent extends React.Component {\n render() {\n return (\n \n
Welcome to my App \n
\n { this.props.children }\n
\n );\n }\n}\nYou can now click between the pages to navigate. However, everytime we do so the requests hit the server. Now we\u2019re going to make our final change, such that after the app has been rendered on the server once, it gets rendered and managed in the client, providing that snappy client-side app experience.\nClient-side rendering\nFirst, we\u2019re going to make a small change to views/index.ejs. React doesn\u2019t like rendering directly into the body and will give a warning when you do so. To prevent this we\u2019ll wrap our app in a div:\n\n <%- markup %>
\n \n\nI\u2019ve also added in a script tag to build.js, which is the file we\u2019ll generate containing all our client-side code.\nNext, create client-render.js. This is going to be the only bit of JavaScript that\u2019s exclusive to the client side. In it we need to pull in our routes and render them to the DOM.\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport { Router } from 'react-router';\n\nimport { routes } from './routes';\n\nimport createBrowserHistory from 'history/lib/createBrowserHistory';\n\nReactDOM.render(\n ,\n document.getElementById('app')\n)\nThe first thing you might notice is the mention of createBrowserHistory. React Router is built on top of the history module, a module that listens to the browser\u2019s address bar and parses the new location. It has many modes of operation: it can keep track using a hashbang, such as http://localhost/#!/about (this is the default), or you can tell it to use the HTML5 history API by calling createBrowserHistory, which is what we\u2019ve done. This will keep the URLs nice and neat and make sure the client and the server are using the same URL structure. You can read more about React Router and histories in the React Router documentation.\nFinally we use ReactDOM.render and give it the Router component, telling it about all our routes, and also tell ReactDOM where to render, the #app element.\nGenerating build.js\nWe\u2019re actually almost there! The final thing we need to do is generate our client side bundle. For this we\u2019re going to use webpack, a module bundler that can take our application, follow all the imports and generate one large bundle from them. We\u2019ll install it and babel-loader, a webpack plugin for transforming code through Babel.\nnpm install --save-dev webpack babel-loader\nTo run webpack we just need to create a configuration file, called webpack.config.js. Create the file in the root of our application and add the following code:\nvar path = require('path');\nmodule.exports = {\n entry: path.join(process.cwd(), 'client-render.js'),\n output: {\n path: './public/',\n filename: 'build.js'\n },\n module: {\n loaders: [\n {\n test: /.js$/,\n loader: 'babel'\n }\n ]\n }\n}\nNote first that this file can\u2019t be written in ES6 as it doesn\u2019t get transformed. The first thing we do is tell webpack the main entry point for our application, which is client-render.js. We use process.cwd() because webpack expects an exact location \u2013 if we just gave it the string \u2018client-render.js\u2019, webpack wouldn\u2019t be able to find it.\nNext, we tell webpack where to output our file, and here I\u2019m telling it to place the file in public/build.js. Finally we tell webpack that every time it hits a file that ends in .js, it should use the babel-loader plugin to transform the code first.\nNow we\u2019re ready to generate the bundle!\n./node_modules/.bin/webpack\nThis will take a fair few seconds to run (on my machine it\u2019s about seven or eight), but once it has it will have created public/build.js, a client-side bundle of our application. If you restart your server once more you\u2019ll see that we can now navigate around our application without hitting the server, because React on the client takes over. Perfect!\nThe first bundle that webpack generates is pretty slow, but if you run webpack -w it will go into watch mode, where it watches files for changes and regenerates the bundle. The key thing is that it only regenerates the small pieces of the bundle it needs, so while the first bundle is very slow, the rest are lightning fast. I recommend leaving webpack constantly running in watch mode when you\u2019re developing.\nConclusions\nFirst, if you\u2019d like to look through this code yourself you can find it all on GitHub. Feel free to raise an issue there or tweet me if you have any problems or would like to ask further questions.\nNext, I want to stress that you shouldn\u2019t use this as an excuse to build all your apps in this way. Some of you might be wondering whether a static site like the one we built today is worth its complexity, and you\u2019d be right. I used it as it\u2019s an easy example to work with but in the future you should carefully consider your reasons for wanting to build a universal React application and make sure it\u2019s a suitable infrastructure for you.\nWith that, all that\u2019s left for me to do is wish you a very merry Christmas and best of luck with your React applications!", "year": "2015", "author": "Jack Franklin", "author_slug": "jackfranklin", "published": "2015-12-05T00:00:00+00:00", "url": "https://24ways.org/2015/universal-react/", "topic": "code"}
{"rowid": 53, "title": "Get Expressive with Your Typography", "contents": "In 1955 Beatrice Warde, an American communicator on typography, published a series of essays entitled The Crystal Goblet in which she wrote, \u201cPeople who love ideas must have a love of words. They will take a vivid interest in the clothes that words wear.\u201d 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.\nBeatrice Warde. \u00a91970 Monotype Imaging Inc.\nChoosing the same typeface as everyone else, especially if you\u2019re 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.\nBut there\u2019s more to your choice of typeface than simply making an impression. In 2012 Jon Tan wrote on 24 ways about a scientific study called \u201cThe Aesthetics of Reading\u201d which concluded that \u201cgood quality typography is responsible for greater engagement during reading and thus induces a good mood.\u201d\nFurthermore, at this year\u2019s 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. \nThe 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\u2019s a real superpower!\nThe 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.\nDisplay text and headings set the scene and draw people in. Text set large creates an image that visitors see before they read, and that\u2019s 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?\nTypography 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?\nMaybe you want them to feel inspired like this stop smoking campaign:\nhelsenorge.no\nPerhaps they should be moved and intrigued, as with Makeshift magazine:\nmkshft.org\nOr calmly reassured:\nwww.cleopatra-marina.gr\nFonts also tap into the complex library of associations that we\u2019ve 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.\nRetiro is obviously Spanish:\nRetiro by Typofonderie\nBodoni and Eurostile used in this menu couldn\u2019t be much more Italian:\nBodoni and Eurostile, both designed in Italy\nTo me, Clarendon gives a sense of the 1960s and 1970s. I\u2019m not sure if that\u2019s what Costa was going for, but that\u2019s what it means to me:\nCosta coffee flier\nAnd Knockout and Gotham really couldn\u2019t be much more American:\nKnockout and Gotham by Hoefler & Co\nWhen 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.\nThe second kind of typeface is one that does most of the work for you. Like finely tailored clothing, it\u2019s the detail in the design that adds interest.\nSetting headings in Bree rather than Helvetica makes a big difference to the tone of the article\nSuch 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.\nPush the boat out\nRemember, 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\u2019t be too reverential, dogmatic \u2013 or ordinary. Be brave and push a few boundaries.\nAdapted from Web Typography a book in progress by Richard Rutter.", "year": "2015", "author": "Richard Rutter", "author_slug": "richardrutter", "published": "2015-12-04T00:00:00+00:00", "url": "https://24ways.org/2015/get-expressive-with-your-typography/", "topic": "design"}
{"rowid": 69, "title": "How to Do a UX Review", "contents": "A UX review is where an expert goes through a website looking for usability and experience problems and makes recommendations on how to fix them. \nI\u2019ve completed a number of UX reviews over my twelve years working as a user experience consultant and I thought I\u2019d share my approach. \nI\u2019ll be talking about reviewing websites here; you can adapt the approach for web apps, or mobile or desktop apps. \nWhy conduct a review\nTypically, a client asks for a review to be undertaken by a trusted and, ideally, detached third party who either works for an agency or is a freelancer. Often they may ask a new member of the UX team to complete one, or even set it as a task for a job interview. This indicates the client is looking for an objective view, seen from the outside as a user would see the website. \nI always suggest conducting some user research rather than a review. Users know their goals and watching them make (what you might think of as) mistakes on the website is invaluable. Conducting research with six users can give you six hours\u2019 worth of review material from six viewpoints. In short, user research can identify more problems and show how common those problems might be. \nThere are three reasons, though, why a review might better suit client needs than user research: \n\nQuick results: user research and analysis takes at least three weeks.\nLimited budget: the \u00a36\u201310,000 cost to run user research is about twice the cost of a UX review. \nUsers are hard to reach: in the business-to-business world, reaching users is difficult, especially if your users hold senior positions in their organisations. Working with consumers is much easier as there are often more of them. \n\nThere is some debate about the benefits of user research over UX review. In my experience you learn far more from research, but opinions differ. \nBe objective\nThe number one mistake many UX reviewers make is reporting back the issues they identify as their opinion. This can cause credibility problems because you have to keep justifying why your opinion is correct. \nI\u2019ve had the most success when giving bad news in a UX review and then finally getting things fixed when I have been as objective as possible, offering evidence for why something may be a problem. \nTo be objective we need two sources of data: numbers from analytics to appeal to reason; and stories from users in the form of personas to speak to emotions. Highlighting issues with dispassionate numerical data helps show the extent of the problem. Making the problems more human using personas can make the problem feel more real. \nNumbers from analytics\nThe majority of clients I work with use Google Analytics, but if you use a different analytics package the same concepts apply. I use analytics to find two sets of things.\n1. Landing pages and search terms\nLanding pages are the pages users see first when they visit a website \u2013 more often than not via a Google search. Landing pages reveal user goals. If a user landed on a page called \u2018Yellow shoes\u2019 their goal may well be to find out about or buy some yellow shoes. \nIt would be great to see all the search terms bringing people to the website but in 2011 Google stopped providing search term data to (rightly!) protect users\u2019 privacy. You can get some search term data from Google Webmaster tools, but we must rely on landing pages as a clue to our users\u2019 goals. \nThe thing to look for is high-traffic landing pages with a high bounce rate. Bounce rate is the percentage of visitors to a website who navigate away from the site after viewing only one page. A high bounce rate (over 50%) isn\u2019t good; above 70% is bad.\nTo get a list of high-traffic landing pages with a high bounce rate install this bespoke report.\nGoogle Analytics showing landing pages ordered by popularity and the bounce rate for each.\nThis is the list of pages with high demand and that have real problems as the bounce rate is high. This is the main focus of the UX review. \n2. User flows\nWe have the beginnings of the user journey: search terms and initial landing pages. Now we can tap into the really useful bit of Google Analytics. Called behaviour flows, they show the most common order of pages visited. \nBehaviour flows from Google Analytics, showing the routes users took through the website.\nHere we can see the second and third (and so on) pages users visited. Importantly, we can also see the drop-outs at each step. \nIf your client has it set up, you can also set goal pages (for example, a post-checkout contact us and thank you page). You can then see a similar view that tracks back from the goal pages. If your client doesn\u2019t have this, suggest they set up goal tracking. It\u2019s easy to do. \nWe now have the remainder of the user journey. \nA user journey\nExpect the work in analytics to take up to a day. \nWe may well identify more than one user journey, starting from different landing pages and going to different second- and third-level pages. That\u2019s a good thing and shows we have different user types. Talking of user types, we need to define who our users are. \nPersonas\nWe have some user journeys and now we need to understand more about our users\u2019 motivations and goals. \nI have a love-hate relationship with personas, but used properly these portraits of users can help bring a human touch to our UX review. \nI suggest using a very cut-down view of a persona. My old friends Steve Cable and Richard Caddick at cxpartners have a great free template for personas from their book Communicating the User Experience.\nThe first thing to do is find a picture that represents that persona. Don\u2019t use crappy stock photography \u2013 it\u2019s sometimes hard to relate to perfect-looking people) \u2013 use authentic-looking people. Here\u2019s a good collection of persona photos. \nAn example persona.\nThe personas have three basic attributes:\n\nGoals: we can complete these drawing on the analytics data we have (see example).\nMusts: things we have to do to meet the persona\u2019s needs.\nMust nots: a list of things we really shouldn\u2019t do. \n\nCompleting points 2 and 3 can often be done during the writing of the report. \nLet\u2019s take an example. We know that the search term \u2018yellow shoes\u2019 takes the user to the landing page for yellow shoes. We also know this page has a high bounce rate, meaning it doesn\u2019t provide a good experience. \nWith our expert hat on we can review the page. We will find two types of problem: \n\nUsability issues: ineffective button placement or incorrect wording, links not looking like links, and so on. \nExperience issues: for example, if a product is out of stock we have to contact the business to ask them to restock. \n\nThat link is very small and hard to see.\nWe could identify that the contact button isn\u2019t easy to find (a usability issue) but that\u2019s not the real problem here. That the user has to ask the business to restock the item is a bad user experience. We add this to our personas\u2019 must nots. The big experience problems with the site form the musts and must nots for our personas. \nWe now have a story around our user journey that highlights what is going wrong. \nIf we\u2019ve identified a number of user journeys, multiple landing pages and differing second and third pages visited, we can create more personas to match. A good rule of thumb is no more than three personas. Any more and they lose impact, watering down your results. \nExpect persona creation to take up to a day to complete. \nLet\u2019s start the review\nWe take the user journeys and we follow them step by step, working through the website looking for the reasons why users drop out at each step. Using Keynote or PowerPoint, I structure the final report around the user journey with separate sections for each step.\nFor each step we\u2019ll find both usability and experience problems. Split the results into those two groups. \nUsability problems are fairly easy to fix as they\u2019re often quick design changes. As you go along, note the usability problems in one place: we\u2019ll call this \u2018quick wins\u2019. Simple quick fixes are a reassuring thing for a client to see and mean they can get started on stuff right away. You can mark the severity of usability issues. Use a scale from 1 to 3 (if you use 1 to 5 everything ends up being a 3!) where 1 is minor and 3 is serious. \nReview the website on the device you\u2019d expect your persona to use. Are they using the site on a smartphone? Review it on a smartphone. \nI allow one page or slide per problem, which allows me to explain what is going wrong. For a usability problem I\u2019ll often make a quick wireframe or sketch to explain how to address it. \nA UX review slide displaying all the elements to be addressed. These slides may be viewed from across the room on a screen so zoom into areas of discussion.\n(Quick tip: if you use Google Chrome, try Awesome Screenshot to capture screens.)\nWhen it comes to the more severe experience problems \u2013 things like an online shop not offering next day delivery, or a business that needs to promise to get back to new customers within a few hours \u2013 these will take more than a tweak to the UI to fix. \nCall these something different. I use the terms like business challenges and customer experience issues as they show that it will take changes to the organisation and its processes to address them. It\u2019s often beyond the remit of a humble UX consultant to recommend how to fix organisational issues, so don\u2019t try. \nAgain, create a page within your document to collect all of the business challenges together. \nExpect the review to take between one and three days to complete. \nThe final report should follow this structure:\n\nThe approach\nOverview of usability quick wins\nOverview of experience issues\nOverview of Google Analytics findings\nThe user journeys \nThe personas\nDetailed page-by-page review (broken down by steps on the user journey)\n\nThere are two academic theories to help with the review. \nHeuristic evaluation is a set of criteria to organise the issues you find. They\u2019re great for categorising the usability issues you identify but in practice they can be quite cumbersome to apply. \nI prefer the more scientific and much simpler cognitive walkthrough that is focused on goals and actions.\nA workshop to go through the findings\nThe most important part of the UX review process is to talk through the issues with your client and their team. \nA document can only communicate a certain amount. Conversations about the findings will help the team understand the severity of the issues you\u2019ve uncovered and give them a chance to discuss what to do about them. \nExpect the workshop to last around three hours.\nWhen presenting the report, explain the method you used to conduct the review, the data sources, personas and the reasoning behind the issues you found. Start by going through the usability issues. Often these won\u2019t be contentious and you can build trust and improve your credibility by making simple, easy to implement changes. \nThe most valuable part of the workshop is conversation around each issue, especially the experience problems. The workshop should include time to talk through each experience issue and how the team will address it. \nI collect actions on index cards throughout the workshop and make a note of who will take what action with each problem. \nIndex cards showing the problem and who is responsible.\nWhen talking through the issues, the person who designed the site is probably in the room \u2013 they may well feel threatened. So be nice.\nWhen I talk through the report I try to have strong ideas, weakly held.\nAt the end of the workshop you\u2019ll have talked through each of the issues and identified who is responsible for addressing them. To close the workshop I hand out the cards to the relevant people, giving them a physical reminder of the next steps they have to take. \nThat\u2019s my process for conducting a review. I\u2019d love to hear any tips you have in the comments.", "year": "2015", "author": "Joe Leech", "author_slug": "joeleech", "published": "2015-12-03T00:00:00+00:00", "url": "https://24ways.org/2015/how-to-do-a-ux-review/", "topic": "ux"}
{"rowid": 62, "title": "Being Customer Supportive", "contents": "Every day in customer support is an inbox, a Twitter feed, or a software forum full of new questions. Each is brimming with your customers looking for advice, reassurance, or fixes for their software problems. Each one is an opportunity to take a break from wrestling with your own troublesome tasks and assist someone else in solving theirs.\nSometimes the questions are straightforward and can be answered in a few minutes with a short greeting, a link to a help page, or a prewritten bit of text you use regularly: how to print a receipt, reset a password, or even, sadly, close your account.\nMore often, a support email requires you to spend some time unpacking the question, asking for more information, and writing a detailed personal response, tailored to help that particular user on this particular day.\nHere I offer a few of my own guidelines on how to make today\u2019s email the best support experience for both me and my customer. And even if you don\u2019t consider what you do to be customer support, you might still find the suggestions useful for the next time you need to communicate with a client, to solve a software problem with teammates, or even reach out and ask for help yourself.\n(All the examples appearing in this article are fictional. Any resemblance to quotes from real, software-using persons is entirely coincidental. Except for the bit about Star Wars. That happened.)\nWho\u2019s TAHT girl\nI\u2019ll be honest: I briefly tried making these recommendations into a clever mnemonic like FAST (facial drooping, arm weakness, speech difficulties, time) or PAD (pressure, antiseptic, dressing). But instead, you get TAHT: tone, ask, help, thank. Ah, well.\nAs I work through each message in my support queue, I\n\nlisten to the tone of the email\nask clarifying questions\nbring in extra help as needed\nand thank the customer when the problem is solved.\n\nLet\u2019s open an email and get started!\nLeave your message at the sound of the tone\nWith our enthusiasm for emoji, it can be very hard to infer someone\u2019s tone from plain text. How much time have you spent pondering why your friend responded with \u201cThanks.\u201d instead of \u201cThanks!\u201d? I mean, why didn\u2019t she :grin: or :wink: too?\nOur support customers, however, are often direct about how they\u2019re feeling:\n\nI\u2019m working against a deadline. Need this fixed ASAP!!!!\nThis hasn\u2019t worked in a week and I am getting really frustrated.\nI\u2019ve done this ten times before and it\u2019s always worked. I must be missing something simple.\n\nThey want us to understand the urgency of this from their point of view, just as much as we want to help them in a timely manner. How this information is conveyed gives us an instant sense of whether they are frustrated, angry, or confused\u2014and, just as importantly, how frustrated-angry-confused they are. \nListen to this tone before you start writing your reply. Here are two ways I might open an email:\n\n\u201cI\u2019m sorry that you ran into trouble with this.\u201d\n\u201cSorry you ran into trouble with this!\u201d\n\nThe content is largely the same, but the tone is markedly different. The first version is a serious, staid reaction to the problem the customer is having; the second version is more relaxed, but no less sincere.\nMatching the tone to the sender\u2019s is an important first step. Overusing exclamation points or dropping in too-casual language may further upset someone who is already having a crummy time with your product. But to a cheerful user, a formal reply or an impersonal form response can be off-putting, and damage a good relationship.\nWhen in doubt, I err on the side of being too formal, rather than sending a reply that may be read as flip or insincere. But whichever you choose, matching your correspondent\u2019s tone will make for a more comfortable conversation.\nCatch the ball and throw it back\nOnce you\u2019ve got that tone on lock, it\u2019s time to tackle the question at hand. Let\u2019s see what our customer needs help with today:\n\nI tried everything in the troubleshooting page but I can\u2019t get it to work again. I am on a Mac. Please help.\n\nHmm, not much information here. Now, if I got this short email after helping five other people with the same problem on Mac OS X, I would be sorely tempted to send this customer that common solution in my first reply. I\u2019ve found it\u2019s important to resist the urge to assume this sixth person needs the same answer as the other five, though: there isn\u2019t enough to connect this email to the ones that came before hers. \nInstead, ask a few questions to start. Invest some time to see if there are other symptoms in common, like so:\n\nI\u2019m sorry that you ran into trouble with this! I\u2019ll need a little more information to see what\u2019s happening here.\n[questions]\nThank you for your help.\n\nThose questions are customized for the customer\u2019s issue as much as possible, and can be fairly wide-ranging. They may include asking for log files, getting some screenshots, or simply checking the browser and operating system version she\u2019s using. I\u2019ll ask anything that might make a connection to the previous cases I\u2019ve answered\u2014or, just as importantly, confirm that there isn\u2019t a connection. What\u2019s more, a few well-placed questions may save us both from pursuing the wrong path and building additional frustration. \n(A note on that closing: \u201cThank you for your help\u201d\u2013I often end an email this way when I\u2019ve asked for a significant amount of follow up information. After all, I\u2019m imposing on my customer\u2019s time to run any number of tests. It\u2019s a necessary step, but I feel that thanking them is a nice acknowledgment we\u2019re in this together.)\nHaving said that, though, let\u2019s bring tone back into the mix:\n\nI tried everything in the troubleshooting but I can\u2019t get it to work again. I am on a Mac. I\u2019m working against a deadline. Need this fixed ASAP!!!!\n\nThis customer wants answers now. I\u2019ll still ask for more details, but would consider including the solution to the previous problem in my initial reply as well. (But only if doing so can\u2019t make the situation worse!)\n\nI\u2019m sorry that you ran into trouble with this! I\u2019ll need a little more information to see what\u2019s happening here.\n[questions]\nIf you\u2019d like to try something in the meantime, delete the file named xyz.txt. (If this isn\u2019t the cause of the problem, deleting the file won\u2019t hurt anything.) Here\u2019s how to find that file on your computer:\n[steps]\nLet me know how it goes!\n\nIn the best case, the suggestion works and the customer is on her way. If it doesn\u2019t solve the problem, you will get more information in answer to your questions and can explore other options. And you\u2019ve given the customer an opportunity to be involved in fixing the issue, and some new tools which might come in handy again in the future.\nBring in help\nThe support software I use counts how many emails the customer and I have exchanged, and reports it in a summary line in my inbox. It\u2019s an easy, passive reminder of how long the customer and I have been working together on a problem, especially first thing in the morning when I\u2019m reacquainting myself with my open support cases.\nThree is the smallest number I\u2019ll see there: the customer sends the initial question (1 email); I reply with an answer (2 emails); the customer confirms the problem is solved (3 emails). But the most complicated, stickiest tickets climb into double-digit replies, and anything that stretches beyond a dozen is worthy of a cheer in Slack when we finally get to the root of the problem and get it fixed.\nWhile an extra round of questions and answers will nudge that number higher, it gives me the chance to feel out the technical comfort level of the person I\u2019m helping. If I ask the customer to send some screenshots or log files and he isn\u2019t sure how to do that, I will use that information to adjust my instructions on next steps. I may still ask him to try running a traceroute on his computer, but I\u2019ll break down the steps into a concise, numbered list, and attach screenshots of each step to illustrate it.\nIf the issue at hand is getting complicated, take note if the customer starts to feel out of their depth technically\u2014either because they tell you so directly or because you sense a shift in tone. If that happens, propose bringing some outside help into the conversation:\n\nDo you have a network firewall or do you use any antivirus software? One of those might be blocking a connection that the software needs to work properly; here\u2019s a list of the required connections [link]. If you have an IT department in-house, they should be able to help confirm that none of those are being blocked.\n\nor:\n\nThis error message means you don\u2019t have permission to install the software on your own computer. Is there a systems administrator in the office that may be able to help with this? \n\nFor email-based support cases, I\u2019ll even offer to add someone from their IT department to the thread, so we can discuss the problem together rather than have the customer relay questions and answers back and forth.\nSimilarly, there are occasionally times when my way of describing things doesn\u2019t fit how the customer understands them. Rather than bang our heads against our keyboards, I will ask one of my support colleagues to join the conversation from our side, and see if he can explain things more clearly than I\u2019ve been able to do.\nWe appreciate your business. Please call again\nAnd then, o frabjous day, you get your reward: the reply which says the problem has been solved. \n\nThat worked!! Thank you so much for saving my day!\nI wish I could send you some cookies!\nIf you were here, I would give you my tickets to Star Wars.\n[Reply is an animated gif.]\n\nSometimes the reply is a bit more understated:\n\nThat fixed it. Thanks.\n\nWhether the customer is elated, satisfied, or frankly happy to be done with emailing support, I like to close longer email threads or short, complicated issues with a final thanks and reminder that we\u2019re here to help: \n\nThank you for the update; I\u2019m glad to hear that solved the problem for you! I hope everything goes smoothly for you now, but feel free to email us again if you run into any other questions or problems. Best,\n\nThen mark that support case closed, and move on to the next question. Because even with the most thoughtfully designed software product, there will always be customers with questions for your capable support team to answer.\nTone, ask, help, thank\nSo there you have it: TAHT. Pay attention to tone; ask questions; bring in help; thank your customer.\n(Lack of) catchy mnemonics aside, good customer support is about listening, paying attention, and taking care in your replies. I think it can be summed up beautifully by this quote from Pamela Marie (as tweeted by Chris Coyier):\n\nGolden rule asking a question: imagine trying to answer it \nGolden rule in answering: imagine getting your answer \n\nYou and your teammates are applying a variation of this golden rule in every email you write. You\u2019re the software ambassadors to your customers and clients. You get the brunt of the problems and complaints, but you also get to help fix them. You write the apologies, but you also have the chance to make each person\u2019s experience with your company or product a little bit better for next time.\nI hope that your holidays are merry and bright, and may all your support inboxes be light.", "year": "2015", "author": "Elizabeth Galle", "author_slug": "elizabethgalle", "published": "2015-12-02T00:00:00+00:00", "url": "https://24ways.org/2015/being-customer-supportive/", "topic": "process"}
{"rowid": 59, "title": "Animating Your Brand", "contents": "Let\u2019s talk about how we add animation to our designs, in a way that\u2019s consistent with other aspects of our brand, such as fonts, colours, layouts and everything else.\nAnimating is fun. Adding animation to our designs can bring them to life and make our designs stand out. Animations can show how the pieces of our designs fit together. They provide context and help people use our products.\nAll too often animation is something we tack on at the end. We put a transition on a modal window or sliding menu and we often don\u2019t think about whether that animation is consistent with our overall design.\nStyle guides to the rescue\nA style guide is a document that establishes and enforces style to improve communication. It can cover anything from typography and writing style to ethics and other, broader goals. It might be a static visual document showing every kind of UI, like in the Codecademy.com redesign shown below.\nUI toolkit from \u201cReimagining Codecademy.com\u201d by @mslima\nIt might be a technical reference with code examples. CodePen\u2019s new design patterns and style guide is a great example of this, showing all the components used throughout the website as live code.\nCodePen\u2019s design patterns and style guide\nA style guide gives a wide view of your project, it maintains consistency when adding new content, and we can use our style guide to present animations.\nLiving documents\nStyle guides don\u2019t need to be static. We can use them to show movement. We can share CSS keyframe animations or transitions that can then go into production. We can also explain why animation is there in the first place.\nJust as a style guide might explain why we chose a certain font or layout, we can use style guides to explain the intent behind animation. This means that if someone else wants to create a new component, they will know why animation applies.\nIf you haven\u2019t yet set up a style guide, you might want to take a look at Pattern Lab. It\u2019s a great tool for setting up your own style guide and includes loads of design patterns to get started.\nThere are many style guide articles linked from the excellent, open sourced, Website Style Guide Resources. Anna Debenham also has an excellent pocket book on the subject.\nAdding animation\nBefore you begin throwing animation at all the things, establish the character you want to convey.\nAndrex Puppy (British TV ad from 1994)\nList some words that describe the character you\u2019re aiming for. If it was the Andrex brand, they might have gone for: fun, playful, soft, comforting.\nPerhaps you\u2019re aiming for something more serious, credible and authoritative. Or maybe exciting and intense, or relaxing and meditative. For each scenario, the animations that best represent these words will be different.\nIn the example below, two animations both take the same length of time, but use different timing functions. One eases, and the other bounces around. Either might be good, depending on your needs.\nTiming functions (CodePen)\nExample: Kitman Labs\nWorking with Kitman Labs, we spent a little time working out what words best reflected the brand and came up with the following:\n\nScientific\nPrecise\nFast\nSolid\nDependable\nHelpful\nConsistent\nClear\n\nWith such a list of words in hand, we design animation that fits. We might prefer a tween that moves quickly to its destination over one that drifts slowly or bounces.\nWe can use the list when justifying our use of animation, such as when it helps our customers understand the context of data on the page. Or we may even choose not to animate, when that might make the message inconsistent.\nCreate guidelines\nIf you already have a style guide, adding animation could begin with creating an overview section.\nOne approach is to create a local website and share it within your organisation. We recently set up a local site for this purpose. \nA recent project\u2019s introduction to the topic of animation\nThis document becomes a reference when adding animation to components. Include links to related resources or examples of animation to help demonstrate the animation style you want.\nPrototyping\nYou can explain the intent of your animation style guide with live animations. This doesn\u2019t just mean waving our hands around. We can show animation through prototypes.\nThere are so many prototype tools right now. You could use Invision, Principle, Floid, or even HTML and CSS as embedded CodePens.\nA login flow prototype created in Principle\nThese tools help when trying out ideas and working through several approaches. Create videos, animated GIFs or online demos to share with others. Experiment. Find what works for you and work with whatever lets you get the most ideas out of your head fastest. Iterate and refine an animation before it gets anywhere near production.\nBuild up a collection\nBuild up your guide, one animation at a time.\nSome people prefer to loosely structure a guide with places to put things as they are discovered or invented; others might build it one page at a time \u2013 it doesn\u2019t matter. The main thing is that you collect animations like you would trading cards. Or Pokemon. Keep them ready to play and deliver that explosive result.\nYou could include animated GIFs, or link to videos or even live webpages as examples of animation. The use of animation to help user experience is also covered nicely in Val Head\u2019s UI animation and UX article on A List Apart.\nWhat matters is that you create an organised place for them to be found. Here are some ideas to get started.\nLogos and brandmarks\nMany sites include some subtle form of animation in their logos. This can draw the eye, add some character, or bring a little liveliness to an otherwise static page. Yahoo and Google have been experimenting with animation on their logos. Even a simple bouncing animation, such as the logo on Hop.ie, can add character.\nThe CSS-animated bouncer from Hop.ie\nContent transitions\nAdding content, removing content, showing and hiding messages are all opportunities to use animation. Careful and deliberate use of animation helps convey what\u2019s changing on screen.\nAnimating list items with CSS (CSSAnimation.rocks)\nFor more detail on this, I also recommend \u201cTransitional Interfaces\u201d by Pasquale D\u2019Silva.\nPage transitions\nOn a larger scale than the changes to content, full-page transitions can smooth the flow between sections of a site. Medium\u2019s article transitions are a good example of this.\nMedium-style page transition (Tympanus.net)\nPreparing a layout before the content arrives\nWe can use animation to draw a page before the content is ready, such as when a page calls a server for data before showing it.\nOptimistic loading grid (CodePen)\nSometimes it\u2019s good to show something to let the user know that everything\u2019s going well. A short animation could cover just enough time to load the initial content and make the loading transition feel seamless.\nInteractions\nHover effects, dropdown menus, slide-in menus and active states on buttons and forms are all opportunities. Look for ways you can remove the sudden changes and help make the experience of using your UI feel smoother.\nForm placeholder animation (Studio MDS)\nKeep animation visible\nIt takes continuous effort to maintain a style guide and keep it up to date, but it\u2019s worth it. Make it easy to include animation and related design decisions in your documentation and you\u2019ll be more likely to do so. If you can make it fun, and be proud of the result, better still.\nWhen updating your style guide, be sure to show the animations at the same time. This might mean animated GIFs, videos or live embedded examples of your components.\nBy doing this you can make animation integral to your design process and make sure it stays relevant.\nInspiration and resources\nThere are loads of great resources online to help you get started. One of my favourites is IBM\u2019s design language site.\nIBM\u2019s design language:\u200aanimation design guidelines\nIBM describes how animation principles apply to its UI work and components. They break down the animations into five categories of animations and explain how they apply to each example.\nThe site also includes an animation library with example videos of animations and links to source code.\nExample component from IBM\u2019s component library\nThe way IBM sets out its aims and methods is helpful not only for their existing designers and developers, but also helps new hires. Furthermore, it\u2019s a good way to show the world that IBM cares about these details.\nAnother popular animation resource is Google\u2019s material design.\nGoogle\u2019s material design documentation\nGoogle\u2019s guidelines cover everything from understanding easing through to creating engaging and useful mobile UI.\nThis approach is visible across many of Google\u2019s apps and software, and has influenced design across much of the web. The site is helpful both for learning about animation and as an showcase of how to illustrate examples.\nFrameworks\nIf you don\u2019t want to create everything from scratch, there are resources you can use to start using animation in your UI. One such resource is Salesforce\u2019s Lightning design system.\nThe system goes further than most guides. It includes a downloadable framework for adding animation to your projects. It has some interesting concepts, such as elevation settings to handle positioning on the z-axis.\nExample of elevation from Salesforce\u2019s Lightning design system\nYou should also check out Animate.css.\n\u201cJust add water\u201d\u200a\u2014\u200aAnimate.css\nAnimate.css gives you a set of predesigned animations you can apply to page elements using classes. If you use JavaScript to add or remove classes, you can then trigger complex animations. It also plays well with scroll-triggering, and tools such as WOW.js.\nLearn, evolve and make it your own\nThere\u2019s a wealth online of information and guides we can use to better understand animation. They can inspire and kick-start our own visual and animation styles. So let\u2019s think of the design of animations just as we do fonts, colours and layouts. Let\u2019s choose animation deliberately, making it part of our style guides.\nMany thanks to Val Head for taking the time to proofread and offer great suggestions for this article.", "year": "2015", "author": "Donovan Hutchinson", "author_slug": "donovanhutchinson", "published": "2015-12-01T00:00:00+00:00", "url": "https://24ways.org/2015/animating-your-brand/", "topic": "design"}
{"rowid": 32, "title": "Cohesive UX", "contents": "With Yosemite, Apple users can answer iPhone calls on their MacBooks. This is weird. And yet it\u2019s representative of a greater trend toward cohesion.\n\nShortly after upgrading to Yosemite, a call came in on my iPhone and my MacBook \u201crang\u201d in parallel. And I was all, like, \u201cWut?\u201d This was a new feature in Yosemite, and honestly it was a little bizarre at first.\n\n Apple promotional image showing a phone call ringing simultaneously on multiple devices.\n\nHowever, I had just spoken at a conference on the very topic you\u2019re reading about now, and therefore I appreciated the underlying concept: the cohesion of user experience, the cohesion of screens.\n\nThis is just one of many examples I\u2019ve encountered since beginning to speak about this topic months ago. But before we get ahead of ourselves, let\u2019s look back at the past few years, specifically the role of responsive web design.\n\nRWD != cohesive experience\n\nI needn\u2019t expound on the virtues of responsive web design (RWD). You\u2019ve likely already encountered more than a career\u2019s worth on the topic. This is a good thing. Count me in as one of its biggest fans.\n\nHowever, if we are to sing the praises of RWD, we must also acknowledge its shortcomings. One of these is that RWD ends where the browser ends. For all its goodness, RWD really has no bearing on native apps or any other experiences that take place outside the browser. This makes it challenging, therefore, to create cohesion for multi-screen users if RWD is the only response to \u201clet\u2019s make it work everywhere.\u201d\n\nWe need something that incorporates the spirit of RWD while unifying all touchpoints for the entire user experience\u2014single device or several devices, in browser or sans browser, native app or otherwise.\n\nI call this cohesive UX, and I believe it\u2019s the next era of successful user experiences.\n\nToward a unified whole\n\nSimply put, the goal of cohesive UX is to deliver a consistent, unified user experience regardless of where the experience begins, continues, and ends.\n\nTwo facets are vital to cohesive UX:\n\n\n\tFunction and form\n\tData symmetry\n\n\nLet\u2019s examine each of these.\n\nFunction AND form\n\nFunction over form, of course. Right? Not so fast, kiddo.\n\nConsider Bruce Lawson\u2019s dad. After receiving an Android phone for Christmas and thumbing through his favorite sites, he was puzzled why some looked different from their counterparts on the desktop. \u201cWhen a site looked radically different,\u201d Bruce observed, \u201che\u2019d check the URL bar to ensure that he\u2019d typed in the right address. In short, he found RWD to be confusing and it meant he didn\u2019t trust the site.\u201d A lack of cohesive form led to a jarring experience for Bruce\u2019s dad.\n\nNow, if I appear to be suggesting websites must look the same in every browser\u2014you already learned they needn\u2019t\u2014know that I recognize the importance of context, especially in regards to mobile. I made a case for this more than seven years ago.\n\nRather, cohesive UX suggests that form deserves the same respect as function when crafting user experiences that span multiple screens or devices. And users are increasingly comfortable traversing media. For example, more than 40% of adults in the U.S. owning more than one device start an activity on one screen and finish it on another, according to a study commissioned by Facebook. I suspect that percentage will only increase in 2015, and I suspect the tech-affluent readers of 24 ways are among the 40%.\n\nThere are countless examples of cohesive form and function. Consider Gmail, which displays email conversations visually as a stack that can be expanded and collapsed like the bellows of an accordion. This visual metaphor has been consistent in virtually any instance of Gmail\u2014website or app\u2014since at least 2007 when I captured this screenshot on my Nokia 6680:\n\n Screenshot captured while authoring Mobile Web Design (2007). Back then we didn\u2019t call this an app, but rather a \u2018smart client\u2019.\n\nWhen the holistic experience is cohesive as it is with Gmail, users\u2019 mental models and even muscle memory are preserved.1 Functionality and aesthetics align with the expectations users have for how things should function and what they should look like. In other words, the experience is roughly the same across screens.\n\nBut don\u2019t be ridiculous, peoples. Note that I said \u201croughly.\u201d It\u2019s important to avoid mindless replication of aesthetics and functionality for the sake of cohesion. Again, the goal is a unified whole, not a carbon copy. Affordances and concessions should be made as context and intuition require. For example, while Facebook users are accustomed to top-aligned navigation in the browser, they encounter bottom-aligned navigation in the iOS app as justified by user testing:\n\nThe iOS app model has held up despite many attempts to better it: http://t.co/rSMSAqeh9m pic.twitter.com/mBp36lAEgc\u2014 Luke Wroblewski (@lukew) December 10, 2014\n\n\nDespite the (rather minor) lack of consistency in navigation placement, other elements such as icons, labels, and color theme work in tandem to produce a unified, holistic whole.\n\nData symmetry\n\nData symmetry involves the repetition, continuity, or synchronicity of data across screens, devices, and platforms. As regards cohesive UX, data includes not just the material (such as an article you\u2019re writing on Medium) but also the actions that can be performed on or with that material (such as Medium\u2019s authoring tools). That is to say, \u201csync verbs, not just nouns\u201d (Josh Clark).\n\nIn my estimation, Amazon is an archetype of data symmetry, as is Rdio. When logged in, data is shared across virtually any device of any kind, irrespective of using a browser or native app. Add a product to your Amazon cart from your phone during the morning commute, and finish the transaction at work on your laptop. Easy peasy.\n\nAmazon\u2019s aesthetics are crazy cohesive, to boot:\n\n Amazon web (left) and native app (right).\n\nWith Rdio, not only are playlists and listening history synced across screens as you would expect, but the cohesion goes even further. Rdio\u2019s remote control feature allows you to control music playing on one device using another device, all in real time.\n\n Rdio\u2019s remote control feature, as viewed on my MacBook while music plays on my iMac.\n\nAt my office I often work from my couch using my MacBook, but my speakers are connected to my iMac. When signed in to Rdio on both devices, my MacBook serves as proxy for controlling Rdio on my iMac, much the same as any Yosemite-enabled device can serve as proxy for an incoming iPhone call.\n\n Me, in my office. Note the iMac and speakers at far right.\n\nThis is a brilliant example of cohesive design, and it\u2019s executed entirely via the cloud.\n\nThings to consider\n\nConsider the following when crafting cohesive experiences:\n\n\n\tInventory the elements that comprise your product experience, and cohesify them.2\nConsider things such as copy, tone, typography, iconography, imagery, flow, placement, brand identification, account data, session data, user preferences, and so on. Then, create cohesion among these elements to the greatest extent possible, while adapting to context as needed.\n\tStore session data in the cloud rather than locally.\nFor example, avoid using browser cookies to store shopping cart data, as cookies are specific to a single browser on a single device. Instead, store this data in the cloud so it can be accessed from other devices, as well as beyond the browser.\n\tConsider using web views when developing your native app.\n\u201cYou\u2019re already using web apps in native wrappers without even noticing it,\u201d Lukas Mathis contends. \u201cThe fact that nobody even notices, the fact that this isn\u2019t a story, shows that, when it comes to user experience, web vs. native doesn\u2019t matter anymore.\u201d Web views essentially allow you to display HTML content inside a native wrapper. This can reduce the time and effort needed to make the overall experience cohesive. So whereas the navigation bar may be rendered by the app, for example, the remaining page display may be rendered via the web. There\u2019s readily accessible documentation for using web views in C++, iOS, Android, and so forth.\n\n\nNature is calling\n\nReturning to the example of Yosemite and sychronized phone calls, is it really that bizarre in light of cohesive UX? Perhaps at first. But I suspect that, over time, Yosemite\u2019s cohesiveness \u2014 and the cohesiveness of other examples like the ones we\u2019ve discussed here \u2014 will become not only more natural but more commonplace, too.\n\n\n\n1 I browse Flipboard on my iPad nearly every morning as part of my breakfast routine. Swiping horizontally advances to the next page. Countless times I\u2019ve done the same gesture in Flipboard for iPhone only to have it do nothing. This is because the gesture for advancing is vertical on phones. I\u2019m so conditioned to the horizontal swipe that I often fail to make the switch to vertical swipe, and apparently others suffer from the same muscle memory, too.\n\n2 Cohesify isn\u2019t a thing. But chances are you understood what I meant. Yay neologism!", "year": "2014", "author": "Cameron Moll", "author_slug": "cameronmoll", "published": "2014-12-24T00:00:00+00:00", "url": "https://24ways.org/2014/cohesive-ux/", "topic": "ux"}
{"rowid": 44, "title": "Taglines and Truisms", "contents": "To bring her good luck, \u201cwhite rabbits\u201d was the first thing that my grandmother said out loud on the first day of every month. We all need a little luck, but we shouldn\u2019t rely on it, especially when it comes to attracting new clients.\n\nThe first thing we say to a prospective client when they visit our website for the first time helps them to understand not only what we do but why we do it. We can also help them understand why they should choose to work with us over one of our competitors.\n\nTake a minute or two to look at your competitors\u2019 websites. What\u2019s the first thing that they say about themselves? Do they say that they \u201cdesign delightful digital experiences,\u201d \u201ccraft beautiful experiences\u201d or \u201ccreate remarkable digital experiences?\u201d\n\nIt\u2019s easy to find companies who introduce themselves with what they do, their proposition, but what a company does is only part of their story. Their beliefs and values, what they stand for why they do what they do are also important. \n\nWhen someone visits our websites for the first time, we have only a brief moment to help them understand us. To help us we can learn from the advertising industry, where the job of a tagline is to communicate a concept, deliver a message and sell a product, often using only a few words.\n\nWhen an advertising campaign is effective, its tagline stays with you, sometimes long after that campaign is over. For example, can you remember which company or brand these taglines help to sell? (Answers at the bottom of the article:)\n\n\nThe Ultimate Driving Machine\nJust Do It\nDon\u2019t Leave Home Without It\n\n\nA clever tagline isn\u2019t just a play on words, although it can include one. A tagline does far more than help make your company memorable. Used well, it brings together notions of what makes your company and what you offer special. Then it expresses those notions in a few words or possibly a short sentence. \n\nI\u2019m sure that everyone can find examples of company slogans written in the type of language that should stay within the walls of a marketing department. We can also find taglines where the meaning is buried so deep that the tag itself becomes effectively meaningless.\n\nA meaningful tagline supports our ideas about who we are and what we offer, and provides a platform for different executions of them, sometimes over a period of time. For a tagline to work well, it must allow for current and future ideas about a brand.\n\nIt must also be meaningful to our brand and describe a truism, a truth that need not be a fact or statistic, but something that\u2019s true about us, who we are, what we do and why that\u2019s distinctive. It can be obvious, funny, serious or specific but above all it must be true. It should also be difficult to argue with, making your messages difficult to argue with too.\n\nI doubt that I need remind you who this tagline belongs to:\n\n\n\tThere are some things money can\u2019t buy. For everything else there\u2019s MasterCard.\n\n\nThat tagline was launched in 1997 by McCann-Erickson along with the \u201cPriceless\u201d campaign and it helped establish MasterCard as a friendlier credit card company, one with a sense of humour. \n\nMasterCard\u2019s truism is that the things which really matter in life can\u2019t be bought. They are worth more than anything that a monetary value can be applied to. In expressing that truism through the tagline, MasterCard\u2019s advertising tells people to use not just any credit card, but their MasterCard, to pay for everything they buy.\n\n\u201cGuinness is good for you\u201d may have been a stretch, but \u201cGood things come to those who wait\u201d builds on the truism that patience is a virtue and therefore a good pint of Guinness takes time to pour (119.5 seconds. I know you were wondering.)\n\nThe fact that British Airways flies to more destinations than any other airline is their truism, and led their advertisers to the now famous tagline, \u201cThe world\u2019s favourite airline.\u201d\n\n\n\nAt my company, Stuff & Nonsense, we\u2019ve been thinking about taglines as we think about our position within an industry that seems full of companies who \u201cdesign\u201d, \u201ccraft\u201d, and \u201ccreate\u201d \u201cdelightful\u201d, \u201cbeautiful\u201d, \u201cremarkable digital experiences\u201d.\n\nMuch of what made us different has changed along with the type of work we\u2019re interested in doing. Our work\u2019s expanded beyond websites and now includes design for mobile and other media. It\u2019s true we can\u2019t know how or where it will be seen. The ways that we make it are flexible too as we\u2019re careful not to become tied to particular tools or approaches. \n\nIt\u2019s also true that we\u2019re a small team. One that\u2019s flexible enough to travel around the world to work alongside our clients. We join their in-house teams and we collaborate with them in ways that other agencies often find more difficult. We know that our clients appreciate our flexibility and have derived enormous value from it. We know that we\u2019ve won business because of it and that it\u2019s now a big part of our proposition.\n\nOur truism is that we\u2019re flexible, \u201cFabulously flexible\u201d as our tagline now expresses. And although we know that there may be other agencies who can be similarly flexible \u2013 after all, being flexible is not a unique selling proposition \u2013 only we do it so fabulously.\n\n\n\nAs the old year rolls into the new, how will your company describe what you do in 2015? More importantly, how will you tell prospective clients why you do it, what matters to you and why they should work with you?\n\nStart by writing a list of truisms about your company. Write as many as you can, but then whittle that list down to just one, the most important truth. Work on that truism to create a tagline that\u2019s meaningful, difficult to be argue with and, above all, uniquely yours.\n\nAnswers\n\n\nThe Ultimate Driving Machine (BMW)\nJust Do It (Nike)\nDon\u2019t Leave Home Without It (American Express)", "year": "2014", "author": "Andy Clarke", "author_slug": "andyclarke", "published": "2014-12-23T00:00:00+00:00", "url": "https://24ways.org/2014/taglines-and-truisms/", "topic": "business"}
{"rowid": 26, "title": "Integrating Contrast Checks in Your Web Workflow", "contents": "It\u2019s nearly Christmas, which means you\u2019ll be sure to find an overload of festive red and green decorating everything in sight\u2014often in the ugliest ways possible. \n\nWhile I\u2019m not here to battle holiday tackiness in today\u2019s 24 ways, it might just be the perfect reminder to step back and consider how we can implement colour schemes in our websites and apps that are not only attractive, but also legible and accessible for folks with various types of visual disabilities.\n\n This simulated photo demonstrates how red and green Christmas baubles could appear to a person affected by protanopia-type colour blindness\u2014not as festive as you might think. Source: Derek Bruff\n\nI\u2019ve been fortunate to work with Simply Accessible to redesign not just their website, but their entire brand. Although the new site won\u2019t be launching until the new year, we\u2019re excited to let you peek under the tree and share a few treats as a case study into how we tackled colour accessibility in our project workflow. Don\u2019t worry\u2014we won\u2019t tell Santa!\n\nCreate a colour game plan\n\nA common misconception about accessibility is that meeting compliance requirements hinders creativity and beautiful design\u2014but we beg to differ. Unfortunately, like many company websites and internal projects, Simply Accessible has spent so much time helping others that they had not spent enough time helping themselves to show the world who they really are. This was the perfect opportunity for them to practise what they preached.\n\nAfter plenty of research and brainstorming, we decided to evolve the existing Simply Accessible brand. Or, rather, salvage what we could. There was no established logo to carry into the new design (it was a stretch to even call it a wordmark), and the Helvetica typography across the site lacked any character. The only recognizable feature left to work with was colour. It was a challenge, for sure: the oranges looked murky and brown, and the blues looked way too corporate for a company like Simply Accessible. We knew we needed to inject a lot of personality.\n\nThe old Simply Accessible website and colour palette.\n\nAfter an audit to round up every colour used throughout the site, we dug in deep and played around with some ideas to bring some new life to this palette. \n\nChoose effective colours\n\nWhether you\u2019re starting from scratch or evolving an existing brand, the first step to having an effective and legible palette begins with your colour choices. While we aren\u2019t going to cover colour message and meaning in this article, it\u2019s important to understand how to choose colours that can be used to create strong contrast\u2014one of the most important ways to create hierarchy, focus, and legibility in your design.\n\nThere are a few methods of creating effective contrast.\n\nLight and dark colours\n\nThe contrast that exists between light and dark colours is the most important attribute when creating effective contrast.\n\nTry not to use colours that have a similar lightness next to each other in a design.\n\n\n\nThe red and green colours on the left share a similar lightness and don\u2019t provide enough contrast on their own without making some adjustments. Removing colour and showing the relationship in greyscale reveals that the version on the right is much more effective. \n\nIt\u2019s important to remember that red and green colour pairs cause difficulty for the majority of colour-blind people, so they should be avoided wherever possible, especially when placed next to each other. \n\nComplementary contrast\n\n\n\nEffective contrast can also be achieved by choosing complementary colours (other than red and green), that are opposite each other on a colour wheel.\n\nThese colour pairs generally work better than choosing adjacent hues on the wheel.\n\nCool and warm contrast\n\nContrast also exists between cool and warm colours on the colour wheel.\n\nImagine a colour wheel divided into cool colours like blues, purples, and greens, and compare them to warm colours like reds, oranges and yellows.\n\n\n\nChoosing a dark shade of a cool colour, paired with a light tint of a warm colour will provide better contrast than two warm colours or two cool colours. \n\nDevelop colour concepts\n\nAfter much experimentation, we settled on a simple, two-colour palette of blue and orange, a cool-warm contrast colour scheme. We added swatches for call-to-action messaging in green, error messaging in red, and body copy and form fields in black and grey. Shades and tints of blue and orange were added to illustrations and other design elements for extra detail and interest.\n\nFirst stab at a new palette.\n\nWe introduced the new palette for the first time on an internal project to test the waters before going full steam ahead with the website. It gave us plenty of time to get a feel for the new design before sharing it with the public.\n\nPutting the test palette into practice with an internal report\n\nIt\u2019s important to be open to changes in your palette as it might need to evolve throughout the design process. Don\u2019t tell your client up front that this palette is set in stone. If you need to tweak the colour of a button later because of legibility issues, the last thing you want is your client pushing back because it\u2019s different from what you promised.\n\nAs it happened, we did tweak the colours after the test run, and we even adjusted the logo\u2014what looked great printed on paper looked a little too light on screens.\n\nConsider how colours might be used\n\nDon\u2019t worry if you haven\u2019t had the opportunity to test your palette in advance. As long as you have some well-considered options, you\u2019ll be ready to think about how the colour might be used on the site or app. \n\nObviously, in such early stages it\u2019s unlikely that you\u2019re going to know every element or feature that will appear on the site at launch time, or even which design elements could be introduced to the site later down the road. There are, of course, plenty of safe places to start.\n\nFor Simply Accessible, I quickly mocked up these examples in Illustrator to get a handle on the elements of a website where contrast and legibility matter the most: text colours and background colours. While it\u2019s less important to consider the contrast of decorative elements that don\u2019t convey essential information, it\u2019s important for a reader to be able to discern elements like button shapes and empty form fields.\n\nA basic list of possible colour combinations that I had in mind for the Simply Accessible website\n\nRun initial tests\n\nOnce these elements were laid out, I manually plugged in the HTML colour code of each foreground colour and background colour on Lea Verou\u2019s Contrast Checker. I added the results from each colour pair test to my document so we could see at a glance which colours needed adjustment or which colours wouldn\u2019t work at all.\n\nNote: Read more about colour accessibility and contrast requirements\n\n\n\n\n\nAs you can see, a few problems were revealed in this test. To meet the minimum AA compliance, we needed to slightly darken the green, blue, and orange background colours for text\u2014an easy fix. A more complicated problem was apparent with the button colours. I had envisioned some buttons appearing over a blue background, but the contrast ratios were well under 3:1. Although there isn\u2019t a guide in WCAG for contrast requirements of two non-text elements, the ISO and ANSI standard for visible contrast is 3:1, which is what we decided to aim for.\n\nWe also checked our colour combinations in Color Oracle, an app that simulates the most extreme forms of colour blindness. It confirmed that coloured buttons over blue backgrounds was simply not going to work. The contrast was much too low, especially for the more common deuteranopia and protanopia-type deficiencies.\n\nHow our proposed colour pairs could look to people with three types of colour blindness\n\nMake adjustments if necessary\n\n\n\nAs a solution, we opted to change all buttons to white when used over dark coloured backgrounds. In addition to increasing contrast, it also gave more consistency to the button design across the site instead of introducing a lot of unnecessary colour variants.\n\nPutting more work into getting compliant contrast ratios at this stage will make the rest of implementation and testing a breeze. When you\u2019ve got those ratios looking good, it\u2019s time to move on to implementation.\n\nImplement colours in style guide and prototype\n\nOnce I was happy with my contrast checks, I created a basic style guide and added all the colour values from my colour exploration files, introduced more tints and shades, and added patterned backgrounds. I created examples of every panel style we were planning to use on the site, with sample text, links, and buttons\u2014all with working hover states. Not only does this make it easier for the developer, it allows you to check in the browser for any further contrast issues.\n\n\n\n\n\nRun a final contrast check\n\nDuring the final stages of testing and before launch, it\u2019s a good idea to do one more check for colour accessibility to ensure nothing\u2019s been lost in translation from design to code. Unless you\u2019ve introduced massive changes to the design in the prototype, it should be fairly easy to fix any issues that arise, particularly if you\u2019ve stayed on top of updating any revisions in the style guide.\n\nOne of the more well-known evaluation tools, WAVE, is web-based and will work in any browser, but I love using Chrome\u2019s Accessibility Tools. Not only are they built right in to the Inspector, but they\u2019ll work if your site is password-protected or private, too.\n\nChrome\u2019s Accessibility Tools audit feature shows that there are no immediate issues with colour contrast in our prototype \n\nThe human touch\n\nFinally, nothing beats a good round of user testing. Even evaluation tools have their flaws. Although they\u2019re great at catching contrast errors for text and backgrounds, they aren\u2019t going to be able to find errors in non-text elements, infographics, or objects placed next to each other where discernible contrast is important. \n\n\n\nOur final palette, compared with our initial ideas, was quite different, but we\u2019re proud to say it\u2019s not just compliant, but shows Simply Accessible\u2019s true personality. Who knows, it may not be final at all\u2014there are so many opportunities down the road to explore and expand it further.\n\n\n\nAccessibility should never be an afterthought in a project. It\u2019s not as simple as adding alt text to images, or running your site through a compliance checker at the last minute and assuming that a pass means everything is okay. Considering how colour will be used during every stage of your project will help avoid massive problems before launch, or worse, launching with serious issues. \n\nIf you find yourself working on a personal project over the Christmas break, try integrating these checks into your workflow and make colour accessibility a part of your New Year\u2019s resolutions.", "year": "2014", "author": "Geri Coady", "author_slug": "gericoady", "published": "2014-12-22T00:00:00+00:00", "url": "https://24ways.org/2014/integrating-contrast-checks-in-your-web-workflow/", "topic": "design"}
{"rowid": 36, "title": "Naming Things", "contents": "There are only two hard things in computer science: cache invalidation and naming things.\nPhil Karlton\n\n\nBeing 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\u2019re working on will dictate the conventions used and how rigorously they are enforced.\n\nWorking in-house may mean working with multiple developers, perhaps in distributed teams, who are all committing changes \u2013 possibly to a significant codebase \u2013 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.\n\nEven 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\u2019s sensible, therefore, to ensure that your code can be understood by those who\u2019ll eventually take ownership of it.\n\nPut 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.\n\nLet\u2019s talk about semantics\n\nNames not only allow us to identify objects, but they can also help us describe the objects being identified.\n\nSemantics (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.\n\nHTML elements provide one level of meaning: a widely accepted description of a document\u2019s underlying structure. It\u2019s only with the mutual agreement of browser vendors and developers that indicates a paragraph.\n\nYet (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.\n\nI didn\u2019t 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 \u201cAbout HTML semantics and front-end architecture\u201d, Nicholas Gallagher wrote:\n\n\n\tThe important thing for class name semantics in non-trivial applications is that they be driven by pragmatism and best serve their primary purpose \u2013 providing meaningful, flexible, and reusable presentational/behavioural hooks for developers to use.\n\n\nThese thoughts are echoed by Harry Roberts in his CSS Guidelines:\n\n\n\tThe 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 \u2018semantics\u2019, look more closely at sensibility and longevity \u2013 choose names based on ease of maintenance, not for their perceived meaning.\n\n\nNaming methodologies\n\nFront-end development has undergone a revolution in recent years. As the projects we\u2019ve 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.\n\nJonathan Snook\u2019s 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:\n\n\n\tBy 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.\n\n\tI 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.\n\n\nSMACSS is more a set of suggestions than a rigid framework, so its ideas can be incorporated into your own practice. Nicholas Gallagher\u2019s SUIT CSS project is far more strict in its naming conventions:\n\n\n\tSUIT 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.\n\n\nOver the last year, I\u2019ve 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:\n\n
\n Rudolph \n Dasher \n Dancer \n Prancer \n Vixen \n Comet \n Cupid \n Dunder \n Blixem \n \n\nI know that:\n\n\n\t.sleigh is a containing block or component.\n\t.sleigh__reindeer is used only as a descendent element of .sleigh.\n\t.sleigh__reindeer\u2013\u2013famous is used only as a modifier of .sleigh__reindeer.\n\n\nWith 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.\n\nEach 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.\n\nWhat makes for a good name?\n\nRegardless of higher-level conventions, there\u2019s no getting away from the fact that, at some point, we\u2019re still going to have to name things. Recognising that classes should be named with other developers in mind, what makes for a good name?\n\nUnderstandable\n\nThe 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.\n\n\n\tCulture\nMost words you\u2019ll 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.\n\tIndustry\nIndustries often use specific terms to describe common business practices and concepts. Publishing has a number of these (headline, standfirst, masthead, colophon\u2026) all have well understood meanings \u2013 and not all of them are relevant to online usage.\n\tOrganisation\nCompanies 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)\u2026 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.\n\tProduct\nYour 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\u2019s bar and circle logo is known internally as the roundel, while Nike\u2019s 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.\n\n\nOnce you recognise the origin of the words you use, you\u2019ll 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\u2019d venture most people outside the armed forces don\u2019t know how they\u2019re ordered.\n\nObvious\n\nQuite 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\u2019t overthink it!\n\nOne 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\u2019s ontologies are all useful sources for object names.\n\nFunctional\n\nWhile we\u2019ve 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\u2019s appearance or behaviour, instead look to its function, its purpose. To clarify, ask what a component\u2019s function is, and not how the component functions.\n\nFor example, the Guardian\u2019s 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\u2026), but do suggest intended use, and therefore imply the likely presentation.\n\nConsistent\n\nBeing 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.\n\nAppropriate\n\nYour 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.\n\nIt\u2019s 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:\n\n\n\tGeneric: list\n\tSpecific: naughty-children\n\tCombined: naughty-children list\n\n\nIf following the BEM methodology, you might use the following classes:\n\n\n\tGeneric: list\n\tSpecific: list\u2013\u2013nice-children\n\tCombined: list list\u2013\u2013nice-children\n\n\nExtensible\n\nGood 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.\n\nMicroformats 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:\n\n\n\th-* for root class names (e.g. h-card)\n\tp-* for simple (text) properties (e.g. p-name)\n\tu-* for URL properties (e.g. u-photo)\n\tdt-* for date/time properties (e.g. dt-bday)\n\te-* for embedded markup properties (e.g. e-note)\n\n\nThe 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\u2019t be as robust, so plan accordingly.\n\n(Note: Microformats perform a very specific function, separate from any presentational concerns. It\u2019s 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.)\n\nShort\n\nNames 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.\n\nFun!\n\nFinally, 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.\n\nThe copyright statement on Apple\u2019s 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\u2019s favourite burger restaurant.\n\nA few thoughts on preprocessors\n\nCSS 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\u2026 oh my!\n\nA second article could be written about naming these, so for now I\u2019ll 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.\n\nLooking 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\u2019d venture that the problem lies with the design rather than the naming scheme.\n\nThe 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).\n\nIt still feels like we\u2019re 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!\n\n\n\nEven with sensible rules and conventions in place, naming things can remain difficult, but hopefully I\u2019ve made this exercise a little less painful. Christmas is a time of giving, so to the developer reading your code in a year\u2019s time, why not make your gift one of clearer class names.", "year": "2014", "author": "Paul Lloyd", "author_slug": "paulrobertlloyd", "published": "2014-12-21T00:00:00+00:00", "url": "https://24ways.org/2014/naming-things/", "topic": "code"}