24ways

Custom SQL query returning 101 rows (hide)

Query parameters

rowidtitlecontentsyearauthorauthor_slugpublishedurltopic
195 Levelling Up for Junior Developers 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’ve learnt one framework or tool, there seems to be something new out there. I 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. In 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’t 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. I have tried to be technology agnostic, so that you can use these tips to guide you, whatever your tech stack might be. Without any further ado and in no particular order, let’s get started. Refactoring code like a boss The Boy Scouts have a rule that goes “always leave the campground cleaner than you found it.” This rule can be applied to code too and ensures that you leave code cleaner than you found it. As a junior developer, it’s 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. My favourite book on this subject has to be Clean Code by Robert C. Martin. It’s 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. If 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. Design 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 “common language” 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. Working Effectively With Legacy Code is another one that I found really valuable. Improving your debugging skills A 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. If 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. At 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. As 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. The Debugging Mindset is an informative online article by Devon H. O’Dell and discusses the the psychology of learning strategies that lead to effective problem-solving skills. A good understanding of relational databases and NoSQL databases Almost all developers will need to persist data at some point in their career. Even if you don’t write SQL queries in your day to day job, a solid understanding of how they work will help you become a better developer. If 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. This 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. If you’d like to learn more about NoSQL queries, I would recommend starting with this article on MongoDB queries. Unfortunately, there isn’t one overall course as most NoSQL databases have their own syntax. You may also have noticed that I haven’t included other types of databases such as Graph or In-memory; it’s worth focussing on the basics before going any deeper. Performance on the web If 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! Steve 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. A 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. The 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’s High Performance Browser Networking. It is also available to read online at hpbn.co. Understand the end to end architecture of your software project I 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. Try 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. I recommend reading Clean Architecture: A Craftsman’s Guide to Software Structure and Design for more detail on this subject. Far 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. How are things deployed A 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? Even 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’re learning about the system - this is a great way to level up and be appreciated and invaluable. A streamlined deployment process is a beautiful thing, and understanding how they work can help you grow your knowledge as a developer. Continuous Integration is a practical read on the ins and outs of implementing this deployment technique. Docker 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. Writing Tests Testing 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’t 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. The book that started it all for me was Roy Osherove’s The Art of Unit Testing. The code in the book is written in C#, but the principles apply to every language. It’s a great, easy-to-understand read. Another 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. Soft skills Whilst reading through this article, you’ve probably noticed that a large chunk of it focusses on code and technical ability. Without a doubt, I’d 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 “personal attributes that enable someone to interact effectively and harmoniously with other people” and I think that it sums this up perfectly. Working on your “soft skills” is something that can truly help you level up in your career. You may be the world’s greatest coder, but if you colleagues can’t get along with you, your coding skills won’t matter! While you may not learn how to become the perfect co-worker overnight, I really try and live by the motto “don’t be an arsehole”. 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 “is this something an arsehole would do”? If you answered yes to that question, you probably shouldn’t do it! Summary Levelling up as a junior developer doesn’t 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. Whilst 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’t know everything on there! I 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! If you are a junior developer reading this article, what would you add to it? 2017 Dean Hume deanhume 2017-12-05T00:00:00+00:00 https://24ways.org/2017/levelling-up-for-junior-developers/ code
201 Lint the Web Forward With Sonarwhal Years ago, when I was in a senior in college, much of my web development courses focused on two things: the basics like HTML and CSS (and boy, do I mean basic), and Adobe Flash. I spent many nights writing ActionScript 3.0 to build interactions for the websites that I would add to my portfolio. A few months after graduating, I built one website in Flash for a client, then never again. Flash was dying, and it became obsolete in my résumé and portfolio. That was my first lesson in the speed at which things change in technology, and what a daunting realization that was as a new graduate looking to enter the professional world. Now, seven years later, I work on the Microsoft Edge team where I help design and build a tool that would have lessened my early career anxieties: sonarwhal. Sonarwhal is a linting tool, built by and for the web community. The code is open source and lives under the JS Foundation. It helps web developers and designers like me keep up with the constant change in technology while simultaneously teaching how to code better websites. Introducing sonarwhal’s mascot Nellie Good web development is hard. It is more than HTML, CSS, and JavaScript: developers are expected to have a grasp of accessibility, performance, security, emerging standards, and more, all while refreshing this knowledge every few months as the web evolves. It’s a lot to keep track of.   Web development is hard Staying up-to-date on all this knowledge is one of the driving forces for developing this scanning tool. Whether you are just starting out, are a student, or you have over a decade of experience, the sonarwhal team wants to help you build better websites for all browsers. Currently sonarwhal checks for best practices in five categories: Accessibility, Interoperability, Performance, PWAs, and Security. Each check is called a “rule”. You can configure them and even create your own rules if you need to follow some specific guidelines for your project (e.g. validate analytics attributes, title format of pages, etc.). You can use sonarwhal in two ways: An online version, that provides a quick and easy way to scan any public website. A command line tool, if you want more control over the configuration, or want to integrate it into your development flow. The Online Scanner The online version offers a streamlined way to scan a website; just enter a URL and you will get a web page of scan results with a permalink that you can share and revisit at any time. The online version of sonarwal When my team works on a new rule, we spend the bulk of our time carefully researching each subject, finding sources, and documenting it rather than writing the rule’s code. Not only is it important that we get you the right results, but we also want you to understand why something is failing. Next to each failing rule you’ll find a link to its detailed documentation, explaining why you should care about it, what exactly we are testing, examples that pass and examples that don’t, and useful links to even more in-depth documentation if you are interested in the subject. We hope that between reading the documentation and continued use of sonarwhal, developers can stay on top of best practices. As devs continue to build sites and identify recurring issues that appear in their results, they will hopefully start to automatically include those missing elements or fix those pieces of code that are producing errors. This also isn’t a one-way communication: the documentation is not only available on the sonarwhal site, but also on GitHub for editing so you can help us make it even better! A results report The current configuration for the online scanner is very strict, so it might hurt your feelings (it did when I first tested it on my personal website). But you can configure sonarwhal to any level of strictness as well as customize the command line tool to your needs! Sonarwhal’s CLI  The CLI gives you full control of sonarwhal: what rules to use, tweaks to them, domains that are out of your control, and so on. You will need the latest node LTS (v8) or Stable (v9) and your favorite package manager, such as npm: npm install -g sonarwhal You can now run sonarwhal from anywhere via: sonarwhal https://example.com Using the CLI The configuration is done via a .sonarwhalrc file. When analyzing a site, if no file is available, you will be prompted to answer a series of questions: What connector do you want to use? Connectors are what sonarwhal uses to access a website and gather all the information about the requests, resources, HTML, etc. Currently it supports jsdom, Microsoft Edge, and Google Chrome. What formatter? This is how you want to see the results: summary, stylish, etc. Make sure to look at the full list. Some are concise for, perfect for a quick build assessment, while others are more verbose and informative. Do you want to use the recommended rules configuration? Rules are the things we are validating. Unless you’ve read the documentation and know what you are doing, first timers should probably use the recommended configuration. What browsers are you targeting? One of the best features of sonarwhal is that rules can adapt their feedback depending on your targeted browsers, suggesting to add or remove things. For example, the rule “Highest Document Mode” will tell you to add the “X-UA-Compatible” header if IE10 or lower is targeted or remove if the opposite is true. sonarwhal configuration generator questions Once you answer all these questions the scan will start and you will have a .sonarwhalrc file similar to the following: { "connector": { "name": "jsdom", "options": { "waitFor": 1000 } }, "formatters": "stylish", "rulesTimeout": 120000, "rules": { "apple-touch-icons": "error", "axe": "error", "content-type": "error", "disown-opener": "error", "highest-available-document-mode": "error", "validate-set-cookie-header": "warning", // ... } } You should see the scan initiate in the command line and within a few seconds the results should start to appear. Remember, the scan results will look different depending on which formatter you selected so try each one out to see which one you like best. sonarwhal results on my website and hurting my feelings 💔 Now that you have a list of errors, you can get to work improving the site! Note though, that when you scan your website, it scans all the resources on that page and if you’ve added something like analytics or fonts hosted elsewhere, you are unable to change those files. You can configure the CLI to ignore files from certain domains so that you are only getting results for files you are in control of. The documentation should give enough guidance on how to fix the errors, but if it’s insufficient, please help us and suggest edits or contribute back to it. This is a community effort and chances are someone else will have the same question as you. When I scanned both my websites, sonarwhal alerted me to not having an Apple Touch Icon. If I search on the web as opposed to using the sonarwhal documentation, the first top 3 results give me outdated information: I need to include many different icon sizes. I don’t need to include all the different size icons that target different devices. Declaring one icon sized 180px x 180px will provide a large enough icon for devices and it will scale down as appropriate for people on older devices. The information at the top of the search results isn’t always the correct answer to an issue and we don’t want you to have to search through outdated documentation. As sonarwhal’s capabilities expand, the goal is for it to be the one stop shop for helping preflight your website. The journey up until now and looking forward On the Microsoft Edge team, we’re passionate about empowering developers to build great websites. Every day we see so many sites come through our issue tracker. (Thanks for filing those bugs, they help us make Microsoft Edge better and better!) Some issues we see over and over are honest mistakes or outdated ‘best practices’ that could be avoided, so we built this tool to help everyone help make the web a better place. When we decided to create sonarwhal, we wanted to create a tool that would help developers write better and more up-to-date code for their websites. We want sonarwhal to be useful to anyone so, early on, we defined three guiding principles we’ve used along the way: Community Driven. We build for the community’s best interests. The web belongs to everyone and this project should too. Not only is it open source, we’ve also donated it to the JS Foundation and have an inclusive governance model that welcomes the collaboration of anyone, individual or company. User Centric. We want to put the user at the center, making sonarwhal configurable for your needs and easy to use no matter what your skill level is. Collaborative. We didn’t want to reinvent the wheel, so we collaborated with existing tools and services that help developers build for the web. Some examples are aXe, snyk.io, Cloudinary, etc. This is just the beginning and we still have lots to do. We’re hard at work on a backlog of exciting features for future releases, such as: New rules for a variety of areas like performance, accessibility, security, progressive web apps, and more. A plug-in for Visual Studio Code: we want sonarwhal to help you write better websites, and what better moment than when you are in your editor. Configuration options for the online service: as we fine tune the infrastructure, the rule configuration for our scanner is locked, but we look forward to adding CLI customization options here in the near future. This is a tool for the web community by the web community so if you are excited about sonarwhal, making a better web, and want to contribute, we have a few issues where you might be able to help. Also, don’t forget to check the rest of the sonarwhal GitHub organization. PRs are always welcome and appreciated! Let us know what you think about the scanner at @NarwhalNellie on Twitter and we hope you’ll help us lint the web forward! 2017 Stephanie Drescher stephaniedrescher 2017-12-02T00:00:00+00:00 https://24ways.org/2017/lint-the-web-forward-with-sonarwhal/ code
178 Make Out Like a Bandit If you are anything like me, you are a professional juggler. No, we don’t juggle bowling pins or anything like that (or do you? Hey, that’s pretty rad!). I’m talking about the work that we juggle daily. In my case, I’m a full-time designer, a half-time graduate student, a sometimes author and conference speaker, and an all-the-time social networker. Only two of these “positions” have actually put any money in my pocket (and, well, the second one takes a lot of money out). Still, this is all part of the work that I do. Your work situation is probably similar. We are workaholics. So if we work so much in our daily lives, shouldn’t we be making out like bandits? Umm, honestly, I’m not hitting on you, silly. I’m talking about our success. We work and work and work. Shouldn’t we be filthy, stinking rich? Well… okay, that’s not quite what I mean either. I’m not necessarily talking about money (though that could potentially be a part of it). I’m talking about success — as in feeling a true sense of accomplishment and feeling happy about what we do and why we do it. It’s important to feel accomplished and a general happiness in our work. To make out like a bandit (or have an incredible amount of success), you can either get lucky or work hard for it. And if you’re going to work hard for it, you might as well make it all meaningful and worthwhile. This is what I strive for in my own work and my life, and the following points I’m sharing with you are the steps I am taking to work toward this. I know the price of success: dedication, hard work & an unremitting devotion to the things you want to see happen. — Frank Lloyd Wright Learn. Participate. Do. The best way to get good at something is to keep doing whatever it is you’re doing that you want to be good at. For example, a sushi-enthusiast might take a sushi-making class because she wants to learn to make sushi for herself. It totally makes sense while the teacher demonstrates all the procedures, materials, and methods needed to make good, beautiful sushi. Later, the student goes home and tries to make sushi on her own, she gets totally confused and lost. Okay, I’m not even going to hide it, I’m talking about myself (this happened to me). As much as I love sushi, I couldn’t even begin to make good sushi because I’ve never really practiced. Take advantage of learning opportunities where possible. Whether you’re learning CSS, Actionscript, or visual design, the best way to grasp how to do things is to participate, practice, do. Apply what you learn in your work. Participation is so vital to your success. If you have problems, let people know, and ask. But definitely practice on your own. And as cliché as it may sound, believe in yourself because if you don’t think you can do it, no one else will think you can either. Maintain momentum With whatever it is you’re doing, if you find yourself “on a roll”, you should take advantage of that momentum and keep moving. Sure, you’ll definitely want to take breaks here or there, but remember that momentum can be very difficult to obtain again once you’ve lost it. Get it done! Deal with people Whether you love or hate people, the fact is, you gotta deal with them — even the difficult ones. If you’re in a management position, then you know pretty well that most people don’t like being told what to do (even if that’s their job). Find ways to get people excited about what they’re doing. Make people feel that they (and what they do) are needed — people respond better if they’re valued, not commanded. Even if you’re not in a management position, this still applies to the way you work with your coworkers, clients, vendors, etc. Resolve any conflicts right away. Conflicts will inevitably happen. Move on to how you can improve the situation, and do it as quickly as possible. Don’t spend too much time focusing on whose screw up it is — nobody feels good in this situation. Also, try to keep people informed on whatever it is you need or what it is you’re doing. If you’re waiting on something from someone, and it’s been a while, don’t be afraid to say something (tactfully). Sometimes people are forgetful — or just slacking. Hey, it happens! Help yourself by helping others What are some of the small, simple things you can do when you’re working that will help the people you work with (and in most cases, will end up helping yourself)? For example: if you’re a designer, perhaps taking a couple minutes now to organize and name your Photoshop layers will end up saving time later (since it will be easier to find things). This is going to help both you and your team. Or, developers: taking some time to write some documentation (even if it’s as simple as a comment in the code, or a well-written commit message) could potentially save valuable time for both you and your team later. Maybe you have to take a little time to sit down with a coworker and explain why something works the way it does. This helps them out tremendously — and will most likely lead to them respecting you a little more. This is a benefit. If you make little things like this a habit, people will notice. People will enjoy working with you. People will trust you and rely on you. Sure, it might seem beneficial at any given moment to be “in it for yourself” (and therefore only helping yourself), but that won’t last very long. Helping others (whether it be a small or large feat) will cause a positive impact in the long run — and that is what will be more valuable to you and your career. Do work that is meaningful One of the best ways to feel successful about what you do is to feel good and happy about it. And a great way to feel good and happy about what you’re doing is to actually do good. This could be purpose-driven work that focuses on sustainability and environmentalism, or work that helps support causes and charity. Perhaps the work simply inspires people. Or maybe the work is just something you are very passionate about. Whatever the work may be, try working on projects that are meaningful to you. You’ll do well simply by being more motivated and interested. And it’s a double-win if the project is meaningful to others as well. I feel very fortunate to work at a place like Crush + Lovely, where we have found quite frequently that the projects that inspire people, focus on global and social good, and create some sort of positive impact are the very projects that bring us more paid projects. But more importantly, we are happy and excited to do it. You might not work at a company that takes on those types of projects. But perhaps you have your own personal endeavors that create this excitement for you. Elliot Jay Stocks wrote about having pet projects. Do you take on side projects? What are those projects? Over the last couple years, I’ve seen some really fantastic side projects come out that are great examples of meaningful work. These projects reflect the passions and goals of the respective designers and developers involved, and therefore become quite successful (because the people involved simply love what they are doing while they’re doing it). Some of these projects include: Typedia is a shared encyclopedia of typefaces which serves as a resource to classify, categorize, and connect typefaces. It was founded by Jason Santa Maria, a graphic designer with a love and passion for typography. He created it as a solution to a problem he faced as a designer: finding the right typeface. Huffduffer was created by Jeremy Keith, a web developer who wanted to create a podcast of inspirational talks — but after he found that this could be tedious, he decided to create a tool to automate this. Level & Tap was created by passionate photographer and web developer, Tom Watson. It began as a photography print store for Tom’s best personal photography. Over time, more photographers were added to the site and the site has grown to become quite a great collection of beautiful photography. Heat Eat Review is a review blog created by information architect and user experience designer, Abi Jones. As a foodie, she is able to use this passion for this blog, as it focuses on reviewing TV Dinners, Frozen Meals, and Microwavable Foods. Art in My Coffee, a favorite personal project of my own, is a photo blog of coffee art I created, after I found that my friends and I were frequently posting coffee art photos to Flickr, Twitter, and other websites. After the blog became more popular, I teamed up with Meagan Fisher on the project, who has just as much a passion for coffee art, if not more. So, what’s important to you? This is the very, very important question here. What really matters to you most? Beyond just working on meaningful projects you are passionate about, is the work you’re doing the right work for you, so that you can live a good lifestyle? Scott Boms wrote an excellent article, Burnout, in which he shares his own experience in battling stress and exhaustion, and what he learned from it. You should definitely read the article in its entirety, but a couple of his points that are particularly excellent are: Make time for numero uno, in which you make time for the things in life that make you happy Examine your values, goals, and measures of success, in which you work toward the things you are passionate about, your own personal development, and focusing on the things that matter. A solid work-life balance can be a challenging struggle to obtain. Of course, you can cheat this by finding ways to combine the things you love with the things you do (so then it doesn’t even feel like you’re working — oh, you sneaky little bandit!). However, there are other factors to consider beyond your general love for the work you’re doing. Take proper care of yourself physically, mentally, and socially. So, are you making out like a bandit? Do you feel accomplished and generally happy with your work? If not, perhaps that is something to focus on for the next year. Consider your work (both in your job as well as any side projects you may take on) and how it benefits you — present and future. Take any steps necessary to get you to where you need to be. If you are miserable, fix it! Finally, it’s important to be thankful for the things that matter to you and make you happy. Pass it along everyday. Thank people. It’s a simple thing, really. Saying “thank you” can and will have enormous impact on the people around you. Oh. And, I apologize if the title of this article led you to thinking it would teach you how to be an amazing kisser. That’s a different article entirely for 24 ways to impress your friends! 2009 Jina Anne jina 2009-12-21T00:00:00+00:00 https://24ways.org/2009/make-out-like-a-bandit/ business
20 Make Your Browser Dance It was a crisp winter’s evening when I pulled up alongside the pier. I stepped out of my car and the bitterly cold sea air hit my face. I walked around to the boot, opened it and heaved out a heavy flight case. I slammed the boot shut, locked the car and started walking towards the venue. This was it. My first gig. I thought about all those weeks of preparation: editing video clips, creating 3-D objects, making coloured patterns, then importing them all into software and configuring effects to change as the music did; targeting frequency, beat, velocity, modifying size, colour, starting point; creating playlists of these… and working out ways to mix them as the music played. This was it. This was me VJing. This was all a lifetime (well a decade!) ago. When I started web designing, VJing took a back seat. I was more interested in interactive layouts, semantic accessible HTML, learning all the IE bugs and mastering the quirks that CSS has to offer. More recently, I have been excited by background gradients, 3-D transforms, the @keyframe directive, as well as new APIs such as getUserMedia, indexedDB, the Web Audio API But wait, have I just come full circle? Could it be possible, with these wonderful new things in technologies I am already familiar with, that I could VJ again, right here, in a browser? Well, there’s only one thing to do: let’s try it! Let’s take to the dance floor Over the past couple of years working in The Lab I have learned to take a much more iterative approach to projects than before. One of my new favourite methods of working is to create a proof of concept to make sure my theory is feasible, before going on to create a full-blown product. So let’s take the same approach here. The main VJing functionality I want to recreate is manipulating visuals in relation to sound. So for my POC I need to create a visual, with parameters that can be changed, then get some sound and see if I can analyse that sound to detect some data, which I can then use to manipulate the visual parameters. Easy, right? So, let’s start at the beginning: creating a simple visual. For this I’m going to create a CSS animation. It’s just a funky i element with the opacity being changed to make it flash. See the Pen Creating a light by Rumyra (@Rumyra) on CodePen A note about prefixes: I’ve left them out of the code examples in this post to make them easier to read. Please be aware that you may need them. I find a great resource to find out if you do is caniuse.com. You can also check out all the code for the examples in this article Start the music Well, that’s pretty easy so far. Next up: loading in some sound. For this we’ll use the Web Audio API. The Web Audio API is based around the concept of nodes. You have a source node: the sound you are loading in; a destination node: usually the device’s speakers; and any number of processing nodes in between. All this processing that goes on with the audio is sandboxed within the AudioContext. So, let’s start by initialising our audio context. var contextClass = window.AudioContext; if (contextClass) { //web audio api available. var audioContext = new contextClass(); } else { //web audio api unavailable //warn user to upgrade/change browser } Now let’s load our sound file into the new context we created with an XMLHttpRequest. function loadSound() { //set audio file url var audioFileUrl = '/octave.ogg'; //create new request var request = new XMLHttpRequest(); request.open("GET", audioFileUrl, true); request.responseType = "arraybuffer"; request.onload = function() { //take from http request and decode into buffer context.decodeAudioData(request.response, function(buffer) { audioBuffer = buffer; }); } request.send(); } Phew! Now we’ve loaded in some sound! There are plenty of things we can do with the Web Audio API: increase volume; add filters; spatialisation. If you want to dig deeper, the O’Reilly Web Audio API book by Boris Smus is available to read online free. All we really want to do for this proof of concept, however, is analyse the sound data. To do this we really need to know what data we have. Learning the steps Let’s take a minute to step back and remember our school days and science class. I’m sure if I drew a picture of a sound wave, we would all start nodding our heads. The sound you hear is caused by pressure differences in the particles in the air. Sound pushes these particles together, causing vibrations. Amplitude is basically strength of pressure. A simple example of change of amplitude is when you increase the volume on your stereo and the output wave increases in size. This is great when everything is analogue, but the waveform varies continuously and it’s not suitable for digital processing: there’s an infinite set of values. For digital processing, we need discrete numbers. We have to sample the waveform at set time intervals, and record data such as amplitude and frequency. Luckily for us, just the fact we have a digital sound file means all this hard work is done for us. What we’re doing in the code above is piping that data in the audio context. All we need to do now is access it. We can do this with the Web Audio API’s analysing functionality. Just pop in an analysing node before we connect the source to its destination node. function createAnalyser(source) { //create analyser node analyser = audioContext.createAnalyser(); //connect to source source.connect(analyzer); //pipe to speakers analyser.connect(audioContext.destination); } The data I’m really interested in here is frequency. Later we could look into amplitude or time, but for now I’m going to stick with frequency. The analyser node gives us frequency data via the getFrequencyByteData method. Don’t forget to count! To collect the data from the getFrequencyByteData method, we need to pass in an empty array (a JavaScript typed array is ideal). But how do we know how many items the array will need when we create it? This is really up to us and how high the resolution of frequencies we want to analyse is. Remember we talked about sampling the waveform; this happens at a certain rate (sample rate) which you can find out via the audio context’s sampleRate attribute. This is good to bear in mind when you’re thinking about your resolution of frequencies. var sampleRate = audioContext.sampleRate; Let’s say your file sample rate is 48,000, making the maximum frequency in the file 24,000Hz (thanks to a wonderful theorem from Dr Harry Nyquist, the maximum frequency in the file is always half the sample rate). The analyser array we’re creating will contain frequencies up to this point. This is ideal as the human ear hears the range 0–20,000hz. So, if we create an array which has 2,400 items, each frequency recorded will be 10Hz apart. However, we are going to create an array which is half the size of the FFT (fast Fourier transform), which in this case is 2,048 which is the default. You can set it via the fftSize property. //set our FFT size analyzer.fftSize = 2048; //create an empty array with 1024 items var frequencyData = new Uint8Array(1024); So, with an array of 1,024 items, and a frequency range of 24,000Hz, we know each item is 24,000 ÷ 1,024 = 23.44Hz apart. The thing is, we also want that array to be updated constantly. We could use the setInterval or setTimeout methods for this; however, I prefer the new and shiny requestAnimationFrame. function update() { //constantly getting feedback from data requestAnimationFrame(update); analyzer.getByteFrequencyData(frequencyData); } Putting it all together Sweet sticks! Now we have an array of frequencies from the sound we loaded, updating as the sound plays. Now we want that data to trigger our animation from earlier. We can easily pause and run our CSS animation from JavaScript: element.style.webkitAnimationPlayState = "paused"; element.style.webkitAnimationPlayState = "running"; Unfortunately, this may not be ideal as our animation might be a whole heap longer than just a flashing light. We may want to target specific points within that animation to have it stop and start in a visually pleasing way and perhaps not smack bang in the middle. There is no really easy way to do this at the moment as Zach Saucier explains in this wonderful article. It takes some jiggery pokery with setInterval to try to ascertain how far through the CSS animation you are in percentage terms. This seems a bit much for our proof of concept, so let’s backtrack a little. We know by the animation we’ve created which CSS properties we want to change. This is pretty easy to do directly with JavaScript. element.style.opacity = "1"; element.style.opacity = "0.2"; So let’s start putting it all together. For this example I want to trigger each light as a different frequency plays. For this, I’ll loop through the HTML elements and change the opacity style if the frequency gain goes over a certain threshold. //get light elements var lights = document.getElementsByTagName('i'); var totalLights = lights.length; for (var i=0; i<totalLights; i++) { //get frequencyData key var freqDataKey = i*8; //if gain is over threshold for that frequency animate light if (frequencyData[freqDataKey] > 160){ //start animation on element lights[i].style.opacity = "1"; } else { lights[i].style.opacity = "0.2"; } } See all the code in action here. I suggest viewing in a modern browser :) Awesome! It is true — we can VJ in our browser! Let’s dance! So, let’s start to expand this simple example. First, I feel the need to make lots of lights, rather than just a few. Also, maybe we should try a sound file more suited to gigs or clubs. Check it out! I don’t know about you, but I’m pretty excited — that’s just a bit of HTML, CSS and JavaScript! The other thing to think about, of course, is the sound that you would get at a venue. We don’t want to load sound from a file, but rather pick up on what is playing in real time. The easiest way to do this, I’ve found, is to capture what my laptop’s mic is picking up and piping that back into the audio context. We can do this by using getUserMedia. Let’s include this in this demo. If you make some noise while viewing the demo, the lights will start to flash. And relax :) There you have it. Sit back, play some music and enjoy the Winamp like experience in front of you. So, where do we go from here? I already have a wealth of ideas. We haven’t started with canvas, SVG or the 3-D features of CSS. There are other things we can detect from the audio as well. And yes, OK, it’s questionable whether the browser is the best environment for this. For one, I’m using a whole bunch of nonsensical HTML elements (maybe each animation could be held within a web component in the future). But hey, it’s fun, and it looks cool and sometimes I think it’s OK to just dance. 2013 Ruth John ruthjohn 2013-12-02T00:00:00+00:00 https://24ways.org/2013/make-your-browser-dance/ code
185 Make Your Mockup in Markup We aren’t designing copies of web pages, we’re designing web pages. Andy Clarke, via Quotes on Design The old way I used to think the best place to design a website was in an image editor. I’d create a pixel-perfect PSD filled with generic content, send it off to the client, go through several rounds of revisions, and eventually create the markup. Does this process sound familiar? You’re not alone. In a very scientific and official survey I conducted, close to 90% of respondents said they design in Photoshop before the browser. That process is whack, yo! Recently, thanks in large part to the influence of design hero Dan Cederholm, I’ve come to the conclusion that a website’s design should begin where it’s going to live: in the browser. Die Photoshop, die Some of you may be wondering, “what’s so bad about using Photoshop for the bulk of my design?” Well, any seasoned designer will tell you that working in Photoshop is akin to working in a minefield: you never know when it’s going to blow up in your face. The application Adobe Photoshop CS4 has unexpectedly ruined your day. Photoshop’s propensity to crash at crucial moments is a running joke in the industry, as is its barely usable interface. And don’t even get me started on the hot, steaming pile of crap that is text rendering. Text rendered in Photoshop (left) versus Safari (right). Crashing and text rendering issues suck, but we’ve learned to live with them. The real issue with using Photoshop for mockups is the expectations you’re setting for a client. When you send the client a static image of the design, you’re not giving them the whole picture — they can’t see how a fluid grid would function, how the design will look in a variety of browsers, basic interactions like :hover effects, or JavaScript behaviors. For more on the disadvantages to showing clients designs as images rather than websites, check out Andy Clarke’s Time to stop showing clients static design visuals. A necessary evil? In the past we’ve put up with Photoshop because it was vital to achieving our beloved rounded corners, drop shadows, outer glows, and gradients. However, with the recent adaptation of CSS3 in major browsers, and the slow, joyous death of IE6, browsers can render mockups that are just as beautiful as those created in an image editor. With the power of RGBA, text-shadow, box-shadow, border-radius, transparent PNGs, and @font-face combined, you can create a prototype that radiates shiny awesomeness right in the browser. If you can see this epic article through to the end, I’ll show you step by step how to create a gorgeous mockup using mostly markup. Get started by getting naked Content precedes design. Design in the absence of content is not design, it’s decoration. Jeffrey Zeldman In the beginning, don’t even think about style. Instead, start with the foundation: the content. Lay the groundwork for your markup order, and ensure that your design will be useable with styles and images turned off. This is great for prioritizing the content, and puts you on the right path for accessibility and search engine optimization. Not a bad place to start, amirite? An example of unstyled content, in all its naked glory. View it large. Flush out the layout The next step is to structure the content in a usable way. With CSS, making basic layout changes is as easy as switching up a float, so experiment to see what structure suits the content best. The mockup with basic layout work done. Got your grids covered There are a variety of tools that allow you to layer a grid over your browser window. For Mac users I recommend using Slammer, and PC users can check out one of the bookmarklets that are available, such as 960 Gridder. The mockup with a grid applied using Slammer. Once you’ve found a layout that works well for the content, pass it along to the client for review. This keeps them involved in the design process, and gives them an idea of how the site will be structured when it’s live. Start your styling Now for the fun part: begin applying the presentation layer. Let usability considerations drive your decisions about color and typography; use highlighted colors and contrasting typefaces on elements you wish to emphasize. RGBA? More like RGByay! Introducing color is easy with RGBA. I like to start with the page’s main color, then use white at varying opacities to empasize content sections. In the example mockup the body background is set to rgba(203,111,21), the content containers are set to rgba(255,255,255,0.7), and a few elements are highlighted with rgba(255,255,255,0.1) If you’re not sure how RGBA works, check out Drew McLellan’s super helpful 24ways article. Laying down type Just like with color, you can use typography to evoke a feeling and direct a user’s attention. Have contrasting typefaces (like serif headlines and sans-serif body text) to group the content into meaningful sections. In a recent A List Apart article, the Master of Web Typography™ Jason Santa Maria offers excellent advice on how to choose your typefaces: Write down a general description of the qualities of the message you are trying to convey, and then look for typefaces that embody those qualities. Sounds pretty straightforward. I wanted to give my design a classic feel with a hint of nostalgia, so I used Georgia for the headlines, and incorporated the ornate ampersand from Baskerville into the header. A closeup on the site’s header. Let’s get sexy The design doesn’t look too bad as it is, but it’s still pretty flat. We can do better, and after mixing in some CSS3 and a couple of PNGs, it’s going to get downright steamy in here. Give it some glow Objects in the natural world reflect light, so to make your design feel tangible and organic, give it some glow. In the example design I achieved this by creating two white to transparent gradients of varying opacities. Both have a solid white border across their top, which gives edges a double border effect and makes them look sharper. Using CSS3’s text-shadow on headlines and box-shadow on content modules is another quick way to add depth. A wide and closeup view of the design with gradients, text-shadow and box-shadow added. For information on how to implement text-shadow and box-shadow using RGBA, check out the article I wrote on it last week. 37 pieces of flair Okay, maybe you don’t need that much flair, but it couldn’t hurt to add a little; it’s the details that will set your design apart. Work in imagery and texture, using PNGs with an alpha channel so you can layer images and still tweak the color later on. The design with grungy textures, a noisy diagonal stripe pattern, and some old transportation images layered behind the text. Because the colors are rendered using RGBA, these images bleed through the content, giving the design a layered feel. Best viewed large. Send it off Hey, look at that. You’ve got a detailed, well structured mockup for the client to review. Best of all, your markup is complete too. If the client approves the design at this stage, your template is practically finished. Bust out the party hats! Not so fast, Buster! So I don’t know about you, but I’ve never gotten a design past the client’s keen eye for criticism on the first go. Let’s review some hypothetical feedback (none of which is too outlandish, in my experience), and see how we’d make the requested changes in the browser. Updating the typography My ex-girlfriend loved Georgia, so I never want to see it again. Can we get rid of it? I want to use a font that’s chunky and loud, just like my stupid ex-girlfriend. Fakey McClient Yikes! Thankfully with CSS, removing Georgia is as easy as running a find and replace on the stylesheet. In my revised mockup, I used @font-face and League Gothic on the headlines to give the typography the, um, unique feel the client is looking for. The same mockup, using @font-face on the headlines. If you’re unfamiliar with implementing @font-face, check out Nice Web Type‘s helpful article. Adding rounded corners I’m not sure if I’ll like it, but I want to see what it’d look like with rounded corners. My cousin, a Web 2.0 marketing guru, says they’re trendy right now. Fakey McClient Switching to rounded corners is a nightmare if you’re doing your mockup in Photoshop, since it means recreating most of the shapes and UI elements in the design. Thankfully, with CSS border-radius comes to our rescue! By applying this gem of a style to a handful of classes, you’ll be rounded out in no time. The mockup with rounded corners, created using border-radius. If you’re not sure how to implement border-radius, check out CSS3.info‘s quick how-to. Making changes to the color The design is too dark, it’s depressing! They call it ‘the blues’ for a reason, dummy. Can you try using a brighter color? I want orange, like Zeldman uses. Fakey McClient Making color changes is another groan-inducing task when working in Photoshop. Finding and updating every background layer, every drop shadow, and every link can take forever in a complex PSD. However, if you’ve done your mockup in markup with RGBA and semi-transparent PNGs, making changes to your color is as easy as updating the body background and a few font colors. The mockup with an orange color scheme. Best viewed large. Ahem, what about Internet Explorer? Gee, thanks for reminding me, buzzkill. Several of the CSS features I’ve suggested you use, such as RGBA, text-shadow and box-shadow, and border-radius, are not supported in Internet Explorer. I know, it makes me sad too. However, this doesn’t mean you can’t try these techniques out in your markup based mockups. The point here is to get your mockups done as efficiently as possible, and to keep the emphasis on markup from the very beginning. Once the design is approved, you and the client have to decide if you can live with the design looking different in different browsers. Is it so bad if some users get to see drop shadows and some don’t? Or if the rounded corners are missing for a portion of your audience? The design won’t be broken for IE people, they’re just missing out on a few visual treats that other users will see. The idea of rewarding users who choose modern browsers is not a new concept; Dan covers it thoroughly in Handcrafted CSS, and it’s been written about in the past by Aaron Gustafson and Andy Clarke on several occasions. I believe we shouldn’t have to design for the lowest common denominator (cough, IE6 users, cough); instead we should create designs that are beautiful in modern browsers, but still degrade nicely for the other guy. However, some clients just aren’t that progressive, and in that case you can always use background images for drop shadows and rounded corners, as you have in the past. Closing thoughts With the advent of CSS3, browsers are just as capable of giving us beautiful, detailed mockups as Photoshop, and in half the time. I’m not the only one to make an argument for this revised process; in his article Time to stop showing clients static design visuals, and in his presentation Walls Come Tumbling Down, Andy Clarke makes a fantastic case for creating your mockups in markup. So I guess my challenge to you for 2010 is to get out of Photoshop and into the code. Even if the arguments for designing in the browser aren’t enough to make you change your process permanently, it’s worthwhile to give it a try. Look at the New Year as a time to experiment; applying constraints and evaluating old processes can do wonders for improving your efficiency and creativity. 2009 Meagan Fisher meaganfisher 2009-12-24T00:00:00+00:00 https://24ways.org/2009/make-your-mockup-in-markup/ process
50 Make a Comic For something slightly different over Christmas, why not step away from your computer and make a comic? Definitely not the author working on a comic in the studio, with the desk displaying some of the things you need to make a comic on paper. Why make a comic? First of all, it’s truly fun and it’s not that difficult. If you’re a designer, you can use skills you already have, so why not take some time to indulge your aesthetic whims and make something for yourself, rather than for a client or your company. And you can use a computer – or not. If you’re an interaction designer, it’s likely you’ve already made a storyboard or flow, or designed some characters for personas. This is a wee jump away from that, to the realm of storytelling and navigating human emotions through characters who may or may not be human. Similar medium and skills, different content. It’s not a client deliverable but something that stands by itself, and you’ve nobody’s criteria to meet except those that exist in your imagination! Thanks to your brain and the alchemy of comics, you can put nearly anything in a sequence and your brain will find a way to make sense of it. Scott McCloud wrote about the non sequitur in comics: “There is a kind of alchemy at work in the space between panels which can help us find meaning or resonance in even the most jarring of combinations.” Here’s an example of a non sequitur from Scott McCloud’s Understanding Comics – the images bear no relation to one another, but since they’re in a sequence our brains do their best to understand it: Once you know this it takes the pressure off somewhat. It’s a fun thing to keep in mind and experiment with in your comics! Materials needed A4 copy/printing paper HB pencil for light drawing Dip pen and waterproof Indian ink Bristol board (or any good quality card with a smooth, durable surface) Step 1: Get ideas You’d be surprised where you can take a small grain of an idea and develop it into an interesting comic. Think about a funny conversation you had, or any irrational fears, habits, dreams or anything else. Just start writing and drawing. Having ideas is hard, I know, but you will get some ideas when you start working. One way to keep track of ideas is to keep a sketch diary, capturing funny conversations and other events you could use in comics later. You might want to just sketch out the whole comic very roughly if that helps. I tend to sketch the story first, but it usually changes drastically during step 2. Step 2: Edit your story using thumbnails How thumbnailing works. Why use thumbnails? You can move them around or get rid of them! Drawings are harder and much slower to edit than words, so you need to draw something very quick and very rough. You don’t have to care about drawing quality at this point. You might already have a drafted comic from the previous step; now you can split each panel up into a thumbnail like the image above. Get an A4 sheet of printing paper and tear it up into squares. A thumbnail equals a comic panel. Start drawing one panel per thumbnail. This way you can move scenes and parts of the story around as you work on the pacing. It’s an extremely useful tip if you want to expand a moment in time or draw out a dialogue, or if you want to just completely cut scenes. Step 3: Plan a layout So you’ve got the story more or less down: you now need to know how they’ll look on the page. Sketch a layout and arrange the thumbnails into the layout. The simplest way to do this is to divide an A4 page into equal panels — say, nine. But if you want, you can be more creative than that. The Gigantic Beard That Was Evil by Stephen Collins is an excellent example of the scope for using page layout creatively. You can really push the form: play with layout, scale, story and what you think of as a comic. Step 4: Draw the comic I recommend drawing on A4 Bristol board paper since it has a smooth surface, can tolerate a lot of rubbing out and holds ink well. You can get it from any art shop. Using your thumbnails for reference, draw the comic lightly using an HB pencil. Don’t make the line so heavy that it can’t be erased (since you’ll ink over the lines later). Step 5: Ink the comic Image before colour was added. You’ve drawn your story. Well done! Now for the fun part. I recommend using a dip pen and some waterproof ink. Why waterproof? If you want, you can add an ink wash later, or even paint it. If you don’t have a dip pen, you could also use any quality pen. Carefully go over your pencilled lines with the pen, working from top left to right and down, to avoid smudging it. It’s unfortunately easy to smudge the ink from the dip pen, so I recommend practising first. You’ve made a comic! Step 6: Adding colour Comics traditionally had a limited colour palette before computers (here’s an in-depth explanation if you’re curious). You can actually do a huge amount with a restricted colour palette. Ellice Weaver’s comics show how very nicely how you can paint your work using a restricted palette. So for the next step, resist the temptation to add ALL THE COLOURS and consider using a limited palette. Once the ink is completely dry, erase the pencilled lines and you’ll be left with a beautiful inked black and white drawing. You could use a computer for this part. You could also photocopy it and paint straight on the copy. If you’re feeling really brave, you could paint straight on the original. But I’d suggest not doing this if it’s your first try at painting! What follows is an extremely basic guide for painting using Photoshop, but there are hundreds of brilliant articles out there and different techniques for digital painting. How to paint your comic using Photoshop Scan the drawing and open it in Photoshop. You can adjust the levels (Image → Adjustments → Levels) to make the lines darker and crisper, and the paper invisible. At this stage, you can erase any smudges or mistakes. With a Wacom tablet, you could even completely redraw parts! Computers are just amazing. Keep the line art as its own layer. Add a new layer on top of the lines, and set the layer state from normal to multiply. This means you can paint your comic without obscuring your lines. Rename the layer something else, so you can keep track. Start blocking in colour. And once you’re happy with that, experiment with adding tone and texture. Christmas comic challenge! Why not challenge yourself to make a short comic over Christmas? If you make one, share it in the comments. Or show me on Twitter — I’d love to see it. Credit: Many of these techniques were learned on the Royal Drawing School’s brilliant ‘Drawing the Graphic Novel’ course. 2015 Rebecca Cottrell rebeccacottrell 2015-12-20T00:00:00+00:00 https://24ways.org/2015/make-a-comic/ design
97 Making Modular Layout Systems For all of the advantages the web has with distribution of content, I’ve always lamented the handiness of the WYSIWYG design tools from the print publishing world. When I set out to redesign my personal website, I wanted to have some of the same abilities that those tools have, laying out pages how I saw fit, and that meant a flexible system for dealing with imagery. Building on some of the CSS that Eric Meyer employed a few years back on the A List Apart design, I created a set of classes to use together to achieve the variety I was after. Employing multiple classes isn’t a new technique, but most examples aren’t coming at this from strictly editorial and visual perspectives; I wanted to have options to vary my layouts depending on content. If you want to skip ahead, you can view the example first. Laying the Foundation We need to be able to map out our page so that we have predictable canvas, and then create a system of image sizes that work with it. For the sake of this article, let’s use a simple uniform 7-column grid, consisting of seven 100px-wide columns and 10px of space between each column, though you can use any measurements you want as long as they remain constant. All of our images will have a width that references the grid column widths (in our example, 100px, 210px, 320px, 430px, 540px, 650px, or 760px), but the height can be as large as needed. Once we know our images will all have one of those widths, we can setup our CSS to deal with the variations in layout. In the most basic form, we’re going to be dealing with three classes: one each that represent an identifier, a size, and a placement for our elements. This is really a process of abstracting the important qualities of what you would do with a given image in a layout into separate classes, allowing you to quickly customize their appearance by combining the appropriate classes. Rather than trying to serve up a one-size-fits-all approach to styling, we give each class only one or two attributes and rely on the combination of classes to get us there. Identifier This specifies what kind of element we have: usually either an image (pic) or some piece of text (caption). Size Since we know how our grid is constructed and the potential widths of our images, we can knock out a space equal to the width of any number of columns. In our example, that value can be one, two, three, four, five, six, or seven. Placement This tells the element where to go. In our example we can use a class of left or right, which sets the appropriate floating rule. Additions I created a few additions that be tacked on after the “placement” in the class stack: solo, for a bit more space beneath images without captions, frame for images that need a border, and inset for an element that appears inside of a block of text. Outset images are my default, but you could easily switch the default concept to use inset images and create a class of outset to pull them out of the content columns. The CSS /* I D E N T I F I E R */ .pic p, .caption { font-size: 11px; line-height: 16px; font-family: Verdana, Arial, sans-serif; color: #666; margin: 4px 0 10px; } /* P L A C E M E N T */ .left {float: left; margin-right: 20px;} .right {float: right; margin-left: 20px;} .right.inset {margin: 0 120px 0 20px;} /* img floated right within text */ .left.inset {margin-left: 230px;} /* img floated left within text */ /* S I Z E */ .one {width: 100px;} .two {width: 210px;} .three {width: 320px;} .four {width: 430px;} .five {width: 540px;} .six {width: 650px;} .seven {width: 760px;} .eight {width: 870px;} /* A D D I T I O N S */ .frame {border: 1px solid #999;} .solo img {margin-bottom: 20px;} In Use You can already see how powerful this approach can be. If you want an image and a caption on the left to stretch over half of the page, you would use: <div class="pic four left"> <img src="image.jpg" /> <p>Caption goes here.</p> </div> Or, for that same image with a border and no caption: <img src="image.jpg" class="pic four left frame solo"/> You just tack on the classes that contain the qualities you need. And because we’ve kept each class so simple, we can apply these same stylings to other elements too: <p class="caption two left">Caption goes here.</p> Caveats Obviously there are some potential semantic hang-ups with these methods. While classes like pic and caption stem the tide a bit, others like left and right are tougher to justify. This is something that you have to decide for yourself; I’m fine with the occasional four or left class because I think there’s a good tradeoff. Just as a fully semantic solution to this problem would likely be imperfect, this solution is imperfect from the other side of the semantic fence. Additionally, IE6 doesn’t understand the chain of classes within a CSS selector (like .right.inset). If you need to support IE6, you may have to write a few more CSS rules to accommodate any discrepancies. Opportunities This is clearly a simple example, but starting with a modular foundation like this leaves the door open for opportunity. We’ve created a highly flexible and human-readable system for layout manipulation. Obviously, this is something that would need to be tailored to the spacing and sizes of your site, but the systematic approach is very powerful, especially for editorial websites whose articles might have lots of images of varying sizes. It may not get us fully to the flexibility of WYSIWYG print layouts, but methods like this point us in a direction of designs that can adapt to the needs of the content. View the example: without grid and with grid. 2008 Jason Santa Maria jasonsantamaria 2008-12-15T00:00:00+00:00 https://24ways.org/2008/making-modular-layout-systems/ process
30 Making Sites More Responsive, Responsibly With digital projects we’re used to shifting our thinking to align with our target audience. We may undertake research, create personas, identify key tasks, or observe usage patterns, with our findings helping to refine our ongoing creations. A product’s overall experience can make or break its success, and when it comes to defining these experiences our development choices play a huge role alongside more traditional user-focused activities. The popularisation of responsive web design is a great example of how we are able to shape the web’s direction through using technology to provide better experiences. If we think back to the move from table-based layouts to CSS, initially our clients often didn’t know or care about the difference in these approaches, but we did. Responsive design was similar in this respect – momentum grew through the web industry choosing to use an approach that we felt would give a better experience, and which was more future-friendly.  We tend to think of responsive design as a means of displaying content appropriately across a range of devices, but the technology and our implementation of it can facilitate much more. A responsive layout not only helps your content work when the newest smartphone comes out, but it also ensures your layout suitably adapts if a visually impaired user drastically changes the size of the text. The 24 ways site at 400% on a Retina MacBook Pro displays a layout more typically used for small screens. When we think more broadly, we realise that our technical choices and approaches to implementation can have knock-on effects for the greater good, and beyond our initial target audiences. We can make our experiences more responsive to people’s needs, enhancing their usability and accessibility along the way. Being responsibly responsive Of course, when we think about being more responsive, there’s a fine line between creating useful functionality and becoming intrusive and overly complex. In the excellent Responsible Responsive Design, Scott Jehl states that: A responsible responsive design equally considers the following throughout a project: Usability: The way a website’s user interface is presented to the user, and how that UI responds to browsing conditions and user interactions. Access: The ability for users of all devices, browsers, and assistive technologies to access and understand a site’s features and content. Sustainability: The ability for the technology driving a site or application to work for devices that exist today and to continue to be usable and accessible to users, devices, and browsers in the future. Performance: The speed at which a site’s features and content are perceived to be delivered to the user and the efficiency with which they operate within the user interface. Scott’s book covers these ideas in a lot more detail than I’ll be able to here (put it on your Christmas list if it’s not there already), but for now let’s think a bit more about our roles as digital creators and the power this gives us. Our choices around technology and the decisions we have to make can be extremely wide-ranging. Solutions will vary hugely depending on the needs of each project, though we can further explore the concept of making our creations more responsive through the use of humble web technologies. The power of the web We all know that under the HTML5 umbrella are some great new capabilities, including a number of JavaScript APIs such as geolocation, web audio, the file API and many more. We often use these to enhance the functionality of our sites and apps, to add in new features, or to facilitate device-specific interactions. You’ll have seen articles with flashy titles such as “Top 5 JavaScript APIs You’ve Never Heard Of!”, which you’ll probably read, think “That’s quite cool”, yet never use in any real work. There is great potential for technologies like these to be misused, but there are also great prospects for them to be used well to enhance experiences. Let’s have a look at a few examples you may not have considered. Offline first When we make websites, many of us follow a process which involves user stories – standardised snippets of context explaining who needs what, and why. “As a student I want to pay online for my course so I don’t have to visit the college in person.” “As a retailer I want to generate unique product codes so I can manage my stock.” We very often focus heavily on what needs doing, but may not consider carefully how it will be done. As in Scott’s list, accessibility is extremely important, not only in terms of providing a great experience to users of assistive technologies, but also to make your creation more accessible in the general sense – including under different conditions. Offline first is yet another ‘first’ methodology (my personal favourite being ‘tea first’), which encourages us to develop so that connectivity itself is an enhancement – letting users continue with tasks even when they’re offline. Despite the rapid growth in public Wi-Fi, if we consider data costs and connectivity in developing countries, our travel habits with planes, underground trains and roaming (or simply if you live in the UK’s signal-barren East Anglian wilderness as I do), then you’ll realise that connectivity isn’t as ubiquitous as our internet-addled brains would make us believe. Take a scenario that I’m sure we’re all familiar with – the digital conference. Your venue may be in a city served by high-speed networks, but after overloading capacity with a full house of hashtag-hungry attendees, each carrying several devices, then everyone’s likely to be offline after all. Wouldn’t it be better if we could do something like this instead? Someone visits our conference website. On this initial run, some assets may be cached for future use: the conference schedule, the site’s CSS, photos of the speakers. When the attendee revisits the site on the day, the page shell loads up from the cache. If we have cached content (our session timetable, speaker photos or anything else), we can load it directly from the cache. We might then try to update this, or get some new content from the internet, but the conference attendee already has a base experience to use. If we don’t have something cached already, then we can try grabbing it online. If for any reason our requests for new content fail (we’re offline), then we can display a pre-cached error message from the initial load, perhaps providing our users with alternative suggestions from what is cached. There are a number of ways we can make something like this, including using the application cache (AppCache) if you’re that way inclined. However, you may want to look into service workers instead. There are also some great resources on Offline First! if you’d like to find out more about this. Building in offline functionality isn’t necessarily about starting offline first, and it’s also perfectly possible to retrofit sites and apps to catch offline scenarios, but this kind of graceful degradation can end up being more complex than if we’d considered it from the start. By treating connectivity as an enhancement, we can improve the experience and provide better performance than we can when waiting to counter failures. Our websites can respond to connectivity and usage scenarios, on top of adapting how we present our content. Thinking in this way can enhance each point in Scott’s criteria. As I mentioned, this isn’t necessarily the kind of development choice that our clients will ask us for, but it’s one we may decide is simply the right way to build based on our project, enhancing the experience we provide to people, and making it more responsive to their situation. Even more accessible We’ve looked at accessibility in terms of broadening when we can interact with a website, but what about how? Our user stories and personas are often of limited use. We refer in very general terms to students, retailers, and sometimes just users. What if we have a student whose needs are very different from another student? Can we make our sites even more usable and accessible through our development choices? Again using JavaScript to illustrate this concept, we can do a lot more with the ways people interact with our websites, and with the feedback we provide, than simply accepting keyboard, mouse and touch inputs and displaying output on a screen. Input Ambient light detection is one of those features that looks great in simple demos, but which we struggle to put to practical use. It’s not new – many satnav systems automatically change the contrast for driving at night or in tunnels, and our laptops may alter the screen brightness or keyboard backlighting to better adapt to our surroundings. Using web technologies we can adapt our presentation to be better suited to ambient light levels. If our device has an appropriate light sensor and runs a browser that supports the API, we can grab the ambient light in units using ambient light events, in JavaScript. We may then change our presentation based on different bandings, perhaps like this: window.addEventListener('devicelight', function(e) { var lux = e.value; if (lux < 50) { //Change things for dim light } if (lux >= 50 && lux <= 10000) { //Change things for normal light } if (lux > 10000) { //Change things for bright light } }); Live demo (requires light sensor and supported browser). Soon we may also be able to do such detection through CSS, with light-level being cited in the Media Queries Level 4 specification. If that becomes the case, it’ll probably look something like this: @media (light-level: dim) { /*Change things for dim light*/ } @media (light-level: normal) { /*Change things for normal light*/ } @media (light-level: washed) { /*Change things for bright light*/ } While we may be quick to dismiss this kind of detection as being a gimmick, it’s important to consider that apps such as Light Detector, listed on Apple’s accessibility page, provide important context around exactly this functionality. “If you are blind, Light Detector helps you to be more independent in many daily activities. At home, point your iPhone towards the ceiling to understand where the light fixtures are and whether they are switched on. In a room, move the device along the wall to check if there is a window and where it is. You can find out whether the shades are drawn by moving the device up and down.” everywaretechnologies.com/apps/lightdetector Input can be about so much more than what we enter through keyboards. Both an ever increasing amount of available sensors and more APIs being supported by the major browsers will allow us to cater for more scenarios and respond to them accordingly. This can be as complex or simple as you need; for instance, while x-webkit-speech has been deprecated, the web speech API is available for a number of browsers, and research into sign language detection is also being performed by organisations such as Microsoft. Output Web technologies give us some great enhancements around input, allowing us to adapt our experiences accordingly. They also provide us with some nice ways to provide feedback to users. When we play video games, many of our modern consoles come with the ability to have rumble effects on our controller pads. These are a great example of an enhancement, as they provide a level of feedback that is entirely optional, but which can give a great deal of extra information to the player in the right circumstances, and broaden the scope of our comprehension beyond what we’re seeing and hearing. Haptic feedback is possible on the web as well. We could use this in any number of responsible applications, such as alerting a user to changes or using different patterns as a communication mechanism. If you find yourself in a pickle, here’s how to print out SOS in Morse code through the vibration API. The following code indicates the length of vibration in milliseconds, interspersed by pauses in milliseconds. navigator.vibrate([100, 300, 100, 300, 100, 300, 600, 300, 600, 300, 600, 300, 100, 300, 100, 300, 100]); Live demo (requires supported browser) With great power… What you’ve no doubt come to realise by now is that these are just more examples of progressive enhancement, whose inclusion will provide a better experience if the capabilities are available, but which we should not rely on. This idea isn’t new, but the most important thing to remember, and what I would like you to take away from this article, is that it is up to us to decide to include these kind of approaches within our projects – if we don’t root for them, they probably won’t happen. This is where our professional responsibility comes in. We won’t necessarily be asked to implement solutions for the scenarios above, but they illustrate how we can help to push the boundaries of experiences. Maybe we’ll have to switch our thinking about how we build, but we can create more usable products for a diverse range of people and usage scenarios through the choices we make around technology. Let’s stop thinking simply in terms of features inside a narrow view of our target users, and work out how we can extend these to cater for a wider set of situations. When you plan your next digital project, consider the power of the web and the enhancements we can use, and try to make your projects even more responsive and responsible. 2014 Sally Jenkinson sallyjenkinson 2014-12-10T00:00:00+00:00 https://24ways.org/2014/making-sites-more-responsive-responsibly/ code
136 Making XML Beautiful Again: Introducing Client-Side XSL Remember that first time you saw XML and got it? When you really understood what was possible and the deep meaning each element could carry? Now when you see XML, it looks ugly, especially when you navigate to a page of XML in a browser. Well, with every modern browser now supporting XSL 1.0, I’m going to show you how you can turn something as simple as an ATOM feed into a customised page using a browser, Notepad and some XSL. What on earth is this XSL? XSL is a family of recommendations for defining XML document transformation and presentation. It consists of three parts: XSLT 1.0 – Extensible Stylesheet Language Transformation, a language for transforming XML XPath 1.0 – XML Path Language, an expression language used by XSLT to access or refer to parts of an XML document. (XPath is also used by the XML Linking specification) XSL-FO 1.0 – Extensible Stylesheet Language Formatting Objects, an XML vocabulary for specifying formatting semantics XSL transformations are usually a one-to-one transformation, but with newer versions (XSL 1.1 and XSL 2.0) its possible to create many-to-many transformations too. So now you have an overview of XSL, on with the show… So what do I need? So to get going you need a browser an supports client-side XSL transformations such as Firefox, Safari, Opera or Internet Explorer. Second, you need a source XML file – for this we’re going to use an ATOM feed from Flickr.com. And lastly, you need an editor of some kind. I find Notepad++ quick for short XSLs, while I tend to use XMLSpy or Oxygen for complex XSL work. Because we’re doing a client-side transformation, we need to modify the XML file to tell it where to find our yet-to-be-written XSL file. Take a look at the source XML file, which originates from my Flickr photos tagged sky, in ATOM format. The top of the ATOM file now has an additional <?xml-stylesheet /> instruction, as can been seen on Line 2 below. This instructs the browser to use the XSL file to transform the document. <?xml version="1.0" encoding="utf-8" standalone="yes"?> <?xml-stylesheet type="text/xsl" href="flickr_transform.xsl"?> <feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"> Your first transformation Your first XSL will look something like this: <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"> <xsl:output method="html" encoding="utf-8"/> </xsl:stylesheet> This is pretty much the starting point for most XSL files. You will notice the standard XML processing instruction at the top of the file (line 1). We then switch into XSL mode using the XSL namespace on all XSL elements (line 2). In this case, we have added namespaces for ATOM (line 4) and Dublin Core (line 5). This means the XSL can now read and understand those elements from the source XML. After we define all the namespaces, we then move onto the xsl:output element (line 6). This enables you to define the final method of output. Here we’re specifying html, but you could equally use XML or Text, for example. The encoding attributes on each element do what they say on the tin. As with all XML, of course, we close every element including the root. The next stage is to add a template, in this case an <xsl:template /> as can be seen below: <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"> <xsl:output method="html" encoding="utf-8"/> <xsl:template match="/"> <html> <head> <title>Making XML beautiful again : Transforming ATOM</title> </head> <body> <xsl:apply-templates select="/atom:feed"/> </body> </html> </xsl:template> </xsl:stylesheet> The beautiful thing about XSL is its English syntax, if you say it out loud it tends to make sense. The / value for the match attribute on line 8 is our first example of XPath syntax. The expression / matches any element – so this <xsl:template/> will match against any element in the document. As the first element in any XML document is the root element, this will be the one matched and processed first. Once we get past our standard start of a HTML document, the only instruction remaining in this <xsl:template/> is to look for and match all <atom:feed/> elements using the <xsl:apply-templates/> in line 14, above. <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"> <xsl:output method="html" encoding="utf-8"/> <xsl:template match="/"> <xsl:apply-templates select="/atom:feed"/> </xsl:template> <xsl:template match="/atom:feed"> <div id="content"> <h1> <xsl:value-of select="atom:title"/> </h1> <p> <xsl:value-of select="atom:subtitle"/> </p> <ul id="entries"> <xsl:apply-templates select="atom:entry"/> </ul> </div> </xsl:template> </xsl:stylesheet> This new template (line 12, above) matches <feed/> and starts to write the new HTML elements out to the output stream. The <xsl:value-of/> does exactly what you’d expect – it finds the value of the item specifed in its select attribute. With XPath you can select any element or attribute from the source XML. The last part is a repeat of the now familiar <xsl:apply-templates/> from before, but this time we’re using it inside of a called template. Yep, XSL is full of recursion… <xsl:template match="atom:entry"> <li class="entry"> <h2> <a href="{atom:link/@href}"> <xsl:value-of select="atom:title"/> </a> </h2> <p class="date"> (<xsl:value-of select="substring-before(atom:updated,'T')"/>) </p> <p class="content"> <xsl:value-of select="atom:content" disable-output-escaping="yes"/> </p> <xsl:apply-templates select="atom:category"/> </li> </xsl:template> The <xsl:template/> which matches atom:entry (line 1) occurs every time there is a <entry/> element in the source XML file. So in total that is 20 times, this is naturally why XSLT is full of recursion. This <xsl:template/> has been matched and therefore called higher up in the document, so we can start writing list elements directly to the output stream. The first part is simply a <h2/> with a link wrapped within it (lines 3-7). We can select attributes using XPath using @. The second part of this template selects the date, but performs a XPath string function on it. This means that we only get the date and not the time from the string (line 9). This is achieved by getting only the part of the string that exists before the T. Regular Expressions are not part of the XPath 1.0 string functions, although XPath 2.0 does include them. Because of this, in XSL we tend to rely heavily on the available XML output. The third part of the template (line 12) is a <xsl:value-of/> again, but this time we use an attribute of <xsl:value-of/> called disable output escaping to turn escaped characters back into XML. The very last section is another <xsl:apply-template/> call, taking us three templates deep. Do not worry, it is not uncommon to write XSL which go 20 or more templates deep! <xsl:template match="atom:category"> <xsl:for-each select="."> <xsl:element name="a"> <xsl:attribute name="rel"> <xsl:text>tag</xsl:text> </xsl:attribute> <xsl:attribute name="href"> <xsl:value-of select="concat(@scheme, @term)"/> </xsl:attribute> <xsl:value-of select="@term"/> </xsl:element> <xsl:text> </xsl:text> </xsl:for-each> </xsl:template> In our final <xsl:template/>, we see a combination of what we have done before with a couple of twists. Once we match atom:category we then count how many elements there are at that same level (line 2). The XPath . means ‘self’, so we count how many category elements are within the <entry/> element. Following that, we start to output a link with a rel attribute of the predefined text, tag (lines 4-6). In XSL you can just type text, but results can end up with strange whitespace if you do (although there are ways to simply remove all whitespace). The only new XPath function in this example is concat(), which simply combines what XPaths or text there might be in the brackets. We end the output for this tag with an actual tag name (line 10) and we add a space afterwards (line 12) so it won’t touch the next tag. (There are better ways to do this in XSL using the last() XPath function). After that, we go back to the <xsl:for-each/> element again if there is another category element, otherwise we end the <xsl:for-each/> loop and end this <xsl:template/>. A touch of style Because we’re using recursion through our templates, you will find this is the end of the templates and the rest of the XML will be ignored by the parser. Finally, we can add our CSS to finish up. (I have created one for Flickr and another for News feeds) <style type="text/css" media="screen">@import "flickr_overview.css?v=001";</style> So we end up with a nice simple to understand but also quick to write XSL which can be used on ATOM Flickr feeds and ATOM News feeds. With a little playing around with XSL, you can make XML beautiful again. All the files can be found in the zip file (14k) 2006 Ian Forrester ianforrester 2006-12-07T00:00:00+00:00 https://24ways.org/2006/beautiful-xml-with-xsl/ code
247 Managing Flow and Rhythm with CSS Custom Properties An important part of designing user interfaces is creating consistent vertical rhythm between elements. Creating consistent, predictable space doesn’t just make your web pages and views look better, but it can also improve the scan-ability. Browsers ship with default CSS and these styles often create consistent rhythm for flow elements out of the box. The problem is though that we often reset these styles with a reset. Elements such as <div> and <section> also have no default margin or padding associated with them. I’ve tried all sorts of weird and wonderful techniques to find a balance between using inherited CSS while also levelling the playing field for component driven front-ends with very little success. This experimentation is how I landed on the flow utility, though and I’m going to show you how it works. Let’s dive in! The Flow utility With the ever-growing number of folks working with component libraries and design systems, we could benefit from a utility that creates space for us, only when it’s appropriate to do so. The problem with my previous attempts at fixing this is that the spacing values were very rigid. That’s fine for 90% of contexts, but sometimes, it’s handy to be able to tweak the values based on the exact context of your component. This is where CSS Custom Properties come in handy. The code .flow { --flow-space: 1em; } .flow > * + * { margin-top: var(--flow-space); } What this code does is enable you to add a class of flow to an element which will then add margin-top to sibling elements within that element. We use the lobotomised owl selector to select these siblings. This approach enables an almost anonymous and automatic system which is ideal for component library based front-ends where components probably don’t have any idea what surrounds them. The other important part of this utility is the usage of the --flow-space custom property. We define it in the .flow component and each element within it will be spaced by --flow-space, by default. The beauty about setting this as a custom property is that custom properties also participate in the cascade, so we can utilise specificity to change it if we need it. Pretty cool, right? Let’s look at some examples. A basic example See the Pen CSS Flow Utility: Basic implementation by Andy Bell (@hankchizljaw) on CodePen. https://codepen.io/hankchizljaw/pen/LXqerj What we’ve got in this example is some basic HTML content that has a class of flow on the parent article element. Because there’s a very heavy-handed reset added as a dependency, all of the content would have been squished together without the flow utility. Because our --flow-space custom property is set to 1em, the space between elements is 1X the font size of the element in question. This means that a <h2> in this context has a calculated margin-top value of 28.8px, because it has an assigned font size of 1.8rem. If we were to globally change the --flow-space value to 1.1em for example, we’d affect everything because margin values would be calculated as 1.1X the font size. This example looks great because using font size as the basis of rhythm works really well. What if we wanted to to tweak certain elements within this article, though? See the Pen CSS Flow Utility: Tweaked Basic implementation by Andy Bell (@hankchizljaw) on CodePen. https://codepen.io/hankchizljaw/pen/qQgxaY I like lots of whitespace with my article layouts, so the 1em space isn’t going to cut it for all elements. I like to provide plenty of space between headed sections, so I increase the --flow-space in these instances: h2 { --flow-space: 3rem; } Notice also how I also switch over to using rem units? I want to make sure that these overrides are always based on the root font size. This is a personal preference of mine and you can use whatever units you want. Just be aware that it’s better for accessibility to use flexible units like em, rem and %, so that a user’s font size preferences are honoured. A more advanced example Although the flow utility is super useful for a plethora of contexts, it really shines when working with a few unrelated components. Instead of having to write specific layout CSS just for your particular context, you can use flow and --flow-space to create predictable and contextual space. See the Pen CSS Flow Utility: Unrelated components by Andy Bell (@hankchizljaw) on CodePen. https://codepen.io/hankchizljaw/pen/ZmPGyL In this example, we’ve got ourselves a little prototype layout that features a media element, followed by a grid of features. By using flow, it was really quick and easy to generate space between those two main elements. It was also easy to create space within the components. For example, I added it to the .media__content element, so that the article’s content would space itself: <article class="media__content flow"> ... </article> Something to remember though: the custom properties cascade in the same way that other CSS values do, so you’ve got to keep that in mind. We’ve got a great example of that in this example where because we’ve got the flow utility on our .features component, which has a --flow-space override: the child elements of .features will inherit that value, so we’ve had to set another value on the .features__list element. “But what about old browsers?”, I hear you cry We’re using CSS Custom Properties that at the time of writing, have about 88% support. One thing we can do to remedy the other 12% of browsers is to set a default, traditional margin-top value of 1em, so it calculates itself based on the element’s font-size: .flow { --flow-space: 1em; } .flow > * + * { margin-top: 1em; margin-top: var(--flow-space); } Thanks to the cascading and declarative nature of CSS, we can set that default margin-top value and then immediately set it to use the custom property instead. Browsers that understand Custom Properties will automatically apply them—those that don’t will ignore them. Yay for the cascade and progressive enhancement! Wrapping up This tiny little utility can bring great power for when you want to consistently space elements, vertically. It also—thanks to the power of the modern web—allows us to create contextual overrides without creating modifier classes or shame CSS. If you’ve got other methods of doing this sort of work, please let me know on Twitter. I’d love to see what you’re working on! 2018 Andy Bell andybell 2018-12-07T00:00:00+00:00 https://24ways.org/2018/managing-flow-and-rhythm-with-css-custom-properties/ code
5 Managing a Mind On 21 May 2013, I woke in a hospital bed feeling exhausted, disorientated and ashamed. The day before, I had tried to kill myself. It’s very hard to write about this and share it. It feels like I’m opening up the deepest recesses of my soul and laying everything bare, but I think it’s important we share this as a community. Since starting tentatively to write about my experience, I’ve had many conversations about this: sharing with others; others sharing with me. I’ve been surprised to discover how many people are suffering similarly, thinking that they’re alone. They’re not. Due to an insane schedule of teaching, writing, speaking, designing and just generally trying to keep up, I reached a point where my buffers completely overflowed. I was working so hard on so many things that I was struggling to maintain control. I was living life on fast-forward and my grasp on everything was slowly slipping. On that day, I reached a low point – the lowest point of my life – and in that moment I could see only one way out. I surrendered. I can’t really describe that moment. I’m still grappling with it. All I know is that I couldn’t take it any more and I gave up. I very nearly died. I’m very fortunate to have survived. I was admitted to hospital, taken there unconscious in an ambulance. On waking, I felt overwhelmed with shame and overcome with remorse, but I was resolved to grasp the situation and address it. The experience has forced me to confront a great deal of issues in my life; it has also encouraged me to seek a deeper understanding of my situation and, in particular, the mechanics of the mind. The relentless pace of change We work in a fast-paced industry: few others, if any, confront the daily challenges we face. The landscape we work within is characterised by constant flux. It’s changing and evolving at a rate we have never experienced before. Few industries reinvent themselves yearly, monthly, weekly… Ours is one of these industries. Technology accelerates at an alarming rate and keeping abreast of this change is challenging, to say the least. As designers it can be difficult to maintain a knowledge bank that is relevant and fit for purpose. We’re on a constant rollercoaster of endless learning, trying to maintain the pace as, daily, new ideas and innovations emerge — in some cases fundamentally changing our medium. Under the pressure of client work or product design and development, it can be difficult to find the time to focus on learning the new skills we need to remain relevant and functionally competent. The result, all too often, is that the edges of our days have eroded. We no longer work nine to five; instead we work eight to six, and after the working day is over we regroup to spend our evenings learning. It’s an unsustainable situation. From the workshop to the web Added to this pressure to keep up, our work is now undertaken under a global gaze, conducted under an ever-present spotlight. Tools like Dribbble, Twitter and others, while incredibly powerful, have an unfortunate side effect, that of unfolding your ideas in public. This shift, from workshop to web, brings with it additional pressure. In the past, the early stages of creativity took place within the relative safety of the workshop, an environment where one could take risks and gather feedback from a trusted few. We had space to make and space to break. No more. Our industry’s focus (and society’s focus) on sharing, leads us now to play out our decisions in public. This shift has changed us culturally, slowly but surely easing every aspect of our process – and lives – from private to public. This is at once liberating and debilitating. If you’re not careful, an addiction to followers, likes, retweets, page views and other forms of measurement can overwhelm you. When you release your work into the wild and all it’s greeted with is silence, it can cripple you. Reflecting on this, in an insightful article titled Derailed, Rogie King asks, “Can social popularity take us off the course of growth and where we were intended to go?” He makes a powerful point, that perhaps we might focus on what really matters, setting aside statistics. He concludes that to grow as practitioners we might be best served by seeking out critique through other avenues, away from the social spotlight. On status anxiety and impostor syndrome Following my experience I embarked on a period of self-reflection. I wanted to discover what had driven me to take the course of action I had. I wanted to ensure it never happened again. I wanted to understand how the mind works and, in so doing, learn a little more about myself. I’ve only begun this journey, but two things I discovered resonated with me: the twin pressures of status anxiety and impostor syndrome. In his excellent book Status Anxiety, the philosopher Alain de Botton explores a growing concern with status anxiety, a worry about how others perceive us and how this shapes our relationship with the world. He states: We all worry about what others think of us. We all long to succeed and fear failure. We all suffer – to a greater or lesser degree, usually privately and with embarrassment – from status anxiety. […] This is an almost universal anxiety that rarely gets mentioned directly: an anxiety about what others think of us; about whether we’re judged a success or a failure, a winner or a loser. We see these pressures played out and amplified in the social sphere we all inhabit. We are social animals and we cannot help but react to the landscape we live and work within. Even if your work receives the public praise you so secretly desire, you find yourself questioning this praise. A psychological phenomenon in which sufferers are unable to internalise their accomplishments, impostor syndrome is far more widespread than you’d imagine. The author Leigh Buchanan describes it as “A fear that one is not as smart or capable as others think.” As she puts it, “People who feel like frauds chalk up their accomplishments to external factors such as luck and timing, or worry they are coasting on charm and personality rather than on talent.” At the bottom, this was all I could see. I felt overwhelmed by others’ perception of me. Was I a success or a failure? Would I be discovered as the fraud I’d convinced myself that I was? These twin pressures – that I was unconscious of at the time – had lead me to a place of crippling self-doubt, questioning my very existence. The act of discovery, of investigating how the mind functions, led me to a deeper understanding of myself. Developing an awareness of psychology and learning about conditions like status anxiety and impostor syndrome helped me to understand and recognise how my mind worked, enabling me to manage it more effectively. Make it count Reflecting upon my experience, I began to regroup, to focus on what really mattered. I’d taken on too much — as I believe many of us do. I was guilty of wanting to do all the things. I started to introduce pauses. Before blindly saying yes to everything, I forced myself to pause and ask: “Is this important?” Our community offers us huge benefits, but an always-on culture in which we’re bombarded daily by opportunity places temptation in our paths. It’s easy to get sucked in to a vortex of wanting to be a part of everything. It’s important, however, to focus. As Simon Collison puts it: I cull and surrender topics. Then I focus on my strengths, mastering my core skills. We only have so much time and we can only do so much. It’s impossible, indeed futile, to try to do everything. Sometimes we need to step back a little and just enjoy life, enjoy others’ achievements, without feeling the need to be actively involved ourselves. As Mahatma Ghandi put it: A ‘no’ uttered from deepest conviction is better and greater than a ‘yes’ merely uttered to please, or what is worse, to avoid trouble. Young India, volume 9, 1927 We need to learn to say no a little more often. We need to focus on the work that matters. This, coupled with an understanding of the mind and how it works, can help us achieve a happier balance between work and life. Don’t waste your time. You only have one life. Make it count. 2013 Christopher Murphy christophermurphy 2013-12-21T00:00:00+00:00 https://24ways.org/2013/managing-a-mind/ process
143 Marking Up a Tag Cloud Everyone’s doing it. The problem is, everyone’s doing it wrong. Harsh words, you might think. But the crimes against decent markup are legion in this area. You see, I’m something of a markup and semantics junkie. So I’m going to analyse some of the more well-known tag clouds on the internet, explain what’s wrong, and then show you one way to do it better. del.icio.us I think the first ever tag cloud I saw was on del.icio.us. Here’s how they mark it up. <div class="alphacloud"> <a href="/tag/.net" class="lb s2">.net</a> <a href="/tag/advertising" class=" s3">advertising</a> <a href="/tag/ajax" class=" s5">ajax</a> ... </div> Unfortunately, that is one of the worst examples of tag cloud markup I have ever seen. The page states that a tag cloud is a list of tags where size reflects popularity. However, despite describing it in this way to the human readers, the page’s author hasn’t described it that way in the markup. It isn’t a list of tags, just a bunch of anchors in a <div>. This is also inaccessible because a screenreader will not pause between adjacent links, and in some configurations will not announce the individual links, but rather all of the tags will be read as just one link containing a whole bunch of words. Markup crime number one. Flickr Ah, Flickr. The darling photo sharing site of the internet, and the biggest blind spot in every standardista’s vision. Forgive it for having atrocious markup and sometimes confusing UI because it’s just so much damn fun to use. Let’s see what they do. <p id="TagCloud">  <a href="/photos/tags/06/" style="font-size: 14px;">06</a>   <a href="/photos/tags/africa/" style="font-size: 12px;">africa</a>   <a href="/photos/tags/amsterdam/" style="font-size: 14px;">amsterdam</a>  ... </p> Again we have a simple collection of anchors like del.icio.us, only this time in a paragraph. But rather than using a class to represent the size of the tag they use an inline style. An inline style using a pixel-based font size. That’s so far away from the goal of separating style from content, they might as well use a <font> tag. You could theoretically parse that to extract the information, but you have more work to guess what the pixel sizes represent. Markup crime number two (and extra jail time for using non-breaking spaces purely for visual spacing purposes.) Technorati Ah, now. Here, you’d expect something decent. After all, the Overlord of microformats and King of Semantics Tantek Çelik works there. Surely we’ll see something decent here? <ol class="heatmap"> <li><em><em><em><em><a href="/tag/Britney+Spears">Britney Spears</a></em></em></em></em></li> <li><em><em><em><em><em><em><em><em><em><a href="/tag/Bush">Bush</a></em></em></em></em></em></em></em></em></em></li> <li><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="/tag/Christmas">Christmas</a></em></em></em></em></em></em></em></em></em></em></em></em></em></li> ... <li><em><em><em><em><em><em><a href="/tag/SEO">SEO</a></em></em></em></em></em></em></li> <li><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="/tag/Shopping">Shopping</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></li> ... </ol> Unfortunately it turns out not to be that decent, and stop calling me Shirley. It’s not exactly terrible code. It does recognise that a tag cloud is a list of links. And, since they’re in alphabetical order, that it’s an ordered list of links. That’s nice. However … fifteen nested <em> tags? FIFTEEN? That’s emphasis for you. Yes, it is parse-able, but it’s also something of a strange way of looking at emphasis. The HTML spec states that <em> is emphasis, and <strong> is for stronger emphasis. Nesting <em> tags seems counter to the idea that different tags are used for different levels of emphasis. Plus, if you had a screen reader that stressed the voice for emphasis, what would it do? Shout at you? Markup crime number three. So what should it be? As del.icio.us tells us, a tag cloud is a list of tags where the size that they are rendered at contains extra information. However, by hiding the extra context purely within the CSS or the HTML tags used, you are denying that context to some users. The basic assumption being made is that all users will be able to see the difference between font sizes, and this is demonstrably false. A better way to code a tag cloud is to put the context of the cloud within the content, not the markup or CSS alone. As an example, I’m going to take some of my favourite flickr tags and put them into a cloud which communicates the relative frequency of each tag. To start with a tag cloud in its most basic form is just a list of links. I am going to present them in alphabetical order, so I’ll use an ordered list. Into each list item I add the number of photos I have with that particular tag. The tag itself is linked to the page on flickr which contains those photos. So we end up with this first example. To display this as a traditional tag cloud, we need to alter it in a few ways: The items need to be displayed next to each other, rather than one-per-line The context information should be hidden from display (but not from screen readers) The tag should link to the page of items with that tag Displaying the items next to each other simply means setting the display of the list elements to inline. The context can be hidden by wrapping it in a <span> and then using the off-left method to hide it. And the link just means adding an anchor (with rel="tag" for some extra microformats bonus points). So, now we have a simple collection of links in our second example. The last stage is to add the sizes. Since we already have context in our content, the size is purely for visual rendering, so we can just use classes to define the different sizes. For my example, I’ll use a range of class names from not-popular through ultra-popular, in order of smallest to largest, and then use CSS to define different font sizes. If you preferred, you could always use less verbose class names such as size1 through size6. Anyway, adding some classes and CSS gives us our final example, a semantic and more accessible tag cloud. 2006 Mark Norman Francis marknormanfrancis 2006-12-09T00:00:00+00:00 https://24ways.org/2006/marking-up-a-tag-cloud/ code
39 Meet for Learning “I’ve never worked in a place like this,” said one of my direct reports during our daily stand-up meeting. And with that statement, my mind raced to the most important thing about lawyering that I’ve learned from decades of watching lawyers lawyer on TV: don’t ask a question you don’t know the answer to. But I couldn’t stop myself. I wanted to learn more. The thought developed in my mind. The words formed in my mouth. And the vocalization occurred: “A place like this?” “I’ve never worked where people are so honest and transparent about things.” Designing a learning-centered culture Before we started Center Centre, Jared Spool and I discussed both the larger goals and the smaller details of this new UX design school. We talked about things like user experience, curriculum, and structure. We discussed the pattern we saw in our research. Hiring managers told us time and again that great designers have excellent technical and interpersonal skills. But, more importantly, the best designers are lifelong learners—they are willing and able to learn how to do new things. Learning this led us to ask a critical question: how would we intentionally design a learning-centered experience? To craft the experience we were aiming for, we knew we had to create a learning-centered culture for our students and our employees. We knew that our staff would need to model the behaviors our students needed to learn. We knew the best way to shape the culture was to work with our direct reports—our directs—to develop the behaviors we wanted them to exemplify. To craft the experience we were aiming for, we knew we had to create a learning-centered culture for our students and our employees. We knew that our staff would need to model the behaviors our students needed to learn. Building a learning team Our learning-centered culture starts with our staff. We believe in transparency. Transparency builds trust. Effective organizations have effective teams who trust each other as individuals. One huge way we build that trust and provide opportunities for transparency is in our meetings. (I know, I know—meetings! Yuck!) But seriously, running and participating in effective meetings is a great opportunity to build a learning-centered culture. Meetings—when done well—allow individuals time to come together, to share, and to listen. These behaviors, executed on a consistent and regular basis, build honest and trusting relationships. An effective meeting is one that achieves the desired outcomes of that meeting. While different meetings aim for different results, at Center Centre all meetings have a secondary goal: meet for learning. A framework for learning-centered meetings We’ve developed a framework for our meetings. We use it for all our meetings, which means attendees know what to expect. It also saves us from reinventing the wheel in each meeting. These basic steps help our meetings focus on the valuable face-to-face interaction we’re having, and help us truly begin to learn from one another. An agenda for a staff meeting. Use effective meeting basics Prepare for the meeting before the meeting. If you’re running the meeting, prepare a typed agenda and share it before the meeting. Agendas have start times for each item. Start the meeting on time. Don’t wait for stragglers. Define ground rules. Get input from attendees. Recurring meetings don’t have to do this every time. Keep to the meeting agenda. Put off-topic questions and ideas in a parking lot, a visual document that everyone can see, so you can address the questions and ideas later. Finish on time. And if you’ve reached the meeting’s goals, finish early. Parking lots where ideas on sticky notes can be posted for later consideration. Focus to learn Have tech-free meetings: no laptops, no phones, no things with notifications. Bring a notebook and a pen. Take notes by hand. You’re not taking minutes, you’re writing to learn. Come with a learning mindset Ask: what are our goals for this meeting? (Hopefully answered by the meeting agenda.) Ask: what can I learn overall? Ask: what can I learn from each of my colleagues? Ask: what can I share that will help the team learn overall? Ask: what can I share that will help each of my colleagues learn? Investing in regularly scheduled learning-centered meetings At Center Centre, we have two types of recurring all-staff meetings: daily stand-ups and weekly staff meetings. (We are a small organization, so it makes sense to meet as an entire group.) Yes, that means we spend thirty minutes each day in stand-up, for a total of two and a half hours of stand-up meeting time each week. And, yes, we also have a weekly ninety-minute sit-down staff meeting on top of that. This investment in time is an investment in learning. We use these meetings to build our transparency, and, therefore, our trust. The regularity of these meetings helps us maintain ongoing, open sharing about our responsibilities, our successes, and our learning. For instance, we answer five questions in our stand-up: What did I get done since the last stand-up (I reported at)? What is my goal to accomplish before the next stand-up? What’s preventing me from getting these things done, if anything? What’s the highest risk or most unknown thing right now about what I’m trying to get done? What is the most important thing I learned since the last time we met and how will what I learned change the way I approach things in the future? Each person writes out their answers to these questions before the meeting. Each person brings their answers printed on paper to the meeting. And each person brings a pen to jot down notes. Notes compiled for a stand-up meeting. During the stand-up, each person shares their answers to the five questions. To sustain a learning-centered culture, the fifth question is the most important question to answer. It allows individual reflection focused on learning. Sometimes this isn’t an easy question to answer. It makes us stretch. It makes us think. By sharing our individual answers to the fifth question, we open ourselves up to the group. When we honestly share what we’ve learned, we openly admit that we didn’t know something. Sharing like this would be scary (and even risky) if we didn’t have a learning-centered culture. We often share the actual process of how we learned something. By listening, each of us is invited to learn more about the topic at hand, consider what more there is to learn about that topic, and even gain insights into other methods of learning—which can be applied to other topics. Sharing the answers to the fifth question also allows opportunities for further conversations. We often take what someone has individually learned and find ways to apply it for our entire team in support of our organization. We are, after all, learning together. Building individual learners We strive to grow together as a team at Center Centre, but we don’t lose sight of the importance of the individuals who form our team. As individuals, we bring our goals, dreams, abilities, and prior knowledge to the team. To build learning teams, we must build individual learners. A team made up of lifelong learners, who share their learning and learn from each other, is a team that will continually produce better results. As a manager, I need to meet each direct where they are with their current abilities and knowledge. Then, I can help them take their skills and knowledge base to the next levels. This process requires each individual direct to engage in professional development. We believe effective managers help their directs engage in behaviors that support growth and development. Effective managers encourage and support learning. Our weekly one-on-ones One way we encourage learning is through weekly one-on-ones. Each of my directs meets with me, individually, for thirty minutes each week. The meeting is their meeting. It is not my meeting. My direct sets the agenda. They talk about what they want to talk about. They can talk about work. They can talk about things outside of work. They can talk about their health, their kids, and even their cat. Whatever is important to them is important to me. I listen. I take notes. Although the direct sets the specific agenda, the meeting has three main parts. Approximately ten minutes for them (the direct), ten minutes for me (the manager), and ten minutes for us to talk about their future within—and beyond—our organization. Coaching for future performance The final third of our one-on-one is when I coach my directs. Coaching looks to the direct’s future performance. It focuses on developing the direct’s skills. Coaching isn’t hard. It doesn’t take much time. For me, it usually takes less than five minutes a week during a one-on-one. The first time I coach one of my directs, I ask them to brainstorm about the skills they want to improve. They usually already have an idea about this. It’s often something they’ve wanted to work on for some time, but didn’t think they had the time or the knowhow to improve. If a direct doesn’t know what they want to improve, we discuss their job responsibilities—specifically the aspects of the job that concern them. Coaching provides an opportunity for me to ask, “In your job, what are the required skills that you feel like you don’t have (or know well enough, or perform effectively, or use with ease)?” Sometimes I have to remind a direct that it’s okay not to know how to do something (even if it’s a required part of their job). After all, our organization is a learning organization. In a learning organization, no one knows everything but everyone is willing to learn anything. After we review the job responsibilities together, I ask my direct what skill they’d like to work to improve. Whatever they choose, we focus on that skill for coaching—I’ve found my directs work better when they’re internally motivated. Sometimes the first time I talk with a direct about coaching, they get a bit anxious. If this happens, I share a personal story about my professional learning journey. I say something like: I didn’t know how to make a school before we started to make Center Centre. I didn’t know how to manage an entire team of people—day in and day out—until I started managing a team of people every day. When I realized that I was the boss—and that the success of the school would hinge, at least in part, on my skills as a manager—I was a bit terrified. I was missing an important skill set that I needed to know (and I needed to know well). When I first understood this, I felt bad—like I should have already known how to be a great manager. But then I realized, I’d never faced this situation. I’d never needed to know how to use this skill set in this way. I worked through my anxiety about feeling inadequate. I decided I’d better learn how to be an effective manager because the school needed me to be one. You needed me to be one. Every day, I work to improve my management skills. You’ve probably noticed that some days I’m better at it than others. I try not to beat myself up about this, although it’s hard—I’d like to be perfect at it. But I’m not. I know that if I make a conscious, daily effort to learn how to be a better manager, I’ll continue to improve. So that’s what I do. Every day I learn. I learn by doing. I learn how to be better than I was the day before. That’s what I ask of you. Once we determine the skill the direct wants to learn, we figure out how they can go about learning it. I ask: “How could you learn this skill?” We brainstorm for two or three minutes about this. We write down every idea that comes to mind, and we write it so both of us can easily see the options (both whiteboards and sticky notes on the wall work well for this exercise). Read a book. Research online. Watch a virtual seminar. Listen to a podcast. Talk to a mentor. Reach out to an expert. Attend a conference. Shadow someone else while they do the skill. Join a professional organization. The goal is to get the direct on a path of self-development. I’m coaching their development, but I’m not the main way my direct will learn this new skill. I ask my direct which path seems like the best place to start. I let them choose whatever option they want (as long as it works with our budget). They are more likely to follow through if they are in control of this process. Next, we work to break down the selected path into tasks. We only plan one week’s worth of tasks. The tasks are small, and the deadlines are short. My direct reports when each task is completed. At our next one-on-one, I ask my direct about their experience learning this new skill. Rinse. Repeat. That’s it. I spend five minutes a week talking with each direct about their individual learning. They develop their professional skills, and together we’re creating a learning-centered culture. Asking questions I don’t know the answer to When my direct said, “I’ve never worked where people are so honest and transparent about things,” it led me to believe that all this is working. We are building a learning-centered culture. This week I was reminded that creating a learning-centered culture starts not just with the staff, but with me. When I challenge myself to learn and then share what I’m currently learning, my directs want to learn more about what I’m learning about. For example, I decided I needed to improve my writing skills. A few weeks ago, I realized that I was sorely out of practice and I felt like I had lost my voice. So I started to write. I put words on paper. I felt overwhelmed. I felt like I didn’t know how to write anymore (at least not well or effectively). I bought some books on writing (mostly Peter Elbow’s books like Writing with Power, Writing Without Teachers, and Vernacular Eloquence), and I read them. I read them all. Reading these books was part of my personal coaching. I used the same steps to coach myself as I use with my directs when I coach them. In stand-ups, I started sharing what I accomplished (like I completed one of the books) and what I learned by doing—specific things, like engaging in freewriting and an open-ended writing process. This week, I went to lunch with one of my directs. She said, “You’ve been talking about freewriting a lot. You’re really excited about it. Freewriting seems like it’s helping your writing process. Would you tell me more about it?” So I shared the details with her. I shared the reasons why I think freewriting is helping. I’m not focused on perfection. Instead, each day I’m focused on spending ten, uninterrupted minutes writing down whatever comes to my mind. It’s opening my writing mind. It’s allowing my words to flow more freely. And it’s helping me feel less self-conscious about my writing. She said, “Leslie, when you say you’re self-conscious about your writing, I laugh. Not because it’s funny. But because when I read what you write, I think, ‘What is there to improve?’ I think you’re a great writer. It’s interesting to know that you think you can be a better writer. I like learning about your learning process. I think I could do freewriting. I’m going to give it a try.” There’s something magical about all of this. I’m not even sure I can eloquently put it into words. I just know that our working environment is something very different. I’ve never experienced anything quite like it. Somehow, by sharing that I don’t know everything and that I’m always working to learn more, I invite my directs to be really open about what they don’t know. And they see it’s possible always to learn and grow. I’m glad I ignore all the lawyering I’ve learned from watching TV. I’m glad I ask the questions I don’t know the answers to. And I’m glad my directs do the same. When we meet for learning, we accelerate and amplify the learning process—building individual learners and learning teams. Embracing the unknown and working toward understanding is what makes our culture a learning-centered culture. Photos by Summer Kohlhorst. 2014 Leslie Jensen-Inman lesliejenseninman 2014-12-20T00:00:00+00:00 https://24ways.org/2014/meet-for-learning/ process
155 Minification: A Christmas Diet The festive season is generally more about gorging ourselves than staying thin but we’re going to change all that with a quick introduction to minification. Performance has been a hot topic this last year. We’re building more complex sites and applications but at the same time trying to make then load faster and behave more responsively. What is a discerning web developer to do? Minification is the process of make something smaller, in the case of web site performance we’re talking about reducing the size of files we send to the browser. The primary front-end components of any website are HTML, CSS, Javascript and a sprinkling of images. Let’s find some tools to trim the fat and speed up our sites. For those that want to play along at home you can download the various utilities for Mac or Windows. You’ll want to be familiar with running apps on the command line too. HTMLTidy HTMLTidy optimises and strips white space from HTML documents. It also has a pretty good go at correcting any invalid markup while it’s at it. tidy -m page.html CSSTidy CSSTidy takes your CSS file, optimises individual rules (for instance transforming padding-top: 10px; padding-bottom: 10px; to padding: 10px 0;) and strips unneeded white space. csstidy style.css style-min.css JSMin JSMin takes your javascript and makes it more compact. With more and more websites using javascript to power (progressive) enhancements this can be a real bandwidth hog. Look out for pre-minified versions of libraries and frameworks too. jsmin <script.js >script-min.js Remember to run JSLint before you run JSMin to catch some common problems. OptiPNG Images can be a real bandwidth hog and making all of them smaller with OptiPNG should speed up your site. optipng image.png All of these tools have an often bewildering array of options and generally good documentation included as part of the package. A little experimentation will get you even more bang for your buck. For larger projects you likely won’t want to be manually minifying all your files. The best approach here is to integrate these tools into your build process and have your live website come out the other side smaller than it went in. You can also do things on the server to speed things up; GZIP compression for instance or compilation of resources to reduce the number of HTTP requests. If you’re interested in performance a good starting point is the Exceptional Performance section on the Yahoo Developer Network and remember to install the YSlow Firebug extension while you’re at it. 2007 Gareth Rushgrove garethrushgrove 2007-12-06T00:00:00+00:00 https://24ways.org/2007/minification-a-christmas-diet/ process
258 Mistletoe Offline It’s that time of year, when we gather together as families to celebrate the life of the greatest person in history. This man walked the Earth long before us, but he left behind words of wisdom. Those words can guide us every single day, but they are at the forefront of our minds during this special season. I am, of course, talking about Murphy, and the golden rule he gave unto us: Anything that can go wrong will go wrong. So true! I mean, that’s why we make sure we’ve got nice 404 pages. It’s not that we want people to ever get served a File Not Found message, but we acknowledge that, despite our best efforts, it’s bound to happen sometime. Murphy’s Law, innit? But there are some Murphyesque situations where even your lovingly crafted 404 page won’t help. What if your web server is down? What if someone is trying to reach your site but they lose their internet connection? These are all things than can—and will—go wrong. I guess there’s nothing we can do about those particular situations, right? Wrong! A service worker is a Murphy-battling technology that you can inject into a visitor’s device from your website. Once it’s installed, it can intercept any requests made to your domain. If anything goes wrong with a request—as is inevitable—you can provide instructions for the browser. That’s your opportunity to turn those server outage frowns upside down. Take those network connection lemons and make network connection lemonade. If you’ve got a custom 404 page, why not make a custom offline page too? Get your server in order Step one is to make …actually, wait. There’s a step before that. Step zero. Get your site running on HTTPS, if it isn’t already. You won’t be able to use a service worker unless everything’s being served over HTTPS, which makes sense when you consider the awesome power that a service worker wields. If you’re developing locally, service workers will work fine for localhost, even without HTTPS. But for a live site, HTTPS is a must. Make an offline page Alright, assuming your site is being served over HTTPS, then step one is to create an offline page. Make it as serious or as quirky as is appropriate for your particular brand. If the website is for a restaurant, maybe you could put the telephone number and address of the restaurant on the custom offline page (unsolicited advice: you could also put this on the home page, you know). Here’s an example of the custom offline page for this year’s Ampersand conference. When you’re done, publish the offline page at suitably imaginative URL, like, say /offline.html. Pre-cache your offline page Now create a JavaScript file called serviceworker.js. This is the script that the browser will look to when certain events are triggered. The first event to handle is what to do when the service worker is installed on the user’s device. When that happens, an event called install is fired. You can listen out for this event using addEventListener: addEventListener('install', installEvent => { // put your instructions here. }); // end addEventListener In this case, you want to make sure that your lovingly crafted custom offline page is put into a nice safe cache. You can use the Cache API to do this. You get to create as many caches as you like, and you can call them whatever you want. Here, I’m going to call the cache Johnny just so I can refer to it as JohnnyCache in the code: addEventListener('install', installEvent => { installEvent.waitUntil( caches.open('Johnny') .then( JohnnyCache => { JohnnyCache.addAll([ '/offline.html' ]); // end addAll }) // end open.then ); // end waitUntil }); // end addEventListener I’m betting that your lovely offline page is linking to a CSS file, maybe an image or two, and perhaps some JavaScript. You can cache all of those at this point: addEventListener('install', installEvent => { installEvent.waitUntil( caches.open('Johnny') .then( JohnnyCache => { JohnnyCache.addAll([ '/offline.html', '/path/to/stylesheet.css', '/path/to/javascript.js', '/path/to/image.jpg' ]); // end addAll }) // end open.then ); // end waitUntil }); // end addEventListener Make sure that the URLs are correct. If just one of the URLs in the list fails to resolve, none of the items in the list will be cached. Intercept requests The next event you want to listen for is the fetch event. This is probably the most powerful—and, let’s be honest, the creepiest—feature of a service worker. Once it has been installed, the service worker lurks on the user’s device, waiting for any requests made to your site. Every time the user requests a web page from your site, a fetch event will fire. Every time that page requests a style sheet or an image, a fetch event will fire. You can provide instructions for what should happen each time: addEventListener('fetch', fetchEvent => { // What happens next is up to you! }); // end addEventListener Let’s write a fairly conservative script with the following logic: Whenever a file is requested, First, try to fetch it from the network, But if that doesn’t work, try to find it in the cache, But if that doesn’t work, and it’s a request for a web page, show the custom offline page instead. Here’s how that translates into JavaScript: // Whenever a file is requested addEventListener('fetch', fetchEvent => { const request = fetchEvent.request; fetchEvent.respondWith( // First, try to fetch it from the network fetch(request) .then( responseFromFetch => { return responseFromFetch; }) // end fetch.then // But if that doesn't work .catch( fetchError => { // try to find it in the cache caches.match(request) .then( responseFromCache => { if (responseFromCache) { return responseFromCache; // But if that doesn't work } else { // and it's a request for a web page if (request.headers.get('Accept').includes('text/html')) { // show the custom offline page instead return caches.match('/offline.html'); } // end if } // end if/else }) // end match.then }) // end fetch.catch ); // end respondWith }); // end addEventListener I am fully aware that I may have done some owl-drawing there. If you need a more detailed breakdown of what’s happening at each point in the code, I’ve written a whole book for you. It’s the perfect present for Murphymas. Hook up your service worker script You can publish your service worker script at /serviceworker.js but you still need to tell the browser where to look for it. You can do that using JavaScript. Put this in an existing JavaScript file that you’re calling in to every page on your site, or add this in a script element at the end of every page’s HTML: if (navigator.serviceWorker) { navigator.serviceWorker.register('/serviceworker.js'); } That tells the browser to start installing the service worker, but not without first checking that the browser understands what a service worker is. When it comes to JavaScript, feature detection is your friend. You might already have some JavaScript files in a folder like /assets/js/ and you might be tempted to put your service worker script in there too. Don’t do that. If you do, the service worker will only be able to handle requests made to for files within /assets/js/. By putting the service worker script in the root directory, you’re making sure that every request can be intercepted. Go further! Nicely done! You’ve made sure that if—no, when—a visitor can’t reach your website, they’ll get your hand-tailored offline page. You have temporarily defeated the forces of chaos! You have briefly fought the tide of entropy! You have made a small but ultimately futile gesture against the inevitable heat-death of the universe! This is just the beginning. You can do more with service workers. What if, every time you fetched a page from the network, you stored a copy of that page in a cache? Then if that person tries to reach that page later, but they’re offline, you could show them the cached version. Or, what if instead of reaching out the network first, you checked to see if a file is in the cache first? You could serve up that cached version—which would be blazingly fast—and still fetch a fresh version from the network in the background to pop in the cache for next time. That might be a good strategy for images. So many options! The hard part isn’t writing the code, it’s figuring out the steps you want to take. Once you’ve got those steps written out, then it’s a matter of translating them into JavaScript. Inevitably there will be some obstacles along the way—usually it’s a misplaced curly brace or a missing parenthesis. Don’t be too hard on yourself if your code doesn’t work at first. That’s just Murphy’s Law in action. 2018 Jeremy Keith jeremykeith 2018-12-04T00:00:00+00:00 https://24ways.org/2018/mistletoe-offline/ code
156 Mobile 2.0 Thinking 2.0 As web geeks, we have a thick skin towards jargon. We all know that “Web 2.0” has been done to death. At Blue Flavor we even have a jargon bucket to penalize those who utter such painfully overused jargon with a cash deposit. But Web 2.0 is a term that has lodged itself into the conscience of the masses. This is actually a good thing. The 2.0 suffix was able to succinctly summarize all that was wrong with the Web during the dot-com era as well as the next evolution of an evolving media. While the core technologies actually stayed basically the same, the principles, concepts, interactions and contexts were radically different. With that in mind, this Christmas I want to introduce to you the concept of Mobile 2.0. While not exactly a new concept in the mobile community, it is relatively unknown in the web community. And since the foundation of Mobile 2.0 is the web, I figured it was about time for you to get to know each other. It’s the Carriers’ world. We just live in it. Before getting into Mobile 2.0, I thought first I should introduce you to its older brother. You know the kind, the kid with emotional problems that likes to beat up on you and your friends for absolutely no reason. That is the mobile of today. The mobile ecosystem is a very complicated space often and incorrectly compared to the Web. If the Web was a freewheeling hippie — believing in freedom of information and the unity of man through communities — then Mobile is the cutthroat capitalist — out to pillage and plunder for the sake of the almighty dollar. Where the Web is relatively easy to publish to and ultimately make a buck, Mobile is wrought with layers of complexity, politics and obstacles. I can think of no better way to summarize these challenges than the testimony of Jason Devitt to the United States Congress in what is now being referred to as the “iPhone Hearing.” Jason is the co-founder and CEO of SkyDeck a new wireless startup and former CEO of Vindigo an early pioneer in mobile content. As Jason points out, the mobile ecosystem is a closed door environment controlled by the carriers, forcing the independent publisher to compete or succumb to the will of corporate behemoths. But that is all about to change. Introducing Mobile 2.0 Mobile 2.0 is term used by the mobile community to describe the current revolution happening in mobile. It describes the convergence of mobile and web services, adding portability, ubiquitous connectivity and location-aware services to add physical context to information found on the Web. It’s an important term that looks toward the future. Allowing us to imagine the possibilities that mobile technology has long promised but has yet to deliver. It imagines a world where developers can publish mobile content without the current constraints of the mobile ecosystem. Like the transition from Web 1.0 to 2.0, it signifies the shift away from corporate or brand-centered experiences to user-centered experiences. A focus on richer interactions, driven by user goals. Moving away from proprietary technologies to more open and standard ones, more akin to the Web. And most importantly (from our perspective as web geeks) a shift away from kludgy one-off mobile applications toward using the Web as a platform for content and services. This means the world of the Web and the world of Mobile are coming together faster than you can say ARPU (Average Revenue Per User, a staple mobile term to you webbies). And this couldn’t come at a better time. The importance of understanding and addressing user context is quickly becoming a crucial consideration to every interactive experience as the number of ways we access information on the Web increases. Mobile enables the power of the Web, the collective information of millions of people, inherit payment channels and access to just about every other mass media to literally be overlaid on top of the physical world, in context to the person viewing it. Anyone who can’t imagine how the influence of mobile technology can’t transform how we perform even the simplest of daily tasks needs to get away from their desktop and see the new evolution of information. The Instigators But what will make Mobile 2.0 move from idillic concept to a hardened market reality in 2008 will be four key technologies. Its my guess that you know each them already. 1. Opera Opera is like the little train that could. They have been a driving force on moving the Web as we know it on to mobile handsets. Opera technology has proven itself to be highly adaptable, finding itself preloaded on over 40 million handsets, available on televisions sets through Nintendo Wii or via the Nintendo DS. 2. WebKit Many were surprised when Apple chose to use KHTML instead of Gecko (the guts of Firefox) to power their Safari rendering engine. But WebKit has quickly evolved to be a powerful and flexible browser in the mobile context. WebKit has been in Nokia smartphones for a few years now, is the technology behind Mobile Safari in the iPhone and the iPod Touch and is the default web technology in Google’s open mobile platform effort, Android. 3. The iPhone The iPhone has finally brought the concepts and principles of Mobile 2.0 into the forefront of consumers minds and therefore developers’ minds as well. Over 500 web applications have been written specifically for the iPhone since its launch. It’s completely unheard of to see so many applications built for the mobile context in such a short period of time. 4. CSS & Javascript Web 2.0 could not exist without the rich interactions offered by CSS and Javascript, and Mobile 2.0 is no different. CSS and Javascript support across multiple phones historically has been, well… to put it positively… utter crap. Javascript finally allows developers to create interesting interactions that support user goals and the mobile context. Specially, AJAX allows us to finally shed the days of bloated Java applications and focus on portable and flexible web applications. While CSS — namely CSS3 — allows us to create designs that are as beautiful as they are economical with bandwidth and load times. With Leaflets, a collection of iPhone optimized web apps we created, we heavily relied on CSS3 to cache and reuse design elements over and over, minimizing download times while providing an elegant and user-centered design. In Conclusion It is the combination of all these instigators that is significantly decreasing the bar to mobile publishing. The market as Jason Devitt describes it, will begin to fade into the background. And maybe the world of mobile will finally start looking more like the Web that we all know and love. So after the merriment and celebration of the holiday is over and you look toward the new year to refresh and renew, I hope that you take a seriously consider the mobile medium. By this time next year, it is predicted that one-third of humanity will be using mobile devices to access the Web. 2007 Brian Fling brianfling 2007-12-21T00:00:00+00:00 https://24ways.org/2007/mobile-2-0/ business
90 Monkey Business “Too expensive.” “Over-priced.” “A bit rich.” They all mean the same thing. When you say that something’s too expensive, you’re doing much more than commenting on a price. You’re questioning the explicit or implicit value of a product or a service. You’re asking, “Will I get out of it what you want me to pay for it?” You’re questioning the competency, judgement and possibly even integrity of the individual or company that gave you that price, even though you don’t realise it. You might not be saying it explicitly, but what you’re implying is, “Have you made a mistake?”, “Am I getting the best deal?”, “Are you being honest with me?”, “Could I get this cheaper?” Finally, you’re being dishonest, because deep down you know all too well that there’s no such thing as too expensive. Why? It doesn’t matter what you’re questioning the price of. It could be a product, a service or the cost of an hour, day or week of someone’s time. Whatever you’re buying, too expensive is always an excuse. Saying it shifts acceptability of a price back to the person who gave it. What you should say, but are too afraid to admit, is: “It’s more money than I wanted to pay.” “It’s more than I estimated it would cost.” “It’s more than I can afford.” Everyone who’s given a price for a product or service will have been told at some point that it’s too expensive. It’s never comfortable to hear that. Thoughts come thick and fast: “What do I do?” “How do I react?” “Do I really want the business?” “Am I prepared to negotiate?” “How much am I willing to compromise?” It’s easy to be defensive when someone questions a price, but before you react, stay calm and remember that if someone says what you’re offering is too expensive, they’re saying more about themselves and their situation than they are about your price. Learn to read that situation and how to follow up with the right questions. Imagine you’ve quoted someone for a week of your time. “That’s too expensive,” they respond. How should you handle that? Think about what they might otherwise be saying. “It’s more money than I want to pay” may mean that they don’t understand the value of your service. How could you respond? Start by asking what similar projects they’ve worked on and the type of people they worked with. Find out what they paid and what they got for their money, because it’s possible what you offer is different from what they had before. Ask if they saw a return on that previous investment. Maybe their problem isn’t with your headline price, but the value they think they’ll receive. Put the emphasis on value and shift the conversation to what they’ll gain, rather than what they’ll spend. It’s also possible they can’t distinguish your service from those of your competitors, so now would be a great time to explain the differences. Do you work faster? Explain how that could help them launch faster, get customers faster, make money faster. Do you include more? Emphasise that, and how unique the experience of working with you will be. “It’s more than I estimated it would cost” could mean that your customer hasn’t done their research properly. You’d never suggest that to them, of course, but you should ask how they’ve arrived at their estimate. Did they base it on work they’ve purchased previously? How long ago was that? Does it come from comparable work or from a different sector? Help your customer by explaining how you arrived at your estimate. Break down each element and while you’re doing that, emphasise the parts of your process that you know will appeal to them. If you know that they’ve had difficulty with something in the past, explain how your approach will benefit them. People almost always value a positive experience more than the money they’ll save. “It’s more than I can afford” could mean they can’t afford what you offer at all, but it could also mean they can’t afford it right now or all at once. So ask if they could afford what you’re asking if they spread payment over a longer period? Ask, “Would that mean you’ll give me the business?” It’s possible they’re asking for too much for what they can afford to pay. Will they compromise? Can you reach an agreement on something less? Ask, “If we can agree what’s in and what’s out, will you give me the business?” What can they afford? When you know, you’re in a good position to decide if the deal makes good business sense, for both of you. Ask, “If I can match that price, will you give me the business?” There’s no such thing as “a bit rich”, only ways for you to get to know your customer better. There’s no such thing as “over-priced”, only opportunities for you to explain yourself better. You should relish those opportunities. There’s really also no such thing as “too expensive”, just ways to set the tone for your relationship and help you develop that relationship to a point where money will be less of a deciding factor. Unfinished Business Join me and my co-host Anna Debenham next year for Unfinished Business, a new discussion show about the business end of working in web, design and creative industries. 2012 Andy Clarke andyclarke 2012-12-23T00:00:00+00:00 https://24ways.org/2012/monkey-business/ business
100 Moo'y Christmas A note from the editors: Moo has changed their API since this article was written. As the web matures, it is less and less just about the virtual world. It is becoming entangled with our world and it is harder to tell what is virtual and what is real. There are several companies who are blurring this line and make the virtual just an extension of the physical. Moo is one such company. Moo offers simple print on demand services. You can print business cards, moo mini cards, stickers, postcards and more. They give you the ability to upload your images, customize them, then have them sent to your door. Many companies allow this sort of digital to physical interaction, but Moo has taken it one step further and has built an API. Printable stocking stuffers The Moo API consists of a simple XML file that is sent to their servers. It describes all the information needed to dynamically assemble and print your object. This is very helpful, not just for when you want to print your own stickers, but when you want to offer them to your customers, friends, organization or community with no hassle. Moo handles the check-out and shipping, all you need to do is what you do best, create! Now using an API sounds complicated, but it is actually very easy. I am going to walk you through the options so you can easily be printing in no time. Before you can begin sending data to the Moo API, you need to register and get an API key. This is important, because it allows Moo to track usage and to credit you. To register, visit http://www.moo.com/api/ and click “Request an API key”. In the following examples, I will use {YOUR API KEY HERE} as a place holder, replace that with your API key and everything will work fine. First thing you need to do is to create an XML file to describe the check-out basket. Open any text-editor and start with some XML basics. Don’t worry, this is pretty simple and Moo gives you a few tools to check your XML for errors before you order. <?xml version="1.0" encoding="UTF-8"?> <moo xsi:noNamespaceSchemaLocation="http://www.moo.com/xsd/api_0.7.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <request> <version>0.7</version> <api_key>{YOUR API KEY HERE}</api_key> <call>build</call> <return_to>http://www.example.com/return.html</return_to> <fail_to>http://www.example.com/fail.html</fail_to> </request> <payload> ... </payload> </moo> Much like HTML’s <head> and <body>, Moo has created <request> and <payload> elements all wrapped in a <moo> element. The <request> element contains a few pieces of information that is the same across all the API calls. The <version> element describes which version of the API is being used. This is more important for Moo than for you, so just stick with “0.7” for now. The <api_key> allows Moo to track sales, referrers and credit your account. The <call> element can only take “build” so that is pretty straight forward. The <return_to> and <fail_to> elements are URLs. These are optional and are the URLs the customer is redirected to if there is an error, or when the check out process is complete. This allows for some basic branding and a custom “thank you” page which is under your control. That’s it for the <request> element, pretty easy so far! Next up is the <payload> element. What goes inside here describes what is to be printed. There are two possible elements, we can put <chooser> or we can put <products> directly inside <payload>. They work in a similar ways, but they drop the customer into different parts of the Moo checkout process. If you specify <products> then you send the customer straight to the Moo payment process. If you specify <chooser> then you send the customer one-step earlier where they are allowed to pick and choose some images, remove the ones they don’t like, adjust the crop, etc. The example here will use <chooser> but with a little bit of homework you can easily adjust to <products> if you desire. ... <chooser> <product_type>sticker</product_type> <images> <url>http://example.com/images/christmas1.jpg</url> </images> </chooser> ... Inside the <chooser> element, we can see there are two basic piece of information. The type of product we want to print, and the images that are to be printed. The <product_type> element can take one of five options and is required! The possibilities are: minicard, notecard, sticker, postcard or greetingcard. We’ll now look at two of these more closely. Moo Stickers In the Moo sticker books you get 90 small squarish stickers in a small little booklet. The simplest XML you could send would be something like the following payload: ... <payload> <chooser> <product_type>sticker</product_type> <images> <url>http://example.com/image1.jpg</url> </images> <images> <url>http://example.com/image2.jpg</url> </images> <images> <url>http://example.com/image3.jpg</url> </images> </chooser> </payload> ... This creates a sticker book with only 3 unique images, but 30 copies of each image. The Sticker books always print 90 stickers in multiples of the images you uploaded. That example only has 3 <images> elements, but you can easily duplicate the XML and send up to 90. The <url> should be the full path to your image and the image needs to be a minimum of 300 pixels by 300 pixels. You can add more XML to describe cropping, but the simplest option is to either, let your customers choose or to pre-crop all your images square so there are no issues. The full XML you would post to the Moo API to print sticker books would look like this: <?xml version="1.0" encoding="UTF-8"?> <moo xsi:noNamespaceSchemaLocation="http://www.moo.com/xsd/api_0.7.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <request> <version>0.7</version> <api_key>{YOUR API KEY HERE}</api_key> <call>build</call> <return_to>http://www.example.com/return.html</return_to> <fail_to>http://www.example.com/fail.html</fail_to> </request> <payload> <chooser> <product_type>sticker</product_type> <images> <url>http://example.com/image1.jpg</url> </images> <images> <url>http://example.com/image2.jpg</url> </images> <images> <url>http://example.com/image3.jpg</url> </images> </chooser> </payload> </moo> Mini-cards The mini-cards are the small cute business cards in 14×35 dimensions and come in packs of 100. Since the mini-cards are print on demand, this allows you to have 100 unique images on the back of the cards. Just like the stickers example, we need the same XML setup. The <moo> element and <request> elements will be the same as before. The part you will focus on is the <payload> section. Since you are sending along specific information, we can’t use the <chooser> option any more. Switch this to <products> which has a child of <product>, which in turn has a <product_type> and <designs>. This might seem like a lot of work, but once you have it set up you won’t need to change it. ... <payload> <products> <product> <product_type>minicard</product_type> <designs> ... </designs> </product> </products> </payload> ... So now that we have the basic framework, we can talk about the information specific to minicards. Inside the <designs> element, you will have one <design> for each card. Much like before, this contains a way to describe the image. Note that this time the element is called <image>, not images plural. Inside the <image> element you have a <url> which points to where the image lives and a <type>. The <type> should just be set to ‘variable’. You can pass crop information here instead, but we’re going to keep it simple for this tutorial. If you are interested in how that works, you should refer to the official API documentation. ... <design> <image> <url>http://example.com/image1.jpg</url> <type>variable</type> </image> </design> ... So far, we have managed to build a pack of 100 Moo mini-cards with the same image on the front. If you wanted 100 different images, you just need to replicate this snippit, 99 more times. That describes the front design, but the flip-side of your mini-cards can contain 6 lines of text, which is customizable in a variety of colors, fonts and styles. The API allows you to create different text on the back of each mini-card, something the web interface doesn’t implement. To describe the text on the mini-card we need to add a <text_collection> element inside the <design> element. If you skip this element, the back of your mini-card will just be blank, but that’s not very festive! Inside the <text_collection> element, we need to describe the type of text we want to format, so we add a <minicard> element, which in turn contains all the lines of text. Each of Moo’s printed products take different numbers of lines of text, so if you are not planning on making mini-cards, be sure to consult the documentation. For mini-cards, we can have 6 distinct lines, each with their own style and layout. Each line is represented by an element <text_line> which has several optional children. The <id> tells which line of the 6 to print the text one. The <string> is the text you want to print and it must be shorter than 38 characters. The <bold> element is false by default, but if you want your text bolded, then add this and set it to true. The <align> element is also optional. By default it is set to align left. You can also set this to right or center if you desirer. The <font> element takes one of 3 types, modern, traditional or typewriter. The default is modern. Finally, you can set the <colour>, yes that’s color with a ‘u’, Moo is a British company, so they get to make the rules. When you start a print on demand company, you can spell it however you want. The <colour> element takes a 6 character hex value with a leading #. <design> ... <text_collection> <minicard> <text_line> <id>(1-6)</id> <string>String, I must be less than 38 chars!</string> <bold>true</bold> <align>left</align> <font>modern</font> <colour>#ff0000</colour> </text_line> </minicard> </text_collection> </design> If you combine all of this into a mini-card request you’d get this example: <?xml version="1.0" encoding="UTF-8"?> <moo xsi:noNamespaceSchemaLocation="http://www.moo.com/xsd/api_0.7.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <request> <version>0.7</version> <api_key>{YOUR API KEY HERE}</api_key> <call>build</call> <return_to>http://www.example.com/return.html</return_to> <fail_to>http://www.example.com/fail.html</fail_to> </request> <payload> <products> <product> <product_type>minicard</product_type> <designs> <design> <image> <url>http://example.com/image1.jpg</url> <type>variable</type> </image> <text_collection> <minicard> <text_line> <id>1</id> <string>String, I must be less than 38 chars!</string> <bold>true</bold> <align>left</align> <font>modern</font> <colour>#ff0000</colour> </text_line> </minicard> </text_collection> </design> </designs> </product> </products> </payload> </moo> Now you know how to construct the XML that describes what to print. Next, you need to know how to send it to Moo to make it happen! Posting to the API So your XML is file ready to go. First thing we need to do is check it to make sure it’s valid. Moo has created a simple validator where you paste in your XML, and it alerts you to problems. When you have a fully valid XML file, you’ll want to send that to the Moo API. There are a few ways to do this, but the simplest is with an HTML form. This is the sample code for an HTML form with a big “Buy My Stickers” button. Once you know that it is working, you can use all your existing HTML knowledge to style it up any way you like. <form method="POST" action="http://www.moo.com/api/api.php"> <input type="hidden" name="xml" value="<?xml version="1.0" encoding="UTF-8"?> <moo xsi:noNamespaceSchemaLocation="http://www.moo.com/xsd/api_0.7.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <request>....</request> <payload>...</payload> </moo> "> <input type="submit" name="submit" value="Buy My Stickers"/> </form> This is just a basic <form> element that submits to the Moo API, http://www.moo.com/api/api.php, when someone clicks the button. There is a hidden input called “xml” which contains the value the XML file we created previously. For those of you who need to “view source” to fully understand what’s happening can see a working version and peek under the hood. Using the API has advantages over uploading the images directly yourself. The images and text that you send via the API can be dynamic. Some companies, like Dopplr, have taken user profiles and dynamic data that changes every minute to generate customer stickers of places that you’ve travelled to or mini-cards with a world map of all the cities you have visited. Every single customer has different travel plans and therefore different sets of stickers and mini-card maps. The API allows for the utmost current information to be printed, on demand, in real-time. Go forth and Moo’ltiply See, making an API call wasn’t that hard was it? You are now 90% of the way to creating anything with the Moo API. With a bit of reading, you can learn that extra 10% and print any Moo product. Be on the lookout in 2009 for the official release of the 1.0 API with improvements and some extras that were not available when this article was written. This article is released under the creative-commons attribution share-a-like license. That means you are free to re-distribute it, mash it up, translate it and otherwise re-using it ways the author never considered, in return he only asks you mention his name. This work by Brian Suda is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License. 2008 Brian Suda briansuda 2008-12-19T00:00:00+00:00 https://24ways.org/2008/mooy-christmas/ code
240 My CSS Wish List I love Christmas. I love walking around the streets of London, looking at the beautifully decorated windows, seeing the shiny lights that hang above Oxford Street and listening to Christmas songs. I’m not going to lie though. Not only do I like buying presents, I love receiving them too. I remember making long lists that I would send to Father Christmas with all of the Lego sets I wanted to get. I knew I could only get one a year, but I would spend days writing the perfect list. The years have gone by, but I still enjoy making wish lists. And I’ll tell you a little secret: my mum still asks me to send her my Christmas list every year. This time I’ve made my CSS wish list. As before, I’d be happy with just one present. Before I begin… … this list includes: things that don’t exist in the CSS specification (if they do, please let me know in the comments – I may have missed them); others that are in the spec, but it’s incomplete or lacks use cases and examples (which usually means that properties haven’t been implemented by even the most recent browsers). Like with any other wish list, the further down I go, the more unrealistic my expectations – but that doesn’t mean I can’t wish. Some of the things we wouldn’t have thought possible a few years ago have been implemented and our wishes fulfilled (think multiple backgrounds, gradients and transformations, for example). The list Cross-browser implementation of font-size-adjust When one of the fall-back fonts from your font stack is used, rather than the preferred (first) one, you can retain the aspect ratio by using this very useful property. It is incredibly helpful when the fall-back fonts are smaller or larger than the initial one, which can make layouts look less polished. What font-size-adjust does is divide the original font-size of the fall-back fonts by the font-size-adjust value. This preserves the x-height of the preferred font in the fall-back fonts. Here’s a simple example: p { font-family: Calibri, "Lucida Sans", Verdana, sans-serif; font-size-adjust: 0.47; } In this case, if the user doesn’t have Calibri installed, both Lucida Sans and Verdana will keep Calibri’s aspect ratio, based on the font’s x-height. This property is a personal favourite and one I keep pointing to. Firefox supported this property from version three. So far, it’s the only browser that does. Fontdeck provides the font-size-adjust value along with its fonts, and has a handy tool for calculating it. More control over overflowing text The text-overflow property lets you control text that overflows its container. The most common use for it is to show an ellipsis to indicate that there is more text than what is shown. To be able to use it, the container should have overflow set to something other than visible, and white-space: nowrap: div { white-space: nowrap; width: 100%; overflow: hidden; text-overflow: ellipsis; } This, however, only works for blocks of text on a single line. In the wish list of many CSS authors (and in mine) is a way of defining text-overflow: ellipsis on a block of multiple text lines. Opera has taken the first step and added support for the -o-ellipsis-lastline property, which can be used instead of ellipsis. This property is not part of the CSS3 spec, but we could certainly make good use of it if it were… WebKit has -webkit-line-clamp to specify how many lines to show before cutting with an ellipsis, but support is patchy at best and there is no control over where the ellipsis shows in the text. Many people have spent time wrangling JavaScript to do this for us, but the methods used are very processor intensive, and introduce a JavaScript dependency. Indentation and hanging punctuation properties You might notice a trend here: almost half of the items in this list relate to typography. The lack of fine-grained control over typographical detail is a general concern among designers and CSS authors. Indentation and hanging punctuation fall into this category. The CSS3 specification introduces two new possible values for the text-indent property: each-line; and hanging. each-line would indent the first line of the block container and each line after a forced line break; hanging would invert which lines are affected by the indentation. The proposed hanging-punctuation property would allow us to specify whether opening and closing brackets and quotes should hang outside the edge of the first and last lines. The specification is still incomplete, though, and asks for more examples and use cases. Text alignment and hyphenation properties Following the typographic trend of this list, I’d like to add better control over text alignment and hyphenation properties. The CSS3 module on Generated Content for Paged Media already specifies five new hyphenation-related properties (namely: hyphenate-dictionary; hyphenate-before and hyphenate-after; hyphenate-lines; and hyphenate-character), but it is still being developed and lacks examples. In the text alignment realm, the new text-align-last property allows you to define how the last line of a block (or a line just before a forced break) is aligned, if your text is set to justify. Its value can be: start; end; left; right; center; and justify. The text-justify property should also allow you to have more control over text set to text-align: justify but, for now, only Internet Explorer supports this. calc() This is probably my favourite item in the list: the calc() function. This function is part of the CSS3 Values and Units module, but it has only been implemented by Firefox (4.0). To take advantage of it now you need to use the Mozilla vendor code, -moz-calc(). Imagine you have a fluid two-column layout where the sidebar column has a fixed width of 240 pixels, and the main content area fills the rest of the width available. This is how you could create that using -moz-calc(): #main { width: -moz-calc(100% - 240px); } Can you imagine how many hacks and headaches we could avoid were this function available in more browsers? Transitions and animations are really nice and lovely but, for me, it’s the ability to do the things that calc() allows you to that deserves the spotlight and to be pushed for implementation. Selector grouping with -moz-any() The -moz-any() selector grouping has been introduced by Mozilla but it’s not part of any CSS specification (yet?); it’s currently only available on Firefox 4. This would be especially useful with the way HTML5 outlines documents, where we can have any number of variations of several levels of headings within numerous types of containers (think sections within articles within sections…). Here is a quick example (copied from the Mozilla blog post about the article) of how -moz-any() works. Instead of writing: section section h1, section article h1, section aside h1, section nav h1, article section h1, article article h1, article aside h1, article nav h1, aside section h1, aside article h1, aside aside h1, aside nav h1, nav section h1, nav article h1, nav aside h1, nav nav h1, { font-size: 24px; } You could simply write: -moz-any(section, article, aside, nav) -moz-any(section, article, aside, nav) h1 { font-size: 24px; } Nice, huh? More control over styling form elements Some are of the opinion that form elements shouldn’t be styled at all, since a user might not recognise them as such if they don’t match the operating system’s controls. I partially agree: I’d rather put the choice in the hands of designers and expect them to be capable of deciding whether their particular design hampers or improves usability. I would say the same idea applies to font-face: while some fear designers might go crazy and litter their web pages with dozens of different fonts, most welcome the freedom to use something other than Arial or Verdana. There will always be someone who will take this freedom too far, but it would be useful if we could, for example, style the default Opera date picker: <input type="date" /> or Safari’s slider control (think star movie ratings, for example): <input type="range" min="0" max="5" step="1" value="3" /> Parent selector I don’t think there is one CSS author out there who has never come across a case where he or she wished there was a parent selector. There have been many suggestions as to how this could work, but a variation of the child selector is usually the most popular: article < h1 { … } One can dream… Flexible box layout The Flexible Box Layout Module sounds a bit like magic: it introduces a new box model to CSS, allowing you to distribute and order boxes inside other boxes, and determine how the available space is shared. Two of my favourite features of this new box model are: the ability to redistribute boxes in a different order from the markup the ability to create flexible layouts, where boxes shrink (or expand) to fill the available space Let’s take a quick look at the second case. Imagine you have a three-column layout, where the first column takes up twice as much horizontal space as the other two: <body> <section id="main"> </section> <section id="links"> </section> <aside> </aside> </body> With the flexible box model, you could specify it like this: body { display: box; box-orient: horizontal; } #main { box-flex: 2; } #links { box-flex: 1; } aside { box-flex: 1; } If you decide to add a fourth column to this layout, there is no need to recalculate units or percentages, it’s as easy as that. Browser support for this property is still in its early stages (Firefox and WebKit need their vendor prefixes), but we should start to see it being gradually introduced as more attention is drawn to it (I’m looking at you…). You can read a more comprehensive write-up about this property on the Mozilla developer blog. It’s easy to understand why it’s harder to start playing with this module than with things like animations or other more decorative properties, which don’t really break your layouts when users don’t see them. But it’s important that we do, even if only in very experimental projects. Nested selectors Anyone who has never wished they could do something like the following in CSS, cast the first stone: article { h1 { font-size: 1.2em; } ul { margin-bottom: 1.2em; } } Even though it can easily turn into a specificity nightmare and promote redundancy in your style sheets (if you abuse it), it’s easy to see how nested selectors could be useful. CSS compilers such as Less or Sass let you do this already, but not everyone wants or can use these compilers in their projects. Every wish list has an item that could easily be dropped. In my case, I would say this is one that I would ditch first – it’s the least useful, and also the one that could cause more maintenance problems. But it could be nice. Implementation of the ::marker pseudo-element The CSS Lists module introduces the ::marker pseudo-element, that allows you to create custom list item markers. When an element’s display property is set to list-item, this pseudo-element is created. Using the ::marker pseudo-element you could create something like the following: Footnote 1: Both John Locke and his father, Anthony Cooper, are named after 17th- and 18th-century English philosophers; the real Anthony Cooper was educated as a boy by the real John Locke. Footnote 2: Parts of the plane were used as percussion instruments and can be heard in the soundtrack. where the footnote marker is generated by the following CSS: li::marker { content: "Footnote " counter(notes) ":"; text-align: left; width: 12em; } li { counter-increment: notes; } You can read more about how to use counters in CSS in my article from last year. Bear in mind that the CSS Lists module is still a Working Draft and is listed as “Low priority”. I did say this wish list would start to grow more unrealistic closer to the end… Variables The sight of the word ‘variables’ may make some web designers shy away, but when you think of them applied to things such as repeated colours in your stylesheets, it’s easy to see how having variables available in CSS could be useful. Think of a website where the main brand colour is applied to elements like the main text, headings, section backgrounds, borders, and so on. In a particularly large website, where the colour is repeated countless times in the CSS and where it’s important to keep the colour consistent, using variables would be ideal (some big websites are already doing this by using server-side technology). Again, Less and Sass allow you to use variables in your CSS but, again, not everyone can (or wants to) use these. If you are using Less, you could, for instance, set the font-family value in one variable, and simply call that variable later in the code, instead of repeating the complete font stack, like so: @fontFamily: Calibri, "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif; body { font-family: @fontFamily; } Other features of these CSS compilers might also be useful, like the ability to ‘call’ a property value from another selector (accessors): header { background: #000000; } footer { background: header['background']; } or the ability to define functions (with arguments), saving you from writing large blocks of code when you need to write something like, for example, a CSS gradient: .gradient (@start:"", @end:"") { background: -webkit-gradient(linear, left top, left bottom, from(@start), to(@end)); background: -moz-linear-gradient(-90deg,@start,@end); } button { .gradient(#D0D0D0,#9F9F9F); } Standardised comments Each CSS author has his or her own style for commenting their style sheets. While this isn’t a massive problem on smaller projects, where maybe only one person will edit the CSS, in larger scale projects, where dozens of hands touch the code, it would be nice to start seeing a more standardised way of commenting. One attempt at creating a standard for CSS comments is CSSDOC, an adaptation of Javadoc (a documentation generator that extracts comments from Java source code into HTML). CSSDOC uses ‘DocBlocks’, a term borrowed from the phpDocumentor Project. A DocBlock is a human- and machine-readable block of data which has the following structure: /** * Short description * * Long description (this can have multiple lines and contain <p> tags * * @tags (optional) */ CSSDOC includes a standard for documenting bug fixes and hacks, colours, versioning and copyright information, amongst other important bits of data. I know this isn’t a CSS feature request per se; rather, it’s just me pointing you at something that is usually overlooked but that could contribute towards keeping style sheets easier to maintain and to hand over to new developers. Final notes I understand that if even some of these were implemented in browsers now, it would be a long time until all vendors were up to speed. But if we don’t talk about them and experiment with what’s available, then it will definitely never happen. Why haven’t I mentioned better browser support for existing CSS3 properties? Because that would be the same as adding chocolate to your Christmas wish list – you don’t need to ask, everyone knows you want it. The list could go on. There are dozens of other things I would love to see integrated in CSS or further developed. These are my personal favourites: some might be less useful than others, but I’ve wished for all of them at some point. Part of the research I did while writing this article was asking some friends what they would add to their lists; other than a couple of items I already had in mine, everything else was different. I’m sure your list would be different too. So tell me, what’s on your CSS wish list? 2010 Inayaili de León Persson inayailideleon 2010-12-03T00:00:00+00:00 https://24ways.org/2010/my-css-wish-list/ code
164 My Other Christmas Present Is a Definition List A note from the editors: readers should note that the HTML5 redefinition of definition lists has come to pass and is now à la mode. Last year, I looked at how the markup for tag clouds was generally terrible. I thought this year I would look not at a method of marking up a common module, but instead just at a simple part of HTML and how it generally gets abused. No, not tables. Definition lists. Ah, definition lists. Often used but rarely understood. Examining the definition of definitions To start with, let’s see what the HTML spec has to say about them. Definition lists vary only slightly from other types of lists in that list items consist of two parts: a term and a description. The canonical example of a definition list is a dictionary. Words can have multiple descriptions (even the word definition has at least five). Also, many terms can share a single definition (for example, the word colour can also be spelt color, but they have the same definition). Excellent, we can all grasp that. But it very quickly starts to fall apart. Even in the HTML specification the definition list is mis-used. Another application of DL, for example, is for marking up dialogues, with each DT naming a speaker, and each DD containing his or her words. Wrong. Completely and utterly wrong. This is the biggest flaw in the HTML spec, along with dropping support for the start attribute on ordered lists. “Why?”, you may ask. Let me give you an example from Romeo and Juliet, act 2, scene 2. <dt>Juliet</dt> <dd>Romeo!</dd> <dt>Romeo</dt> <dd>My niesse?</dd> <dt>Juliet</dt> <dd>At what o'clock tomorrow shall I send to thee?</dd> <dt>Romeo</dt> <dd>At the hour of nine.</dd> Now, the problem here is that a given definition can have multiple descriptions (the DD). Really the dialog “descriptions” should be rolled up under the terms, like so: <dt>Juliet</dt> <dd>Romeo!</dd> <dd>At what o'clock tomorrow shall I send to thee?</dd> <dt>Romeo</dt> <dd>My niesse?</dd> <dd>At the hour of nine.</dd> Suddenly the play won’t make anywhere near as much sense. (If it’s anything, the correct markup for a play is an ordered list of CITE and BLOCKQUOTE elements.) This is the first part of the problem. That simple example has turned definition lists in everyone’s mind from pure definitions to more along the lines of a list with pre-configured heading(s) and text(s). Screen reader, enter stage left. In many screen readers, a simple definition list would be read out as “definition term equals definition description”. So in our play excerpt, Juliet equals Romeo! That’s not right, either. But this also leads a lot of people astray with definition lists to believing that they are useful for key/value pairs. Behaviour and convention The WHAT-WG have noticed the common mis-use of the DL, and have codified it into the new spec. In the HTML5 draft, a definition list is no longer a definition list. The dl element introduces an unordered association list consisting of zero or more name-value groups (a description list). Each group must consist of one or more names (dt elements) followed by one or more values (dd elements). They also note that the “dl element is inappropriate for marking up dialogue, since dialogue is ordered”. So for that example they have created a DIALOG (sic) element. Strange, then, that they keep DL as-is but instead refer to it an “association list”. They have not created a new AL element, and kept DL for the original purpose. They have chosen not to correct the usage or to create a new opportunity for increased specificity in our HTML, but to “pave the cowpath” of convention. How to use a definition list Given that everyone else is using a DL incorrectly, should we? Well, if they all jumped off a bridge, would you too? No, of course you wouldn’t. We don’t have HTML5 yet, so we’re stuck with the existing semantics of HTML4 and XHTML1. Which means that: Listing dialogue is not defining anything. Listing the attributes of a piece of hardware (resolution = 1600×1200) is illustrating sample values, not defining anything (however, stating what ‘resolution’ actually means in this context would be a definition). Listing the cast and crew of a given movie is not defining the people involved in making movies. (Stuart Gordon may have been the director of Space Truckers, but that by no means makes him the true definition of a director.) A menu of navigation items is simply a nested ordered or unordered list of links, not a definition list. Applying styling handles to form labels and elements is not a good use for a definition list. And so on. Living by the specification, a definition list should be used for term definitions – glossaries, lexicons and dictionaries – only. Anything else is a crime against markup. 2007 Mark Norman Francis marknormanfrancis 2007-12-05T00:00:00+00:00 https://24ways.org/2007/my-other-christmas-present-is-a-definition-list/ code
36 Naming Things There are only two hard things in computer science: cache invalidation and naming things. Phil Karlton Being a professional web developer means taking responsibility for the code you write and ensuring it is comprehensible to others. Having a documented code style is one means of achieving this, although the size and type of project you’re working on will dictate the conventions used and how rigorously they are enforced. Working in-house may mean working with multiple developers, perhaps in distributed teams, who are all committing changes – possibly to a significant codebase – at the same time. Left unchecked, this codebase can become unwieldy. Coding conventions ensure everyone can contribute, and help build a product that works as a coherent whole. Even on smaller projects, perhaps working within an agency or by yourself, at some point the resulting product will need to be handed over to a third party. It’s sensible, therefore, to ensure that your code can be understood by those who’ll eventually take ownership of it. Put simply, code is read more often than it is written or changed. A consistent and predictable naming scheme can make code easier for other developers to understand, improve and maintain, presumably leaving them free to worry about cache invalidation. Let’s talk about semantics Names not only allow us to identify objects, but they can also help us describe the objects being identified. Semantics (the meaning or interpretation of words) is the cornerstone of standards-based web development. Using appropriate HTML elements allows us to create documents and applications that have implicit structural meaning. Thanks to HTML5, the vocabulary we can choose from has grown even larger. HTML elements provide one level of meaning: a widely accepted description of a document’s underlying structure. It’s only with the mutual agreement of browser vendors and developers that <p> indicates a paragraph. Yet (with the exception of widely accepted microdata and microformat schemas) only HTML elements convey any meaning that can be parsed consistently by user agents. While using semantic values for class names is a noble endeavour, they provide no additional information to the visitor of a website; take them away and a document will have exactly the same semantic value. I didn’t always think this was the case, but the real world has a habit of changing your opinion. Much of my thinking around semantics has been informed by the writing of my peers. In “About HTML semantics and front-end architecture”, Nicholas Gallagher wrote: The important thing for class name semantics in non-trivial applications is that they be driven by pragmatism and best serve their primary purpose – providing meaningful, flexible, and reusable presentational/behavioural hooks for developers to use. These thoughts are echoed by Harry Roberts in his CSS Guidelines: The debate surrounding semantics has raged for years, but it is important that we adopt a more pragmatic, sensible approach to naming things in order to work more efficiently and effectively. Instead of focussing on ‘semantics’, look more closely at sensibility and longevity – choose names based on ease of maintenance, not for their perceived meaning. Naming methodologies Front-end development has undergone a revolution in recent years. As the projects we’ve worked on have grown larger and more important, our development practices have matured. The pros and cons of object-orientated approaches to CSS can be endlessly debated, yet their introduction has highlighted the usefulness of having documented naming schemes. Jonathan Snook’s SMACSS (Scalable and Modular Architecture for CSS) collects style rules into five categories: base, layout, module, state and theme. This grouping makes it clear what each rule does, and is aided by a naming convention: By separating rules into the five categories, naming convention is beneficial for immediately understanding which category a particular style belongs to and its role within the overall scope of the page. On large projects, it is more likely to have styles broken up across multiple files. In these cases, naming convention also makes it easier to find which file a style belongs to. I like to use a prefix to differentiate between layout, state and module rules. For layout, I use l- but layout- would work just as well. Using prefixes like grid- also provide enough clarity to separate layout styles from other styles. For state rules, I like is- as in is-hidden or is-collapsed. This helps describe things in a very readable way. SMACSS is more a set of suggestions than a rigid framework, so its ideas can be incorporated into your own practice. Nicholas Gallagher’s SUIT CSS project is far more strict in its naming conventions: SUIT CSS relies on structured class names and meaningful hyphens (i.e., not using hyphens merely to separate words). This helps to work around the current limits of applying CSS to the DOM (i.e., the lack of style encapsulation), and to better communicate the relationships between classes. Over the last year, I’ve favoured a BEM-inspired approach to CSS. BEM stands for block, element, modifier, which describes the three types of rule that contribute to the style of a single component. This means that, given the following markup: <ul class=“sleigh”> <li class=“sleigh__reindeer sleigh__reindeer––famous”>Rudolph</li> <li class=“sleigh__reindeer”>Dasher</li> <li class=“sleigh__reindeer”>Dancer</li> <li class=“sleigh__reindeer”>Prancer</li> <li class=“sleigh__reindeer”>Vixen</li> <li class=“sleigh__reindeer”>Comet</li> <li class=“sleigh__reindeer”>Cupid</li> <li class=“sleigh__reindeer”>Dunder</li> <li class=“sleigh__reindeer”>Blixem</li> </ul> I know that: .sleigh is a containing block or component. .sleigh__reindeer is used only as a descendent element of .sleigh. .sleigh__reindeer––famous is used only as a modifier of .sleigh__reindeer. With this naming scheme in place, I know which styles relate to a particular component, and which are shared. Beyond reducing specificity-related head-scratching, this approach has given me a framework within which I can consistently label items, and has sped up my workflow considerably. Each of these methodologies shows that any robust CSS naming convention will have clear rules around case (lowercase, camelCase, PascalCase) and the use of special (allowed) characters like hyphens and underscores. What makes for a good name? Regardless of higher-level conventions, there’s no getting away from the fact that, at some point, we’re still going to have to name things. Recognising that classes should be named with other developers in mind, what makes for a good name? Understandable The most important aspect is for a name to be understandable. Words used in your project may come from a variety of sources: some may be widely understood, and others only be recognised by people working within a particular environment. Culture Most words you’ll choose will have common currency outside the world of web development, although they may have a particular interpretation among developers (think menu, list, input). However, words may have a narrower cultural significance; for example, in Germany and other German-speaking countries, impressum is the term used for legally mandated statements of ownership. Industry Industries often use specific terms to describe common business practices and concepts. Publishing has a number of these (headline, standfirst, masthead, colophon…) all have well understood meanings – and not all of them are relevant to online usage. Organisation Companies may have internal names (or nicknames) for their products and services. The Guardian is rife with such names: bisons (and buffalos), pixies (and super-pixies), bentos (and mini-bentos)… all of which mean something very different outside the organisation. Although such names can be useful inside smaller teams, in larger organisations they can become a barrier to entry, a sort of secret code used among employees who have been around long enough to know what they mean. Product Your team will undoubtedly have created names for specific features or interface components used in your product. For example, at Clearleft we coined the term gravigation for a navigation bar that was pinned to the bottom of the viewport. Elements of a visual design language may have names, too. Transport for London’s bar and circle logo is known internally as the roundel, while Nike’s logo is called the swoosh. Branding agencies often christen colours within a brand palette, too, either to evoke aspects of the identity or to indicate intended usage. Once you recognise the origin of the words you use, you’ll be better able to judge their appropriateness. Using Latin words for class names may satisfy a need to use semantic-sounding terms but, unless you work in a company whose employees have a basic grasp of Latin, a degree of translation will be required. Military ranks might be a clever way of declaring sizes without implying actual values, but I’d venture most people outside the armed forces don’t know how they’re ordered. Obvious Quite often, the first name that comes into your head will be the best option. Names that obliquely reference the function of a class (e.g. receptacle instead of container, kevlar instead of no-bullets) only serve to add an additional layer of abstraction. Don’t overthink it! One way of knowing if the names you use are well understood is to look at what similar concepts are called in existing vocabularies. schema.org, Dublin Core and the BBC’s ontologies are all useful sources for object names. Functional While we’ve learned to avoid using presentational classes, there remains a tension between naming things based on their content, and naming them for their intended presentation or behaviour (which may change at different breakpoints). Rather than think about a component’s appearance or behaviour, instead look to its function, its purpose. To clarify, ask what a component’s function is, and not how the component functions. For example, the Guardian’s internal content system uses the following names for different types of image placement: supporting, showcase and thumbnail, with inline being the default. These options make no promise of the resulting position on a webpage (or smartphone app, or television screen…), but do suggest intended use, and therefore imply the likely presentation. Consistent Being consistent in your approach to names will allow for easier naming of successive components, and extending the vocabulary when necessary. For example, a predictably named hierarchy might use names like primary and secondary. Should another level need to be added, tertiary is clearly be preferred over third. Appropriate Your project will feature a mix of style rules. Some will perform utility functions (clearing floats, removing bullets from a list, reseting margins), while others will perform specific functions used only once or twice in a project. Names should reflect this. For commonly used classes, be generic; for unique components be more specific. It’s also worth remembering that you can use multiple classes on an element, so combining both generic and specific can give you a powerful modular design system: Generic: list Specific: naughty-children Combined: naughty-children list If following the BEM methodology, you might use the following classes: Generic: list Specific: list––nice-children Combined: list list––nice-children Extensible Good naming schemes can be extended. One way of achieving this is to use namespaces, which are basically a way of grouping related names under a higher-level term. Microformats are a good example of a well-designed naming scheme, with many of its vocabularies taking property names from existing and related specifications (e.g. hCard is a 1:1 representation of vCard). Microformats 2 goes one step further by grouping properties under several namespaces: h-* for root class names (e.g. h-card) p-* for simple (text) properties (e.g. p-name) u-* for URL properties (e.g. u-photo) dt-* for date/time properties (e.g. dt-bday) e-* for embedded markup properties (e.g. e-note) The inclusion of namespaces is a massive improvement over the earlier specification, but the downside is that microformats now occupy five separate namespaces. This might be problematic if you are using u-* for your utility classes. While nothing will break, your naming system won’t be as robust, so plan accordingly. (Note: Microformats perform a very specific function, separate from any presentational concerns. It’s therefore considered best practice to not use microformat classes as styling hooks, but instead use additional classes that relate to the function of the component and adhere to your own naming conventions.) Short Names should be as long as required, but no longer. When looking for words to describe a particular function, I try to look for single words where possible. Avoid abbreviations unless they are understood within the contexts described above. rrp is fine if labelling a recommended retail price in an online shop, but not very helpful if used to mean ragged-right paragraph, for example. Fun! Finally, names can be an opportunity to have some fun! Names can give character to a project, be it by providing an outlet for in-jokes or adding little easter eggs for those inclined to look. The copyright statement on Apple’s website has long been named sosumi, a word that has a nice little history inside Apple. Until recently, the hamburger menu icon on the Guardian website was labelled honest-burger, after the developer’s favourite burger restaurant. A few thoughts on preprocessors CSS preprocessors have solved a lot of problems, but they have an unfortunate downside: they require you to name yet more things! Whereas we needed to worry only about style rules, now we need names for variables, mixins, functions… oh my! A second article could be written about naming these, so for now I’ll offer just a few thoughts. The first is to note that preprocessors make it easier to change things, as they allow for DRYer code. So while the names of variables are important (and the advice in this article still very much applies), you can afford to relax a little. Looking to name colour variables? If possible, find out if colours have been assigned names in a brand palette. If not, use obvious names (based on appearance or function, depending on your preference) and adapt as the palette grows. If it becomes difficult to name colours that are too similar, I’d venture that the problem lies with the design rather than the naming scheme. The same is true for responsive breakpoints. Preprocessors allow you to move awkward naming conventions out of the markup and into the CSS. Although terms like mobile, tablet and desktop are not desirable given the need to think about device-agnostic design, if these terms are widely understood within a product team and among stakeholders, using them will ensure everyone is using the same language (they can always be changed later). It still feels like we’re at the very beginning of understanding how preprocessors fit into a development workflow, if at all! I suspect over the next few years, best practices will emerge for all of these considerations. In the meantime, use your brain! Even with sensible rules and conventions in place, naming things can remain difficult, but hopefully I’ve made this exercise a little less painful. Christmas is a time of giving, so to the developer reading your code in a year’s time, why not make your gift one of clearer class names. 2014 Paul Lloyd paulrobertlloyd 2014-12-21T00:00:00+00:00 https://24ways.org/2014/naming-things/ code
335 Naughty or Nice? CSS Background Images Web Standards based development involves many things – using semantically sound HTML to provide structure to our documents or web applications, using CSS for presentation and layout, using JavaScript responsibly, and of course, ensuring that all that we do is accessible and interoperable to as many people and user agents as we can. This we understand to be good. And it is good. Except when we don’t clearly think through the full implications of using those techniques. Which often happens when time is short and we need to get things done. Here are some naughty examples of CSS background images with their nicer, more accessible counterparts. Transaction related messages I’m as guilty of this as others (or, perhaps, I’m the only one that has done this, in which case this can serve as my holiday season confessional) We use lovely little icons to show status messages for a transaction to indicate if the action was successful, or was there a warning or error? For example: “Your postal/zip code was not in the correct format.” Notice that we place a nice little icon there, and use background colours and borders to convey a specific message: there was a problem that needs to be fixed. Notice that all of this visual information is now contained in the CSS rules for that div: <div class="error"> <p>Your postal/zip code was not in the correct format.</p> </div> div.error { background: #ffcccc url(../images/error_small.png) no-repeat 5px 4px; color: #900; border-top: 1px solid #c00; border-bottom: 1px solid #c00; padding: 0.25em 0.5em 0.25em 2.5em; font-weight: bold; } Using this approach also makes it very easy to create a div.success and div.warning CSS rules meaning we have less to change in our HTML. Nice, right? No. Naughty. Visual design communicates The CSS is being used to convey very specific information. The choice of icon, the choice of background colour and borders tell us visually that there is something wrong. With the icon as a background image – there is no way to specify any alt text for the icon, and significant meaning is lost. A screen reader user, for example, misses the fact that it is an “error.” The solution? Ask yourself: what is the bare minimum needed to indicate there was an error? Currently in the absence of CSS there will be no icon – which (I’m hoping you agree) is critical to communicating there was an error. The icon should be considered content and not simply presentational. The borders and background colour are certainly much less critical – they belong in the CSS. Lets change the code to place the image directly in the HTML and using appropriate alt text to better communicate the meaning of the icon to all users: <div class="bettererror"> <img src="images/error_small.png" alt="Error" /> <p>Your postal/zip code was not in the correct format.</p> </div> div.bettererror { background-color: #ffcccc; color: #900; border-top: 1px solid #c00; border-bottom: 1px solid #c00; padding: 0.25em 0.5em 0.25em 2.5em; font-weight: bold; position: relative; min-height: 1.25em; } div.bettererror img { display: block; position: absolute; left: 0.25em; top: 0.25em; padding: 0; margin: 0; } div.bettererror p { position: absolute; left: 2.5em; padding: 0; margin: 0; } Compare these two examples of transactional messages Status of a Record This example is pretty straightforward. Consider the following: a real estate listing on a web site. There are three “states” for a listing: new, normal, and sold. Here’s how they look: Example of a New Listing Example of A Sold Listing If we (forgive the pun) blindly apply the “use a CSS background image” technique we clearly run into problems with the new and sold images – they actually contain content with no way to specify an alternative when placed in the CSS. In this case of the “new” image, we can use the same strategy as we used in the first example (the transaction result). The “new” image should be considered content and is placed in the HTML as part of the <h2>...</h2> that identifies the listing. However when considering the “sold” listing, there are less changes to be made to keep the same look by leaving the “SOLD” image as a background image and providing the equivalent information elsewhere in the listing – namely, right in the heading. For those that can’t see the background image, the status is communicated clearly and right away. A screen reader user that is navigating by heading or viewing a listing will know right away that a particular property is sold. Of note here is that in both cases (new and sold) placing the status near the beginning of the record helps with a zoom layout as well. Better Example of A Sold Listing Summary Remember: in the holiday season, its what you give that counts!! Using CSS background images is easy and saves time for you but think of the children. And everyone else for that matter… CSS background images should only be used for presentational images, not for those that contain content (unless that content is already represented and readily available elsewhere). 2005 Derek Featherstone derekfeatherstone 2005-12-20T00:00:00+00:00 https://24ways.org/2005/naughty-or-nice-css-background-images/ code
294 New Tricks for an Old Dog Much of my year has been spent helping new team members find their way around the expansive and complex codebase that is the TweetDeck front-end, trying to build a happy and productive group of people around a substantial codebase with many layers of legacy. I’ve loved doing this. Everything from writing new documentation, drawing diagrams, and holding technical architecture sessions teaches you something you didn’t know or exposes an area of uncertainty that you can go work on. In this article, I hope to share some experiences and techniques that will prove useful in your own situation and that you can impress your friends in some new and exciting ways! How do you do, fellow kids? To start with I’d like to introduce you to our JavaScript framework, Flight. Right now it’s used by twitter.com and TweetDeck although, as a company, Twitter is largely moving to React. Over time, as we used Flight for more complex interfaces, we found it wasn’t scaling with us. Composing components into trees was fiddly and often only applied for a specific parent-child pairing. It seems like an obvious feature with hindsight, but it didn’t come built-in to Flight, and it made reusing components a real challenge. There was no standard way to manage the state of a component; they all did it slightly differently, and the technique often varied by who was writing the code. This cost us in maintainability as you just couldn’t predict how a component would be built until you opened it. Making matters worse, Flight relied on events to move data around the application. Unfortunately, events aren’t good for giving structure to complex logic. They jump around in a way that’s hard to understand and debug, and force you to search your code for a specific string — the event name‚ to figure out what’s going on. To find fixes for these problems, we looked around at other frameworks. We like React for it’s simple, predictable state management and reactive re-render flow, and Elm for bringing strict functional programming to everyone. But when you have lots of existing code, rewriting or switching framework is a painful and expensive option. You have to understand how it will interact with your existing code, how you’ll test it alongside existing code, and how it will affect the size and performance of the application. This all takes time and effort! Instead of planning a rewrite, we looked for the ideas hidden within other frameworks that we could reapply in our own situation or bring to the tools we already were using. Boiled down, what we liked seemed quite simple: Component nesting & composition Easy, predictable state management Normal functions for data manipulation Making these ideas applicable to Flight took some time, but we’re in a much better place now. Through persistent trial-and-error, we have well documented, testable and standard techniques for creating complex component hierarchies, updating and reacting to state changes, and passing data around the app. While the specifics of our situation and Flight aren’t really important, this experience taught me something: Distill good tech into great ideas. You can apply great ideas anywhere. You don’t have to use cool kids’ latest framework, hottest build tool or fashionable language to benefit from them. If you can identify a nugget of gold at the heart of it all, why not use it to improve what you have already? Times, they are a changin’ Apart from stealing ideas from the new and shiny, how can we keep make the most of improved tooling and techniques? Times change and so should the way we write code. Going back in time a bit, TweetDeck used some slightly outmoded tools for building and bundling. Without a transpiler like Babel we were missing out new language features, and without a more advanced build tools like Webpack, every module’s source was encased in AMD boilerplate. In fact, we found ourselves with a mix of both AMD syntaxes: define(["lodash"], function (_) { // . . . }); define(function (require) { var _ = require("lodash"); // . . . }); This just wouldn’t do. And besides, what we really wanted was CommonJS, or even ES2015 module syntax: import _ from "lodash"; These days we’re using Babel, Webpack, ES2015 modules and many new language features that make development just… better. But how did we get there? To explain, I want to introduce you to codemods and jscodeshift. A codemod is a large-scale refactor of a whole codebase, often mechanical or repetitive. Think of renaming a module or changing an API like URL("...") to new URL("..."). jscodeshift is a toolkit for running automated codemods, where you express a code transformation using code. The automated codemod operates on each file’s syntax tree – a data-structure representation of the code — finding and modifying in place as it goes. Here’s an example that renames all instances of the variable foo to bar: module.exports = function (fileInfo, api) { return api .jscodeshift(fileInfo.source) .findVariableDeclarators('foo') .renameTo('bar') .toSource(); }; It’s a seriously powerful tool, and we’ve used it to write a series of codemods that: rename modules, unify our use of AMD to a single syntax, transition from one testing framework to another, and switch from AMD to CommonJS. These changes can be pretty huge and far-reaching. Here’s an example commit from when we switched to CommonJS: commit 8f75de8fd4c702115c7bf58febba1afa96ae52fc Date: Tue Jul 12 2016 Run AMD -> CommonJS codemod 418 files changed, 47550 insertions(+), 48468 deletions(-) Yep, that’s just under 50k lines changed, tested, merged and deployed without any trouble. AMD be gone! From this step-by-step approach, using codemods to incrementally tweak and improve, we extracted a little codemod recipe for making significant, multi-stage changes: Find all the existing patterns Choose the two most similar Unify with a codemod Repeat. For example: For module loading, we had 2 competing AMD patterns plus some use of CommonJS The two AMD syntaxes were the most similar We used a codemod to move to unify the AMD patterns Later we returned to AMD to convert it to CommonJS It’s worked for us, and if you’d like to know more about codemods then check out Evolving Complex Systems Incrementally by Facebook engineer, Christoph Pojer. Welcome aboard! As TweetDeck has gotten older and larger, the amount of things a new engineer has to learn about has exploded. The myriad of microservices that manage our data and their layers of authentication, security and business logic around them make for an overwhelming amount of information to hand to a newbie. Inspired by Amy’s amazing Guide to the Care and Feeding of Junior Devs, we realised it was important to take time to design our onboarding that each of our new hires go through to make the most of their first few weeks. Joining a new company, team, or both, is stressful and uncomfortable. Everything you can do to help a new hire will be valuable to them. So please, take time to design your onboarding! And as you build up an onboarding process, you’ll create things that are useful for more than just new hires; it’ll force you to write documentation, for example, in a way that’s understandable for people who are unfamiliar with your team, product and codebase. This can lead to more outside contributions: potential contributors feel more comfortable getting set up on your product without asking for help. This is something that’s taken for granted in open source, but somehow I think we forget about it in big companies. After all, better documentation is just a good thing. You will forget things from time to time, and you’d be surprised how often the “beginner” docs help! For TweetDeck, we put together system and architecture diagrams, and one-pager explanations of important concepts: What are our dependencies? Where are the potential points of failure? Where does authentication live? Storage? Caching? Who owns “X”? Of course, learning continues long after onboarding. The landscape is constantly shifting; old services are deprecated, new APIs appear and what once true can suddenly be very wrong. Keeping up with this is a serious challenge, and more than any one person can track. To address this, we’ve thought hard about our knowledge sharing practices across the whole team. For example, we completely changed the way we do code review. In my opinion, code review is the single most effective practice you can introduce to share knowledge around, and build the quality and consistency of your team’s work. But, if you’re not doing it, here’s my suggestion for getting started: Every pull request gets a +1 from someone else. That’s all — it’s very light-weight and easy. Just ask someone to have a quick look over your code before it goes into master. At Twitter, every commit gets a code review. We do a lot of reviewing, so small efficiency and effectiveness improvements make a big difference. Over time we learned some things: Don’t review for more than hour 1 Keep reviews smaller than ~400 lines 2 Code review your own code first 2 After an hour, and above roughly 400 lines, your ability to detect issues in a code review starts to decrease. So review little and often. The gaps around lunch, standup and before you head home are ideal. And remember, if someone’s put code up for a review, that review is blocking them doing other work. It’s your job to unblock them. On TweetDeck, we actually try to keep reviews under 250 lines. It doesn’t sound like much, but this constraint applies pressure to make smaller, incremental changes. This makes breakages easier to detect and roll back, and leads to a very natural feature development process that encourages learning and iteration. But the most important thing I’ve learned personally is that reviewing my own code is the best way to spot issues. I try to approach my own reviews the way I approach my team’s: with fresh, critical eyes, after a break, using a dedicated code review tool. It’s amazing what you can spot when you put a new in a new interface around code you’ve been staring at for hours! And yes, this list features science. The data backs up these conclusions, and if you’d like to learn more about scientific approaches to software engineering then I recommend you buy Making Software: What Really Works, and Why We Believe It. It’s ace. For more dedicated information sharing, we’ve introduced regular seminars for everyone who works on a specific area or technology. It works like this: a team-member shares or teaches something to everyone else, and next time it’s someone else’s turn. Giving everyone a chance to speak, and encouraging a wide range of topics, is starting to produce great results. If you’d like to run a seminar, one thing you could try to get started: run a point at the thing you least understand in our architecture session — thanks to James for this idea. And guess what… your onboarding architecture diagrams will help (and benefit from) this! More, please! There’s a few ideas here to get you started, but there are even more in a talk I gave this year called Frontend Archaeology, including a look at optimising for confidence with front-end operations. And finally, thanks to Amy for proof reading this and to Passy for feedback on the original talk. Dunsmore et al. 2000. Object-Oriented Inspection in the Face of Delocalisation. Beverly, MA: SmartBear Software. ↩ Cohen, Jason. 2006. Best Kept Secrets of Peer Code Review. Proceedings of the 22nd ICSE 2000: 467-476. ↩ ↩ 2016 Tom Ashworth tomashworth 2016-12-18T00:00:00+00:00 https://24ways.org/2016/new-tricks-for-an-old-dog/ code
281 Nine Things I've Learned I’ve been a professional graphic designer for fourteen years and for just under four of those a professional web designer. Like most designers I’ve learned a lot in my time, both from a design point of view and in business as freelance designer. A few of the things I’ve learned stick out in my mind, so I thought I’d share them with you. They’re pretty random and in no particular order. 1. Becoming the designer you want to be When I started out as a young graphic designer, I wanted to design posters and record sleeves, pretty much like every other young graphic designer. The problem is that the reality of the world means that when you get your first job you’re designing the back of a paracetamol packet or something equally weird. I recently saw a tweet that went something like this: “You’ll never become the designer you always dreamt of being by doing the work you never wanted to do”. This is so true; to become the designer you want to be, you need to be designing the things you’re passionate about designing. This probably this means working in the evenings and weekends for little or no money, but it’s time well spent. Doing this will build up your portfolio with the work that really shows what you can do! Soon, someone will ask you to design something based on having seen this work. From this point, you’re carving your own path in the direction of becoming the designer you always wanted to be. 2. Compete on your own terms As well as all being friends, we are also competitors. In order to win new work we need a selling point, preferably a unique selling point. Web design is a combination of design disciplines – user experience design, user interface Design, visual design, development, and so on. Some companies will sell themselves as UX specialists, which is fine, but everyone who designs a website from scratch does some sort of UX, so it’s not really a unique selling point. Of course, some people do it better than others. One area of web design that clients have a strong opinion on, and will judge you by, is visual design. It’s an area in which it’s definitely possible to have a unique selling point. Designing the visual aesthetic for a website is a combination of logical decision making and a certain amount of personal style. If you can create a unique visual style to your work, it can become a selling point that’s unique to you. 3. How much to charge and staying motivated When you’re a freelance designer one of the hardest things to do is put a price on your work and skills. Finding the right amount to charge is a fine balance between supplying value to your customer and also charging enough to stay motivated to do a great job. It’s always tempting to offer a low price to win work, but it’s often not the best approach: not just for yourself but for the client as well. A client once asked me if I could reduce my fee by £1,000 and still be motivated enough to do a good job. In this case the answer was yes, but it was the question that resonated with me. I realized I could use this as a gauge to help me price projects. Before I send out a quote I now always ask myself the question “Is the amount I’ve quoted enough to make me feel motivated to do my best on this project?” I never send out a quote unless the answer is yes. In my mind there’s no point in doing any project half-heartedly, as every project is an opportunity to build your reputation and expand your portfolio to show potential clients what you can do. Offering a client a good price but not being prepared to put everything you have into it, isn’t value for money. 4. Supplying the right design When I started out as a graphic designer it seemed to be the done thing to supply clients with a ton of options for their logo or brochure designs. In a talk given by Dan Rubin, he mentioned that this was a legacy of agencies competing with each other in a bid to create the illusion of offering more value for money. Over the years, I’ve realized that offering more than one solution makes no sense. The reason a client comes to you as a designer is because you’re the person than can get it right. If I were to supply three options, I’d be knowingly offering my client at least two options that I didn’t think worked. To this day I still get asked how many homepage design options I’ll supply for the quoted amount. The answer is one. Of course, I’m more than happy to iterate upon the design to fine-tune it and, on the odd occasion, I do revisit a design concept if I just didn’t nail the design first time around. Your time is much better spent refining the right design option than rushing out three substandard designs in the same amount of time. 5. Colour is key There are many contributing factors that go into making a good visual design, but one of the simplest ways to do this is through the use of colour. The colour palette used in a design can have such a profound effect on a visual design that it almost feels like you’re cheating. It’s easy to add more and more subtle shades of colour to add a sense of sophistication and complexity to a design, but it dilutes the overall visual impact. When I design, I almost have a rule that only allows me to use a very limited colour palette. I don’t always stick to it, but it’s always in mind and something I’m constantly reviewing through my design process. 6. Creative thinking is central to good or boundary-pushing web design When we think of creativity in web design we often link this to the visual design, as there is an obvious opportunity to be creative in this area if the brief allows it. Something that I’ve learnt in my time as a web designer is that there’s a massive need for creative thinking in the more technical aspects of web design. The tools we use for building websites are there to be manipulated and used in creative ways to design exciting and engaging user experiences. Great developers are constantly using their creativity to push the boundaries of what can be done with CSS, jQuery and JavaScript. Being creative and creative thinking are things we should embrace as an industry and they are qualities that can be found in anyone, whether they be a visual designer or Rails developer. 7. Creative block: don’t be afraid to get things wrong Creative block can be a killer when designing. It’s often applied to visual design, which is more subjective. I suffer from creative block on a regular basis. It’s hugely frustrating and can screw up your schedule. Having thought about what creative block actually is, I’ve come to the conclusion that it’s actually more of a lack of direction than a lack of ideas. You have ideas and solutions in mind but don’t feel committed to any of them. You’re scared that whatever direction you take, it’ll turn out to be wrong. I’ve found that the best remedy for this is to work through this barrier. It’s a bit like designing with a blindfold on – you don’t really know where you’re going. If you stick to your guns and keep pressing forward I find that, nine times out of ten, this process leads to a solution. As the page begins to fill, the direction you’re looking for slowly begins to take shape. 8. You get better at designing by designing I often get emails asking me what books someone can read to help them become a better designer. There are a lot of good books on subjects like HTML5, CSS, responsive web design and the like, that will really help improve anyone’s web design skills. But, when it comes to visual design, the best way to get better is to design as much as possible. You can’t follow instructions for these things because design isn’t following instructions. A large part of web design is definitely applying a set of widely held conventions, but there’s another part to it that is invention and the only way to get better at this is to do it as much as possible. 9. Self-belief is overrated Throughout our lives we’re told to have self-belief. Self-belief and confidence in what we do, whatever that may be. The problem is that some people find it easier than others to believe in themselves. I’ve spent years trying to convince myself to believe in what I do but have always found it difficult to have complete confidence in my design skills. Self-doubt always creeps in. I’ve realized that it’s ok to doubt myself and I think it might even be a good thing! I’ve realized that it’s my self-doubt that propels me forward and makes me work harder to achieve the best results. The reason I’m sharing this is because I know I’m not the only designer that feels this way. You can spend a lot of time fighting self-doubt only to discover that it’s your body’s natural mechanism to help you do the best job possible. 2011 Mike Kus mikekus 2011-12-11T00:00:00+00:00 https://24ways.org/2011/nine-things-ive-learned/ business
232 Optimize Your Web Design Workflow I’m not sure about you, but I still favour using Photoshop to create my designs for the web. I agree that this application, even with its never-ending feature set, is not the perfect environment to design websites in. The ideal application doesn’t exist yet, however, so until it does it’s maybe not such a bad idea to investigate ways to optimize our workflow. Why use Photoshop? It will probably not come as a surprise if I say that Photoshop and Illustrator are the applications that I know best and feel most comfortable and creative in. Some people prefer Fireworks for web design. Even though I understand people’s motivations, I still prefer Photoshop personally. On the occasions that I gave Fireworks a try, I ended up just using the application to export my images as slices, or to prepare a dummy for the client. For some reason, I’ve never been able to find my way in that app. There were always certain things missing that could only be done in either Photoshop or Illustrator, which bothered me. Why not start in the browser? These days, with CSS3 styling emerging, there are people who find it more efficient to design in the browser. I agree that at a certain point, once the basic design is all set and defined, you can jump right into the code and go from there. But the actual creative part, at least for me, needs to be done in an application such as Photoshop. As a designer I need to be able to create and experiment with shapes on the fly, draw things, move them around, change colours, gradients, effects, and so on. I can’t see me doing this with code. I’m sure if I switch to markup too quickly, I might end up with a rather boxy and less interesting design. Once I start playing with markup, I leave my typical ‘design zone’. My brain starts thinking differently – more rational and practical, if you know what I mean; I start to structure and analyse how to mark up my design in the most efficient semantic way. When I design, I tend to let that go for a bit. I think more freely and not so much about the limitations, as it might hinder my creativity. Now that you know my motivations to stick with Photoshop for the time being, let’s see how we can optimize this beast. Optimize your Photoshop workspace In Photoshop CS5 you have a few default workspace options to choose from which can be found at the top right in the Application Bar (Window > Application Bar). You can set up your panels and palettes the way you want, starting from the ‘Design’ workspace option, and save this workspace for future web work. Here is how I have set up things for when I work on a website design: I have the layers palette open, and I keep the other palettes collapsed. Sometimes, when space permits, I open them all. For designers who work both on print and web, I think it’s worthwhile to save a workspace for both, or for when you’re doing photo retouching. Set up a grid When you work a lot with Shape Layers like I do, it’s really helpful to enable the Grid (View > Show > Grid) in combination with Snap to Grid (View > Snap To > Grid). This way, your vector-based work will be pixel-sharp, as it will always snap to the grid, and so you don’t end up with blurry borders. To set up your preferred grid, go to Preferences > Guides, Grids and Slices. A good setting is to use ‘Gridline Every 10 pixels’ and ‘Subdivision 10’. You can switch it on and off at any time using the shortcut Cmd/Ctrl + ’. It might also help to turn on Smart Guides (View > Show > Smart Guides). Another important tip for making sure your Shape Layer boxes and other shapes are perfectly aligned to the pixel grid when you draw them is to enable Snap to Pixels. This option can be enabled in the Application bar in the Geometry options dropdown menu when you select one of the shape tools from the toolbox. Use Shape Layers To keep your design as flexible as possible, it’s a good thing to use Shape Layers wherever you can as they are scalable. I use them when I design for the iPhone. All my icons, buttons, backgrounds, illustrative graphics – they are all either Smart Objects placed from Illustrator, or Shape Layers. This way, the design is scalable for the retina display. Use Smart Objects Among the things I like a lot in Photoshop are Smart Objects. Smart Objects preserve an image’s source content with all its original characteristics, enabling you to perform non-destructive editing to the layer. For me, this is the ideal way of making my design flexible. For example, a lot of elements are created in Illustrator and are purely vector-based. Placing these elements in Photoshop as Smart Objects (via copy and paste, or dragging from Illustrator into Photoshop) will keep them vector-based and scalable at all times without loss of quality. Another way you could use Smart Objects is whenever you have repeating elements; for example, if you have a stream or list of repeating items. You could, for instance, create one, two or three different items (for the sake of randomness), make each one a Smart Object, and repeat them to create the list. Then, when you have to update, you need only change the Smart Object, and the update will be automatically applied in all its linked instances. Turning photos into Smart Objects before you resize them is also worth considering – you never know when you’ll need that same photo just a bit bigger. It keeps things more flexible, as you leave room to resize the image at a later stage. I use this in combination with the Smart Filters a lot, as it gives me such great flexibility. I usually use Smart Objects as well for the main sections of a web page, which are repeated across different pages of a site. So, for elements such as the header, footer and sidebar, it can be handy for bigger projects that are constantly evolving, where you have to create a lot of different pages in Photoshop. You could save a template page that has the main sections set up as Smart Objects, always in their latest version. Each time you need to create new page, you can start from that template file. If you need to update an existing page because the footer (or sidebar, or header) has been updated, you can drag the updated Smart Object into this page. Although, do I wish Photoshop made it possible to have Smart Objects live as separate files, which are then linked to my different pages. Then, whenever I update the Smart Object, the pages are automatically updated next time I open the file. This is how linked files work in InDesign and Illustrator when you place a external image. Use Layer Comps In some situations, using Layer Comps can come in handy. I try to use them when the design consists of different states; for example, if there are hidden and show states of certain content, such as when content is shown after clicking a certain button. It can be useful to create a Layer Comp for each state. So, when you switch between the two Layer Comps, you’re switching between the two states. It’s OK to move or hide content in each of these states, as well as apply different layer styles. I find this particularly useful when I need to save separate JPEG versions of each state to show to the client, instead of going over all the eye icons in the layers palette to turn the layers’ visibility on or off. Create a set of custom colour swatches I tend to use a distinct colour Swatches palette for each project I work on, by saving a separate Swatches palette in project’s folder (as an .ase file). You can do this through the palette’s dropdown menu, choosing Save Swatches for Exchange. Selecting this option gives you the flexibility to load this palette in other Adobe applications like Illustrator, InDesign or Fireworks. This way, you have the colours of any particular project at hand. I name each colour, using the hexadecimal values. Loading, saving or changing the view of the Swatches palette can be done via the palette’s dropdown menu. My preferred view is ‘Small List’ so I can see the hexadecimal values or other info I have added in the description. I do wish Photoshop had the option of loading several different Styles palettes, so I could have two or more of them open at the same time, but each as a separate palette. This would be handy whenever I switch to another project, as I’m usually working on more than one project in a day. At the moment, you can only add a set of colours to the palette that is already open, which is frustrating and inefficient if you need to update the palette of a project separately. Create a set of custom Styles Just like saving a Swatches palette, I also always save the styles I apply in the Styles palette as a separate Styles file in the project’s folder when I work on a website design or design for iPhone/iPad. During the design process, I can save it each time styles are added. Again, though, it would be great if we could have different Styles palettes open at the same time. Use a scratch file What I also find particularly timesaving, when working on a large project, is using some kind of scratch file. By that, I mean a file that has elements in place that you reuse a lot in the general design. Think of buttons, icons and so on, that you need in every page or screen design. This is great for both web design work and iPad/iPhone work. Use the slice tool This might not be something you think of at first, because you probably associate this way of working with ‘old-school’ table-based techniques. Still, you can apply your slice any way you want, keeping your way of working in mind. Just think about it for a second. If you use the slice tool, and you give each slice its proper filename, you don’t have to worry about it when you need to do updates on the slice or image. Photoshop will remember what the image of that slice is called and which ‘Save for Web’ export settings you’ve used for it. You can also export multiple slices all at once, or export only the ones you need using ‘Save selected slices’. I hope this list of optimization tips was useful, and that they will help you improve and enjoy your time in Photoshop. That is, until the ultimate web design application makes its appearance. Somebody is building this as we speak, right? 2010 Veerle Pieters veerlepieters 2010-12-10T00:00:00+00:00 https://24ways.org/2010/optimize-your-web-design-workflow/ process
166 Performance On A Shoe String Back in the summer, I happened to notice the official Wimbledon All England Tennis Club site had jumped to the top of Alexa’s Movers & Shakers list — a list that tracks sites that have had the biggest upturn or downturn in traffic. The lawn tennis championships were underway, and so traffic had leapt from almost nothing to crazy-busy in a no time at all. Many sites have similar peaks in traffic, especially when they’re based around scheduled events. No one cares about the site for most of the year, and then all of a sudden – wham! – things start getting warm in the data centre. Whilst the thought of chestnuts roasting on an open server has a certain appeal, it’s less attractive if you care about your site being available to visitors. Take a look at this Alexa traffic graph showing traffic patterns for superbowl.com at the beginning of each year, and wimbledon.org in the month of July. Traffic graph from Alexa.com Whilst not on the same scale or with such dramatic peaks, we have a similar pattern of traffic here at 24ways.org. Over the last three years we’ve seen a dramatic pick up in traffic over the month of December (as would be expected) and then a much lower, although steady load throughout the year. What we do have, however, is the luxury of knowing when the peaks will be. For a normal site, be that a blog, small scale web app, or even a small corporate site, you often just cannot predict when you might get slashdotted, end up on the front page of Digg or linked to from a similarly high-profile site. You just don’t know when the peaks will be. If you’re a big commercial enterprise like the Super Bowl, scaling up for that traffic is simply a cost of doing business. But for most of us, we can’t afford to have massive capacity sat there unused for 90% of the year. What you have to do instead is work out how to deal with as much traffic as possible with the modest resources you have. In this article I’m going to talk about some of the things we’ve learned about keeping 24 ways running throughout December, whilst not spending a fortune on hosting we don’t need for 11 months of each year. We’ve not always got it right, but we’ve learned a lot along the way. The Problem To know how to deal with high traffic, you need to have a basic idea of what happens when a request comes into a web server. 24 ways is hosted on a single small virtual dedicated server with a great little hosting company in the UK. We run Apache with PHP and MySQL all on that one server. When a request comes in a new Apache process is started to deal with the request (or assigned if there’s one available not doing anything). Each process takes a bunch of memory, so there’s a finite number of processes that you can run, and therefore a finite number of pages you can serve at once before your server runs out of memory. With our budget based on whatever is left over after beer, we need to get best performance we can out of the resources available. As the goal is to serve as many pages as quickly as possible, there are several approaches we can take: Reducing the amount of memory needed by each Apache process Reducing the amount of time each process is needed Reducing the number of requests made to the server Yahoo! have published some information on what they call Exceptional Performance, which is well worth reading, and compliments many of my examples here. The Yahoo! guidelines very much look at things from a user perspective, which is always important. Server tweaking If you’re in the position of being able to change your server configuration (our set-up gives us root access to what is effectively a virtual machine) there are some basic steps you can take to maximise the available memory and reduce the memory footprint. Without getting too boring and technical (whole books have been written on this) there are a couple of things to watch out for. Firstly, check what processes you have running that you might not need. Every megabyte of memory that you free up might equate to several thousand extra requests being served each day, so take a look at top and see what’s using up your resources. Quite often a machine configured as a web server will have some kind of mail server running by default. If your site doesn’t use mail (ours doesn’t) make sure it’s shut down and not using resources. Secondly, have a look at your Apache configuration and particularly what modules are loaded. The method for doing this varies between versions of Apache, but again, every module loaded increases the amount of memory that each Apache process requires and therefore limits the number of simultaneous requests you can deal with. The final thing to check is that Apache isn’t configured to start more servers than you have memory for. This is usually done by setting the MaxClients directive. When that limit is reached, your site is going to stop responding to further requests. However, if all else goes well that threshold won’t be reached, and if it does it will at least stop the weight of the traffic taking the entire server down to a point where you can’t even log in to sort it out. Those are the main tidbits I’ve found useful for this site, although it’s worth repeating that entire books have been written on this subject alone. Caching Although the site is generated with PHP and MySQL, the majority of pages served don’t come from the database. The process of compiling a page on-the-fly involves quite a few trips to the database for content, templates, configuration settings and so on, and so can be slow and require a lot of CPU. Unless a new article or comment is published, the site doesn’t actually change between requests and so it makes sense to generate each page once, save it to a file and then just serve all following requests from that file. We use QuickCache (or rather a plugin based on it) for this. The plugin integrates with our publishing system (Textpattern) to make sure the cache is cleared when something on the site changes. A similar plugin called WP-Cache is available for WordPress, but of course this could be done any number of ways, and with any back-end technology. The important principal here is to reduce the time it takes to serve a page by compiling the page once and serving that cached result to subsequent visitors. Keep away from your database if you can. Outsource your feeds We get around 36,000 requests for our feed each day. That really only works out at about 7,000 subscribers averaging five-and-a-bit requests a day, but it’s still 36,000 requests we could easily do without. Each request uses resources and particularly during December, all those requests can add up. The simple solution here was to switch our feed over to using FeedBurner. We publish the address of the FeedBurner version of our feed here, so those 36,000 requests a day hit FeedBurner’s servers rather than ours. In addition, we get pretty graphs showing how the subscriber-base is building. Off-load big files Larger files like images or downloads pose a problem not in bandwidth, but in the time it takes them to transfer. A typical page request is very quick, a few seconds at the most, resulting in the connection being freed up promptly. Anything that keeps a connection open for a long time is going to start killing performance very quickly. This year, we started serving most of the images for articles from a subdomain – media.24ways.org. Rather than pointing to our own server, this subdomain points to an Amazon S3 account where the files are held. It’s easy to pigeon-hole S3 as merely an online backup solution, and whilst not a fully fledged CDN, S3 works very nicely for serving larger media files. The roughly 20GB of files served this month have cost around $5 in Amazon S3 charges. That’s so affordable it may not be worth even taking the files back off S3 once December has passed. I found this article on Scalable Media Hosting with Amazon S3 to be really useful in getting started. I upload the files via a Firefox plugin (mentioned in the article) and then edit the ACL to allow public access to the files. The way S3 enables you to point DNS directly at it means that you’re not tied to always using the service, and that it can be transparent to your users. If your site uses photographs, consider uploading them to a service like Flickr and serving them directly from there. Many photo sharing sites are happy for you to link to images in this way, but do check the acceptable use policies in case you need to provide a credit or link back. Off-load small files You’ll have noticed the pattern by now – get rid of as much traffic as possible. When an article has a lot of comments and each of those comments has an avatar along with it, a great many requests are needed to fetch each of those images. In 2006 we started using Gravatar for avatars, but their servers were slow and were holding up page loads. To get around this we started caching the images on our server, but along with that came the burden of furnishing all the image requests. Earlier this year Gravatar changed hands and is now run by the same team behind WordPress.com. Those guys clearly know what they’re doing when it comes to high performance, so this year we went back to serving avatars directly from them. If your site uses avatars, it really makes sense to use a service like Gravatar where your users probably already have an account, and where the image requests are going to be dealt with for you. Know what you’re paying for The server account we use for 24 ways was opened in November 2005. When we first hit the front page of Digg in December of that year, we upgraded the server with a bit more memory, but other than that we were still running on that 2005 spec for two years. Of course, the world of technology has moved on in those years, prices have dropped and specs have improved. For the same amount we were paying for that 2005 spec server, we could have an account with twice the CPU, memory and disk space. So in November of this year I took out a new account and transferred the site from the old server to the new. In that single step we were prepared for dealing with twice the amount of traffic, and because of a special offer at the time I didn’t even have to pay the setup cost on the new server. So it really pays to know what you’re paying for and keep an eye out of ways you can make improvements without needing to spend more money. Further steps There’s nearly always more that can be done. For example, there are some media files (particularly for older articles) that are not on S3. We also serve our CSS directly and it’s not minified or compressed. But by tackling the big problems first we’ve managed to reduce load on the server and at the same time make sure that the load being placed on the server can be dealt with in the most frugal way. Over the last 24 days we’ve served up articles to more than 350,000 visitors without breaking a sweat. On a busy day, that’s been nearly 20,000 visitors in just 24 hours. While in the grand scheme of things that’s not a huge amount of traffic, it can be a lot if you’re not prepared for it. However, with a little planning for the peaks you can help ensure that when the traffic arrives you’re ready to capitalise on it. Of course, people only visit 24 ways for the wealth of knowledge and experience that’s tied up in the articles here. Therefore I’d like to take the opportunity to thank all our authors this year who have given their time as a gift to the community, and to wish you all a very happy Christmas. 2007 Drew McLellan drewmclellan 2007-12-24T00:00:00+00:00 https://24ways.org/2007/performance-on-a-shoe-string/ ux
134 Photographic Palettes How many times have you seen a colour combination that just worked, a match so perfect that it just seems obvious? Now, how many times do you come up with those in your own work? A perfect palette looks easy when it’s done right, but it’s often maddeningly difficult and time-consuming to accomplish. Choosing effective colour schemes will always be more art than science, but there are things you can do that will make coming up with that oh-so-smooth palette just a little a bit easier. A simple trick that can lead to incredibly gratifying results lies in finding a strong photograph and sampling out particularly harmonious colours. Photo Selection Not all photos are created equal. You certainly want to start with imagery that fits the eventual tone you’re attempting to create. A well-lit photo of flowers might lead to a poor colour scheme for a funeral parlour’s web site, for example. It’s worth thinking about what you’re trying to say in advance, and finding a photo that lends itself to your message. As a general rule of thumb, photos that have a lot of neutral or de-saturated tones with one or two strong colours make for the best palette; bright and multi-coloured photos are harder to derive pleasing results from. Let’s start with a relatively neutral image. Sampling In the above example, I’ve surrounded the photo with three different background colours directly sampled from the photo itself. Moving from left to right, you can see how each of the sampled colours is from an area of increasingly smaller coverage within the photo, and yet there’s still a strong harmony between the photo and the background image. I don’t really need to pick the big obvious colours from the photo to create that match, I can easily concentrate on more interesting colours that might work better for what I intend. Using a similar palette, let’s apply those colour choices to a more interesting layout: In this mini-layout, I’ve re-used the same tan colour from the previous middle image as a background, and sampled out a nicely matching colour for the top and bottom overlays, as well as the two different text colours. Because these colours all fall within a narrow range, the overall balance is harmonious. What if I want to try something a little more daring? I have a photo of stacked chairs of all different colours, and I’d like to use a few more of those. No problem, provided I watch my colour contrast: Though it uses varying shades of red, green, and yellow, this palette actually works because the values are even, and the colours muted. Placing red on top of green is usually a hideous combination of death, but if the green is drab enough and the red contrasts well enough, the result can actually be quite pleasing. I’ve chosen red as my loudest colour in this palette, and left green and yellow to play the quiet supporting roles. Obviously, there are no hard and fast rules here. You might not want to sample absolutely every colour in your scheme from a photo. There are times where you’ll need a variation that’s just a little bit lighter, or a blue that’s not in the photo. You might decide to start from a photo base and tweak, or add in colours of your own. That’s okay too. Tonal Variations I’ll leave you with a final trick I’ve been using lately, a way to bring a bit more of a formula into the equation and save some steps. Starting with the same base palette I sampled from the chairs, in the above image I’ve added a pair of overlaying squares that produce tonal variations of each primary. The lighter variation is simply a solid white square set to 40% opacity, the darker one is a black square at 20%. That gives me a highlight and shadow for each colour, which would prove handy if I had to adapt this colour scheme to a larger layout. I could add a few more squares of varying opacities, or adjust the layer blending modes for different effects, but as this looks like a great place to end, I’ll leave that up to your experimental whims. Happy colouring! 2006 Dave Shea daveshea 2006-12-22T00:00:00+00:00 https://24ways.org/2006/photographic-palettes/ design
336 Practical Microformats with hCard You’ve probably heard about microformats over the last few months. You may have even read the easily digestible introduction at Digital Web Magazine, but perhaps you’ve not found time to actually implement much yet. That’s understandable, as it can sometimes be difficult to see exactly what you’re adding by applying a microformat to a page. Sure, you’re semantically enhancing the information you’re marking up, and the Semantic Web is a great idea and all, but what benefit is it right now, today? Well, the answer to that question is simple: you’re adding lots of information that can be and is being used on the web here and now. The big ongoing battle amongst the big web companies if one of territory over information. Everyone’s grasping for as much data as possible. Some of that information many of us are cautious to give away, but a lot of is happy to be freely available. Of the data you’re giving away, it makes sense to give it as much meaning as possible, thus enabling anyone from your friends and family to the giant search company down the road to make the most of it. Ok, enough of the waffle, let’s get working. Introducing hCard You may have come across hCard. It’s a microformat for describing contact information (or really address book information) from within your HTML. It’s based on the vCard format, which is the format the contacts/address book program on your computer uses. All the usual fields are available – name, address, town, website, email, you name it. If you’re running Firefox and Greasemonkey (or if you can, just to try this out), install this user script. What it does is look for instances of the hCard microformat in a page, and then add in a link to pass any hCards it finds to a web service which will convert it to a vCard. Take a look at the About the author box at the bottom of this article. It’s a hCard, so you should be able to click the icon the user script inserts and add me to your Outlook contacts or OS X Address Book with just a click. So microformats are useful after all. Free microformats all round! Implementing hCard This is the really easy bit. All the hCard microformat is, is a bunch of predefined class names that you apply to the markup you’ve probably already got around your contact information. Let’s take the example of the About the author box from this article. Here’s how the markup looks without hCard: <div class="bio"> <h3>About the author</h3> <p>Drew McLellan is a web developer, author and no-good swindler from just outside London, England. At the <a href="http://www.webstandards.org/">Web Standards Project</a> he works on press, strategy and tools. Drew keeps a <a href="http://www.allinthehead.com/">personal weblog</a> covering web development issues and themes.</p> </div> This is a really simple example because there’s only two key bits of address book information here:- my name and my website address. Let’s push it a little and say that the Web Standards Project is the organisation I work for – that gives us Name, Company and URL. To kick off an hCard, you need a containing object with a class of vcard. The div I already have with a class of bio is perfect for this – all it needs to do is contain the rest of the contact information. The next thing to identify is my name. hCard uses a class of fn (meaning Full Name) to identify a name. As is this case there’s no element surrounding my name, we can just use a span. These changes give us: <div class="bio vcard"> <h3>About the author</h3> <p><span class="fn">Drew McLellan</span> is a web developer... The two remaining items are my URL and the organisation I belong to. The class names designated for those are url and org respectively. As both of those items are links in this case, I can apply the classes to those links. So here’s the finished hCard. <div class="bio vcard"> <h3>About the author</h3> <p><span class="fn">Drew McLellan</span> is a web developer, author and no-good swindler from just outside London, England. At the <a class="org" href="http://www.webstandards.org/">Web Standards Project</a> he works on press, strategy and tools. Drew keeps a <a class="url" href="http://www.allinthehead.com/">personal weblog</a> covering web development issues and themes.</p> </div> OK, that was easy. By just applying a few easy class names to the HTML I was already publishing, I’ve implemented an hCard that right now anyone with Greasemonkey can click to add to their address book, that Google and Yahoo! and whoever else can index and work out important things like which websites are associated with my name if they so choose (and boy, will they so choose), and in the future who knows what. In terms of effort, practically nil. Where next? So that was a trivial example, but to be honest it doesn’t really get much more complex even with the most pernickety permutations. Because hCard is based on vCard (a mature and well thought-out standard), it’s all tried and tested. Here’s some good next steps. Play with the hCard Creator Take a deep breath and read the spec Start implementing hCard as you go on your own projects – it takes very little time hCard is just one of an ever-increasing number of microformats. If this tickled your fancy, I suggest subscribing to the microformats site in your RSS reader to keep in touch with new developments. What’s the take-away? The take-away is this. They may sound like just more Web 2-point-HoHoHo hype, but microformats are a well thought-out, and easy to implement way of adding greater depth to the information you publish online. They have some nice benefits right away – certainly at geek-level – but in the longer term they become much more significant. We’ve been at this long enough to know that the web has a long, long memory and that what you publish today will likely be around for years. But putting the extra depth of meaning into your documents now you can help guard that they’ll continue to be useful in the future, and not just a bunch of flat ASCII. 2005 Drew McLellan drewmclellan 2005-12-06T00:00:00+00:00 https://24ways.org/2005/practical-microformats-with-hcard/ code
312 Preparing to Be Badass Next Year Once we’ve eaten our way through the holiday season, people will start to think about new year’s resolutions. We tend to focus on things that we want to change… and often things that we don’t like about ourselves to “fix”. We set rules for ourselves, or try to start new habits or stop bad ones. We focus in on things we will or won’t do. For many of us the list of things we “ought” to be spending time on is just plain overwhelming – family, charity/community, career, money, health, relationships, personal development. It’s kinda scary even just listing it out, isn’t it? I want to encourage you to think differently about next year. The 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. When we help the user be badass, then we are really making a difference. I 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? In what ways do you want to be more badass next year? A professional lens Though 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. So let’s talk about a scaffold to help you figure out your professional / career development next year. First 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 “Today I am aiming for just south of mediocre, and if I can mess up everybody else’s ability to do good work then that will be just perfect2”. Ergo, you want to be awesome. So what does awesome look like? Danger! The big trap that people fall into when think about their professional development is to immediately focus on the things that they aren’t good at. When you ask people “what do you want to work on getting better at next year?” they frequently gravitate to the things that they believe they are bad at. Why 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 → mediocre at a given skill / behaviour takes a bunch of time and energy. So if you spend all your time going from bad → mediocre at things, what do you think you end up? That’s right, mediocre. Mediocrity is not a great career goal, kids. What do you already rock at? The much better investment of time and energy is to go from good → 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. Then figure out how to double down on those things. What does brilliant look like for a given skill? What’s the knowledge or practice that you need to level yourself up even further in that thing? But what if I really really suck? Admittedly, sometimes something you suck at really is holding you back. But it’s important to separate out weaknesses (just something you suck at) from controlling weaknesses (something you suck at that actually matters for your chosen career). If skill x is just not an important thing for you to be good at, you may never need to care that you aren’t 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’s worth investing your time and energy (and possibly money too) getting better at it. So when you look at the things that you aren’t good at, which of those are actually essential for success? The right ratio A 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 → mediocre. Levelling up learning So once you’ve figured out your areas you want to focus on next year, what do you actually decide to do? Most 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 – you get to try something, see if it works, learn from it, rinse and repeat. It’s also about balance: you want to be challenged enough for work to be interesting, without it being so hard it’s 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’s boring. Continuously getting better at things you are already good at is actually both easier and harder than it sounds. The advantage is that it’s pretty easy to add the feedback loop to make sure that you are improving; the disadvantage is that you’re already good at these skills so you could easily just “do” without ever stopping to reflect and improve. Build in time for personal retrospectives (“What went well? What didn’t? What one thing will I choose to change next time?”) and find a way of getting feedback from outside sources as well. As for the new skills, it’s worth knowing that skill development follows a particular pattern: We all start out unconsciously incompetent (we don’t know what to do and if we tried we’d unwittingly get it wrong), progress on to conscious incompetence (we now know we’re doing it wrong) then conscious competence (we’re doing it right but wow it takes effort and attention) and eventually get to unconscious competence (automatically getting it right). Your 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. What about keeping up? Everything 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. Which 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? Whatever your learning style though, remember that there are three real needs: Scan the landscape (what’s changing, does it matter) Gain the knowledge or skills (get the detail) Apply the knowledge or skills (use it in reality) When you remember that you need all three of these things it can help you get more of what you do. For 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. In summary Aim to be awesome (mediocrity is not a career goal). Figure out what you already rock at. Only care about stuff you suck at that matters for your career. Pick three things to go from good → awesome and one thing to go from bad → mediocre (or mediocre → good) this year. Design learning into your daily work. Scan the landscape, learn new stuff, apply it for real. Be badass! She wrote a whole book about it. You should read it: Badass: Making Users Awesome ↩ Before you argue too vehemently: I suppose some antisocial sociopathic bastards do exist. Identify them, and then RUN AWAY FAST AS YOU CAN #realtalk ↩ 2016 Meri Williams meriwilliams 2016-12-22T00:00:00+00:00 https://24ways.org/2016/preparing-to-be-badass-next-year/ business
3 Project Hubs: A Home Base for Design Projects SCENE: A design review meeting. Laptop screens. Coffee cups. Project manager: Hey, did you get my email with the assets we’ll be discussing? Client: I got an email from you, but it looks like there’s no attachment. PM: Whoops! OK. I’m resending the files with the attachments. Check again? Client: OK, I see them. It’s homepage_v3_brian-edits_FINAL_for-review.pdf, right? PM: Yeah, that’s the one. Client: OK, hang on, Bill’s going to print them out. (3-minute pause. Small talk ensues.) Client: Alright, Bill’s back. We’re good to start. Brian: Oh, actually those homepage edits we talked about last time are in the homepage_v4_brian_FINAL_v2.pdf document that I posted to Basecamp earlier today. Client: Oh, OK. What message thread was that in? Brian: Uh, I’m pretty sure it’s in “Homepage Edits and Holiday Schedule.” Client: Alright, I see them. Bill’s going back to the printer. Hang on a sec… This is only a slightly exaggerated version of my experience in design review meetings. The design project dance is a sloppy one. It involves a slew of email attachments, PDFs, PSDs, revisions, GitHub repos, staging environments, and more. And while tools like Basecamp can help manage all these moving parts, it can still be incredibly challenging to extract only the important bits, juggle deliverables, and see how your project is progressing. Enter project hubs. Project hubs A project hub consolidates all the key design and development materials onto a single webpage presented in reverse chronological order. The timeline lives online (either publicly available or password protected), so that everyone involved in the team has easy access to it. A project hub. I was introduced to project hubs after seeing Dan Mall’s open redesign of Reading Is Fundamental. Thankfully, I had a chance to work with Dan on two projects where I got to see firsthand how beneficial a project hub can be. Here’s what makes a project hub great: Serves as a centralized home base for the project Trains clients and teams to decide in the browser Easily and visually view project’s progress Provides an archive for project artifacts A home base Your clients and colleagues can expect to get the latest and greatest updates to your project when visiting the project hub, the same way you’d expect to get the latest information on a requested topic when you visit a Wikipedia page. That’s the beauty of URIs that don’t change. Creating a project hub reduces a ton of email volley nonsense, and eliminates the need to produce files and directories with staggeringly ridiculous names like design/12.13.13/team/brian/for_review/_FINAL/styletile_121313_brian-edits-final_v2_FINAL.pdf. The team can simply visit the project hub’s URL and click the link to whatever artifact they need. Need to make an update? Simply update the link on the project hub. No more email tango and silly file names. Deciding in the browser Let’s change the phrase “designing in the browser” to “deciding in the browser.” Dan Mall We make websites, but all too often we find ourselves looking at web design artifacts in abstractions. We email PDFs to each other, glance at mockup JPGs on our desktops, and of course kill trees in order to print out designs so that we can scribble in the margins. All of these practices subtly take everyone further and further away from the design’s eventual final resting place: the browser. Because a project hub is just a simple webpage, reviewing designs is as easy as clicking some links, which keep your clients and teams in the browser. You can keep people in the browser with yet another clever trick from the wily Dan Mall: instead of sending clients PDFs or JPGs, he created a simple webpage and tossed his static visuals into the template (you can view an example here). This forces clients to review web design work in the browser rather than launching a PDF viewer or Preview. Now this all might sound trivial to you (“Of course my client knows that we’re designing a website!”), but keeping the design artifacts in the browser subconsciously helps remind everyone of the medium for which you’re designing, which helps everyone focus on the right aspects of the design and have the right conversations. Progress over time When you’re in the trenches, it’s often hard to visualize how a project is progressing. Tools like Basecamp include discussions, files, to-dos, and more, which are all great tools but also make things a bit noisy. Project hubs provide you and your clients a quick and easy way to see at a glance how things are coming along. Teams can rest assured they’re viewing the most current versions of designs, and managers can share progress with stakeholders simply by providing a link to the project hub. Over time, a project hub becomes an easily accessible archive of all the design decisions, which makes it easy to compare and contrast different versions of designs and prototypes. Setting up a project hub Setting up your own project hub is pretty simple. Simply create a webpage with some basic styles and branding. I’ve created a project hub template that’s available on GitHub if you want a jump-start. Publish the webpage to a URL somewhere that makes sense (we’ve found that a subdomain of your site works quite well) and share it with everyone involved in the project. Bookmark it. Let everyone know that this is where design updates will be shared, and that they can always come back to the project hub to track the project’s progress. When it comes time to share new updates, simply add a new node to the timeline and republish the webpage. Simple FTPing works just fine, but it might make sense to keep track of changes using version control. Our project hub for our open redesign of the Pittsburgh Food Bank is managed on GitHub, which means that I can make edits to the hub right from GitHub. Thanks to the magical wizardry of webhooks, I can automatically deploy the project hub so that everything stays in sync. That’s the fancy-pants way to do it, and is certainly not a requirement. As long as you’re able to easily make edits and keep your project hub up to date, you’re good to go. So that’s the hubbub Project hubs can help tame the chaos of the design process by providing a home base for all key design and development materials. Keep the design artifacts in the browser and give clients and colleagues quick insight into your project’s progress. Happy hubbing! 2013 Brad Frost bradfrost 2013-12-17T00:00:00+00:00 https://24ways.org/2013/project-hubs/ process
297 Public Speaking with a Buddy 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. Though it didn’t 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! To some, adding more people to a presentation sounds like a recipe for on-stage disaster. To others, having a friendly face nearby—a partner who can step in if you fumble—is incredibly reassuring. As design director Yesenia Perez-Cruz writes, “While public speaking is a deeply personal activity, you don’t have to go it alone. Nothing has helped my speaking career more than turning it into a group effort.” Co-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. For 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. Moreover, 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 “I don’t know” 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—and the presentation!—significantly better. Co-presenting won’t work if you don’t trust the person you’re onstage with, or if you don’t have good chemistry working together. It might also not work if there’s an imbalance of responsibilities, both in preparing the talk and giving it. Read on for how to make partner talks work to your advantage! Trustworthiness If 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’t being helpful. We’re all about reducing the fears and stress levels surrounding being in that spotlight onstage; make sure that the person you’re relying on isn’t making the process harder. Before you start working together, sketch out the breakdown of work and timeline you’re 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’s 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’s work style or deliverable needs to be tweaked. This should be a partnership in which you both feel supported; it’s healthy to set all these expectations up front, and create a space in which you can each tweak things as the work progresses. Talk flow and responsibilities There 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—are 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? If you’re 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? Rehearse how handoffs will go between sections so it feels natural, rather than stilted. I like breaking a presentation into “chapters” when I’m passionate about particular aspects of a topic and can speak on those, but know that there are other aspects to be shared and there’s someone else who can handle (and enjoy!) talking about them. When Destiny and I rehearsed our “chapter” handoffs, we developed little jingles that we’d 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. .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%; } Alternatively, you can give the presentation in a way that’s close to having a rehearsed conversation, rather than independently presenting discrete parts of the talk. In this case, you’ll 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’re both holding microphones; also figure out how you’ll be standing in relation to each other. More on that next! Sharing the stage If you choose to give a talk with a partner, determine ahead of time how you’ll stand (or sit). For example, if you each take “chapters” or major sections of the presentation, ensure that it’s 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’re not distracting to the audience; you don’t 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’t just open your laptop and ignore what’s happening! Feel free to smile, laugh, or react how the audience should be reacting as your partner is speaking. If you’re both sharing the spotlight at the same time and having a rehearsed conversation, make sure that your body language engages the audience and you’re 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. Consider whether or not you will share a microphone, or if you will both be mic’d. (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’d like to handle Q&A time during or after the talk, especially if you have clear “chapters” 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. Co-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. 2016 Lara Hogan larahogan 2016-12-06T00:00:00+00:00 https://24ways.org/2016/public-speaking-with-a-buddy/ process
218 Put Yourself in a Corner Some backstory, and a shameful confession For the first couple years of high school I was one of those jerks who made only the minimal required effort in school. Strangely enough, how badly I behaved in a class was always in direct proportion to how skilled I was in the subject matter. In the subjects where I was confident that I could pass without trying too hard, I would give myself added freedom to goof off in class. Because I was a closeted lit-nerd, I was most skilled in English class. I’d devour and annotate required reading over the weekend, I knew my biblical and mythological allusions up and down, and I could give you a postmodern interpretation of a text like nobody’s business. But in class, I’d sit in the back and gossip with my friends, nap, or scribble patterns in the margins of my textbooks. I was nonchalant during discussion, I pretended not to listen during lectures. I secretly knew my stuff, so I did well enough on tests, quizzes, and essays. But I acted like an ass, and wasn’t getting the most I could out of my education. The day of humiliation, but also epiphany One day in Ms. Kaney’s AP English Lit class, I was sitting in the back doodling. An earbud was dangling under my sweater hood, attached to the CD player (remember those?) sitting in my desk. Because of this auditory distraction, the first time Ms. Kaney called my name, I barely noticed. I definitely heard her the second time, when she didn’t call my name so much as roar it. I can still remember her five feet frame stomping across the room and grabbing an empty desk. It screamed across the worn tile as she slammed it next to hers. She said, “This is where you sit now.” My face gets hot just thinking about it. I gathered my things, including the CD player (which was now impossible to conceal), and made my way up to the newly appointed Seat of Shame. There I sat, with my back to the class, eye-to-eye with Ms. Kaney. From my new vantage point I couldn’t see my friends, or the clock, or the window. All I saw were Ms. Kaney’s eyes, peering at me over her reading glasses while I worked. In addition to this punishment, I was told that from now on, not only would I participate in class discussions, but I would serve detention with her once a week until an undetermined point in the future. During these detentions, Ms. Kaney would give me new books to read, outside the curriculum, and added on to my normal homework. They ranged from classics to modern novels, and she read over my notes on each book. We’d discuss them at length after class, and I grew to value not only our private discussions, but the ones in class as well. After a few weeks, there wasn’t even a question of this being punishment. It was heaven, and I was more productive than ever. To the point Please excuse this sentimental story. It’s not just about honoring a teacher who cared enough to change my life, it’s really about sharing a lesson. The most valuable education Ms. Kaney gave me had nothing to do with literature. She taught me that I (and perhaps other people who share my special brand of crazy) need to be put in a corner to flourish. When we have physical and mental constraints applied, we accomplish our best work. For those of you still reading, now seems like a good time to insert a pre-emptive word of mediation. Many of you, maybe all of you, are self-disciplined enough that you don’t require the rigorous restrictions I use to maximize productivity. Also, I know many people who operate best in a stimulating and open environment. I would advise everyone to seek and execute techniques that work best for them. But, for those of you who share my inclination towards daydreams and digressions, perhaps you’ll find something useful in the advice to follow. In which I pretend to be Special Agent Olivia Dunham Now that I’m an adult, and no longer have Ms. Kaney to reign me in, I have to find ways to put myself in the corner. By rejecting distraction and shaping an environment designed for intense focus, I’m able to achieve improved productivity. Lately I’ve been obsessed with the TV show Fringe, a sci-fi series about an FBI agent and her team of genius scientists who save the world (no, YOU’RE a nerd). There’s a scene in the show where the primary character has to delve into her subconscious to do extraordinary things, and she accomplishes this by immersing herself in a sensory deprivation tank. The premise is this: when enclosed in a space devoid of sound, smell, or light, she will enter a new plane of consciousness wherein she can tap into new levels of perception. This might sound a little nuts, but to me this premise has some real-world application. When I am isolated from distraction, and limited to only the task at hand, I’m able to be productive on a whole new level. Since I can’t actually work in an airtight iron enclosure devoid of input, I find practical ways to create an interruption-free environment. Since I work from home, many of my methods for coping with distractions wouldn’t be necessary for my office-bound counterpart. However for some of you 9-to-5-ers, the principles will still apply. Consider your visual input First, I have to limit my scope to the world I can (and need to) affect. In the largest sense, this means closing my curtains to the chaotic scene of traffic, birds, the post office, a convenience store, and generally lovely weather that waits outside my window. When the curtains are drawn and I’m no longer surrounded by this view, my sphere is reduced to my desk, my TV, and my cat. Sometimes this step alone is enough to allow me to focus. But, my visual input can be whittled down further still. For example, the desk where I usually keep my laptop is littered with twelve owl figurines, a globe, four books, a three-pound weight, and various nerdy paraphernalia (hard drives, Wacom tablets, unnecessary bluetooth accessories, and so on). It’s not so much a desk as a dumping ground for wacky flea market finds and impulse technology buys. Therefore, in addition to this Official Desk, I have an adult version of Ms. Kaney’s Seat of Shame. It’s a rusty old student’s desk I picked up at the Salvation Army, almost an exact replica of the model Ms. Kaney dragged across the classroom all those years ago. This tiny reproduction Seat of Shame is literally in a corner, where my only view is a blank wall. When I truly need to focus, this is where I take refuge, with only a notebook and a pencil (and occasionally an iPad). Find out what works for your ears Even from my limited sample size of two people, I know there are lots of different ways to cope with auditory distraction. I prefer silence when focused on independent work, and usually employ some form of a white noise generator. I’ve yet to opt for the fancy ‘real’ white noise machines; instead, I use a desktop fan or our allergy filter machine. This is usually sufficient to block out the sounds of the dishwasher and the cat, which allows me to think only about the task of hand. My boyfriend, the other half of my extensive survey, swears by another method. He calls it The Wall of Sound, and it’s basically an intense blast of raucous music streamed directly into his head. The outcome of his technique is really the same as mine; he’s blocking out unexpected auditory input. If you can handle the grating sounds of noisy music while working, I suggest you give The Wall of Sound a try. Don’t count the minutes When I sat in the original Seat of Shame in lit class, I could no longer see the big classroom clock slowly ticking away the seconds until lunch. Without the marker of time, the class period often flew by. The same is true now when I work; the less aware of time I am, the less it feels like time is passing too quickly or slowly, and the more I can focus on the task (not how long it takes). Nowadays, to assist in my effort to forget the passing of time, I sometimes put a sticky note over the clock on my monitor. If I’m writing, I’ll use an app like WriteRoom, which blocks out everything but a simple text editor. There are situations when it’s not advisable to completely lose track of time. If I’m working on a project with an hourly rate and a tight scope, or if I need to be on time to a meeting or call, I don’t want to lose myself in the expanse of the day. In these cases, I’ll set an alarm that lets me know it’s time to reign myself back in (or on some days, take a shower). Put yourself in a mental corner, too When Ms. Kaney took action and forced me to step up my game, she had the insight to not just change things physically, but to challenge me mentally as well. She assigned me reading material outside the normal coursework, then upped the pressure by requiring detailed reports of the material. While this additional stress was sometimes uncomfortable, it pushed me to work harder than I would have had there been less of a demand. Just as there can be freedom in the limitations of a distraction-free environment, I’d argue there is liberty in added mental constraints as well. Deadlines as a constraint Much has been written about the role of deadlines in the creative process, and they seem to serve different functions in different cases. I find that deadlines usually act as an important constraint and, without them, it would be nearly impossible for me to ever consider a project finished. There are usually limitless ways to improve upon the work I do and, if there’s no imperative for me to be done at a certain point, I will revise ad infinitum. (Hence, the personal site redesign that will never end – Coming Soon, Forever!). But if I have a clear deadline in mind, there’s a point when the obsessive tweaking has to stop. I reach a stage where I have to gather up the nerve to launch the thing. Putting the pro in procrastination Sometimes I’ve found that my tendency to procrastinate can help my productivity. (Ducks, as half the internet throws things at her.) I understand the reasons why procrastination can be harmful, and why it’s usually a good idea to work diligently and evenly towards a goal. I try to divide my projects up in a practical way, and sometimes I even pull it off. But for those tasks where you work aimlessly and no focus comes, or you find that every other to-do item is more appealing, sometimes you’re forced to bring it together at the last moment. And sometimes, this environment of stress is a formula for magic. Often when I’m down to the wire and have no choice but to produce, my mind shifts towards a new level of clarity. There’s no time to endlessly browse for inspiration, or experiment with convoluted solutions that lead nowhere. Obviously a life lived perpetually on the edge of a deadline would be a rather stressful one, so it’s not a state of being I’d advocate for everyone, all the time. But every now and then, the work done when I’m down to the wire is my best. Keep one toe outside your comfort zone When I’m choosing new projects to take on, I often seek out work that involves an element of challenge. Whether it’s a design problem that will require some creative thinking, or a coding project that lends itself to using new technology like HTML5, I find a manageable level of difficulty to be an added bonus. The tension that comes from learning a new skill or rethinking an old standby is a useful constraint, as it keeps the work interesting, and ensures that I continue learning. There you have it Well, I think I’ve spilled most of my crazy secrets for forcing my easily distracted brain to focus. As with everything we web workers do, there are an infinite number of ways to encourage productivity. I hope you’ve found a few of these to be helpful, and please share your personal techniques in the comments. Have a happy and productive new year! 2010 Meagan Fisher meaganfisher 2010-12-20T00:00:00+00:00 https://24ways.org/2010/put-yourself-in-a-corner/ process
27 Putting Design on the Map The web can leave us feeling quite detached from the real world. Every site we make is really just a set of abstract concepts manifested as tools for communication and expression. At any minute, websites can disappear, overwritten by a newfangled version or simply gone. I think this is why so many of us have desires to create a product, write a book, or play with the internet of things. We need to keep in touch with the physical world and to prove (if only to ourselves) that we do make real things. I could go on and on about preserving the web, the challenges of writing a book, or thoughts about how we can deal with the need to make real things. Instead, I’m going to explore something that gives us a direct relationship between a website and the physical world – maps. A map does not just chart, it unlocks and formulates meaning; it forms bridges between here and there, between disparate ideas that we did not know were previously connected. Reif Larsen, The Selected Works of T.S. Spivet The simplest form of map on a website tends to be used for showing where a place is and often directions on how to get to it. That’s an incredibly powerful tool. So why is it, then, that so many sites just plonk in a default Google Map and leave it as that? You wouldn’t just use dark grey Helvetica on every site, would you? Where’s the personality? Where’s the tailored experience? Where is the design? Jumping into design Let’s keep this simple – we all want to be better web folk, not cartographers. We don’t need to go into the history, mathematics or technology of map making (although all of those areas are really interesting to research). For the sake of our sanity, I’m going to gloss over some of the technical areas and focus on the practical concepts. Tiles If you’ve ever noticed a map loading in sections, it’s because it uses tiles that are downloaded individually instead of requiring the user to download everything that they might need. These tiles come in many styles and can be used for anything that covers large areas, such as base maps and data. You’ve seen examples of alternative base maps when you use Google Maps as Google provides both satellite imagery and road maps, both of which are forms of base maps. They are used to provide context for the real world, or any other world for that matter. A marker on a blank page is useless. The tiles are representations of the physical; they do not have to be photographic imagery to provide context. This means you can design the map itself. The easiest way to conceive this is by comparing Google’s road maps with Ordnance Survey road maps. Everything about the two maps is different: the colours, the label fonts and the symbols used. Yet they still provide the exact same context (other maps may provide different context such as terrain contours). Comparison of Google Maps (top) and the Ordnance Survey (bottom). Carefully designing the base map tiles is as important as any other part of the website. The most obvious, yet often overlooked, aspect are aesthetics and branding. Maps could fit in with the rest of the site; for example, by matching the colours and line weights, they can enhance the full design rather than inhibiting it. You’re also able to define the exact purpose of the map, so instead of showing everything you could specify which symbols or labels to show and hide. I’ve not done any real research on the accessibility of base maps but, having looked at some of the available options, I think a focus on the typography of labels and the colour of the various elements is crucial. While you can choose to hide labels, quite often they provide the data required to make sense of the map. Therefore, make sure each zoom level is not too cluttered and shows enough to give context. Also be as careful when choosing the typeface as you are in any other design work. As for colour, you need to pay closer attention to issues like colour-blindness when using colour to convey information. Quite often a spectrum of colour will be used to show data, or to show the topography, so you need to be aware that some people struggle to see colour differences within a spectrum. A nice example of a customised base map can be found on Michael K Owens’ check-in pages: One of Michael K Owens’ check-in pages. As I’ve already mentioned, tiles are not just for base maps: they are also for data. In the screenshot below you can see how Plymouth Marine Laboratory uses tiles to show data with a spectrum of colour. A map from the Marine Operational Ecology data portal, showing data of adult cod in the North Sea. Technical You’re probably wondering how to design the base layers. I will briefly explain the concepts here and give you tools to use at the end of the article. If you’re worried about the time it takes to design the maps, don’t be – you can automate most of it. You don’t need to manually draw each tile for the entire world! We’ve learned the importance of web standards the hard way, so you’ll be glad (and I won’t have to explain the advantages) of the standard for web mapping from the Open Geospatial Consortium (OGC) called the Web Map Service (WMS). You can use conventional file formats for the imagery but you need a way to query for the particular tiles to show for the area and zoom level, that is what WMS does. Features Tiles are great for covering large areas but sometimes you need specific smaller areas. We call these features and they usually consist of polygons, lines or points. Examples include postcode boundaries and routes between places, or even something more dynamic such as borders of nations changing over time. Showing features on a map presents interesting design challenges. If the colour or shape conveys some kind of data beyond geographical boundaries then it needs to be made obvious. This is actually really hard, without building complicated user interfaces. For example, in the image below, is it obvious that there is a relationship between the colours? Does it need a way of showing what the colours represent? Choropleth map showing ranked postcode areas, using ViziCities. Features are represented by means of lines or colors; and the effective use of lines or colors requires more than knowledge of the subject – it requires artistic judgement. Erwin Josephus Raisz, cartographer (1893–1968) Where lots of boundaries are small and close together (such as a high street or shopping centre) will it be obvious where the boundaries are and what they represent? When designing maps, the hardest challenge is dealing with how the data is represented and how it is understood by the user. Technical As you probably gathered, we use WMS for tiles and another standard called the web feature service (WFS) for specific features. I need to stress that the difference between the two is that WMS is for tiling, whereas WFS is for specific features. Both can use similar file formats but should be used for their particular use cases. You may be wondering why you can’t just use a vector format such as KML, GeoJSON (or even SVG) – and you can – but the issue is the same as for WMS: you need a way to query the data to get the correct area and zoom level. User interface There is of course never a correct way to design an interface as there are so many different factors to take into consideration for each individual project. Maps can be used in a variety of ways, to provide simple information about directions or for complex visualisations to explain large amounts of data. I would like to just touch on matters that need to be taken into account when working with maps. As I mentioned at the beginning, there are so many Google Maps on the web that people seem to think that its UI is the only way you can use a map. To some degree we don’t want to change that, as people know how to use them; but does every map require a zoom slider or base map toggle? In fact, does the user need to zoom at all? The answer to that one is generally yes, zooming does provide more context to where the map is zoomed in on. In some cases you will need to let users choose what goes on the map (such as data layers or directions), so how do they show and hide the data? Does a simple drop-down box work, or do you need search? Google’s base map toggle is quite nice since it doesn’t offer many options yet provides very different contexts and styling. It isn’t until we get to this point that we realise just plonking a quick Google map is really quite ridiculous, especially when compared to the amount of effort we make in other areas such as colour, typography or how the CSS is written. Each of these is important but we need to make sure the whole site is designed, and that includes the maps as much as any other content. Putting it into practice I could ramble on for ages about what we can do to customise maps to fit a site’s personality and correctly represent the data. I wanted to focus on concepts and standards because tools constantly change and it is never good to just rely on a tool to do the work. That said, there are a large variety of tools that will help you turn these concepts into reality. This is not a comparison; I just want to show you a few of the many options you have for maps on the web. Google OK, I’ve been quite critical so far about Google Maps but that is only because there is such a large amount of the default maps across the web. You can style them almost as much as anything else. They may not allow you to use custom WMS layers but Google Maps does have its own version, called styled maps. Using an array of map features (in the sense of roads and lakes and landmarks rather than the kind WFS is used for), you can style the base map with JavaScript. It even lets you toggle visibility, which helps to avoid the issue of too much clutter on the map. As well as lacking WMS, it doesn’t support WFS, but it does support GeoJSON and KML so you can still show the features on the map. You should also check out Google Maps Engine (the new version of My Maps), which provides an interface for creating more advanced maps with a selection of different base maps. A premium version is available, essentially for creating map-based visualisations, and it provides a step up from the main Google Maps offering. A useful feature in some cases is that it gives you access to many datasets. Leaflet You have probably seen Leaflet before. It isn’t quite as popular as Google Maps but it is definitely used often and for good reason. Leaflet is a lightweight open source JavaScript library. It is not a service so you don’t have to worry about API throttling and longevity. It gives you two options for tiling, the ability to use WMS, or to directly get the file using variables in the filename such as /{z}/{x}/{y}.png. I would recommend using WMS over dynamic file names because it is a standard, but the ability to use variables in a file name could be useful in some situations. Leaflet has a strong community and a well-documented API. Mapbox As a freemium service, Mapbox may not be perfect for every use case but it’s definitely worth looking into. The service offers incredible customisation tools as well as lots of data sources and hosting for the maps. It also provides plenty of libraries for the various platforms, so you don’t have to only use the maps on the web. Mapbox is a service, though its map design tool is open source. Mapbox Studio is a vector-only version of their previous tool called Tilemill. Earlier I wrote about how typography and colour are as important to maps as they are to the rest of a website; if you thought, “Yes, but how on earth can I design those parts of a map?” then this is the tool for you. It is incredibly easy to use. Essentially each map has a stylesheet. If you do not want to open a paid-for Mapbox account, then you can export the tiles (as PNG, SVG etc.) to use with other map tools. OpenLayers After a long wait, OpenLayers 3 has been released. It is similar to Leaflet in that it is a library not a service, but it has a much broader scope. During the last year I worked on the GIS portal at Plymouth Marine Laboratory (which I used to show the data tiles earlier), it essentially used OpenLayers 2 to create a web-based geographic information system, taking a large amount of data and permitting analysis (such as graphs) without downloading entire datasets and complicated software. OpenLayers 3 has improved greatly on the previous version in both performance and accessibility. It is the ideal tool for complex map-based web apps, though it can be used for the simple use cases too. OpenStreetMap I couldn’t write an article about maps on the web without at least mentioning OpenStreetMap. It is the place to go for crowd-sourced data about any location, with complete road maps and a strong API. ViziCities The newest project on this list is ViziCities by Robin Hawkes and Peter Smart. It is a open source 3-D visualisation tool, currently in the very early stages of development. The basic example shows 3-D buildings around the world using OpenStreetMap data. Robin has used it to create some incredible demos such as real-time London underground trains, and planes landing at an airport. Edward Greer and I are currently working on using ViziCities to show ideal housing areas based on particular personas. We chose it because the 3-D aspect gives us interesting possibilities for the data we are able to visualise (such as bar charts on the actual map instead of in the UI). Despite not being a completely stable, fully featured system, ViziCities is worth taking a look at for some use cases and is definitely going to go from strength to strength. So there you have it – a whistle-stop tour of how maps can be customised. Now please stop plonking in maps without thinking about it and design them as you design the rest of your content. 2014 Shane Hudson shanehudson 2014-12-11T00:00:00+00:00 https://24ways.org/2014/putting-design-on-the-map/ design
54 Putting My Patterns through Their Paces 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. The 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. Meet the Teaser Here’s 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.) In its simplest form, a teaser contains a headline, which links to an article: Fairly straightforward, sure. But it’s 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 – 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. Nearly every element visible on this page is built out of our generic “teaser” pattern. But the teaser variation I’d like to call out is the one that appears on The Toast’s 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. The approved visual design of our teaser, as it appears on lists on the homepage and the section fronts. And this is, as it happens, the teaser variation that gave me pause. Back in the old days – you know, like six months ago – I probably would’ve marked this module up to match the design. In other words, I would’ve looked at the module’s visual hierarchy (metadata up top, headline and content below) and written the following HTML: <div class="teaser"> <p class="article-byline">By <a href="#">Author Name</a></p> <a class="comment-count" href="#">126 <i>comments</i></a> <h1 class="article-title"><a href="#">Article Title</a></h1> <p class="teaser-excerpt">Lorem ipsum dolor sit amet, consectetur…</p> </div> But then I caught myself, and realized this wasn’t the best approach. Moving Beyond Layout Since I’ve started working responsively, there’s a question I work into every step of my design process. Whether I’m working in Sketch, CSSing a thing, or researching a project, I try to constantly ask myself: What if someone doesn’t browse the web like I do? …Okay, that doesn’t seem especially fancy. (And maybe you came here for fancy.) But as straightforward as that question might seem, it’s been invaluable to so many aspects of my practice. If I’m working on a widescreen layout, that question helps me remember the constraints of the small screen; if I’m working on an interface that has some enhancements for touch, it helps me consider other input modes as I work. It’s 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. And 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’d 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’re associated. That’s why I find it’s helpful to begin designing a pattern’s hierarchy before its layout: to move past the visual presentation in front of me, and focus on the underlying content I’m trying to support. In other words, if someone’s encountering my design without the CSS I’ve written, what should their experience be? So I took a step back, and came up with a different approach: <div class="teaser"> <h1 class="article-title"><a href="#">Article Title</a></h1> <h2 class="article-byline">By <a href="#">Author Name</a></h2> <p class="teaser-excerpt"> Lorem ipsum dolor sit amet, consectetur… <a class="comment-count" href="#">126 <i>comments</i></a> </p> </div> Much, much better. This felt like a better match for the content I was designing: the headline – easily most important element – was at the top, followed by the author’s 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’s why it’s at the very end of the excerpt, the last element within our teaser. And with some light styling, we’ve got a respectable-looking hierarchy in place: Yeah, you’re right – it’s not our final design. But from this basic-looking foundation, we can layer on a bit more complexity. First, we’ll bolster the markup with an extra element around our title and byline: <div class="teaser"> <div class="teaser-hed"> <h1 class="article-title"><a href="#">Article Title</a></h1> <h2 class="article-byline">By <a href="#">Author Name</a></h2> </div> … </div> With that in place, we can use flexbox to tweak our layout, like so: .teaser-hed { display: flex; flex-direction: column-reverse; } flex-direction: column-reverse acts a bit like a change in gravity within our teaser-hed element, vertically swapping its two children. Getting closer! But as great as flexbox is, it doesn’t do anything for elements outside our container, like our little comment count, which is, as you’ve probably noticed, still stranded at the very bottom of our teaser. Flexbox 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’s using a sufficiently modern version of flexbox. Here’s the one we used: var doc = document.body || document.documentElement; var style = doc.style; if ( style.webkitFlexWrap == '' || style.msFlexWrap == '' || style.flexWrap == '' ) { doc.className += " supports-flex"; } Eagle-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’s design: .supports-flex .teaser-hed { display: flex; flex-direction: column-reverse; } .supports-flex .teaser .comment-count { position: absolute; right: 0; top: 1.1em; } If the supports-flex class is present, we can apply our flexbox layout to the title area, sure – 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’t meet our threshold for our advanced styles are left with an attractive design that matches our HTML’s content hierarchy; but the ones that pass our test receive the finished, final design. And with that, our teaser’s complete. Diving Into Device-Agnostic Design This is, admittedly, a pretty modest application of flexbox. (For some truly next-level work, I’d recommend Heydon Pickering’s “Flexbox Grid Finesse”, 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’d be right! In fact, it’s 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’ve found that thinking about my design as existing in broad experience tiers – in layers – is one of the best ways of designing for the modern web. And what’s more, it works not just for simple modules like our teaser, but for more complex or interactive patterns as well. Open video Even a simple search form can be conditionally enhanced, given a little layered thinking. This more layered approach to interface design isn’t a new one, mind you: it’s 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’ve found to practice responsive design. As Trent Walton once wrote, Like cars designed to perform in extreme heat or on icy roads, websites should be built to face the reality of the web’s inherent variability. We have a weird job, working on the web. We’re designing for the latest mobile devices, sure, but we’re increasingly aware that our definition of “smartphone” is much too narrow. Browsers have started appearing on our wrists and in our cars’ dashboards, but much of the world’s mobile data flows over sub-3G networks. After all, the web’s evolution has never been charted along a straight line: it’s 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’t yet know about, a more device-agnostic, more layered design process can better prepare our patterns – and ourselves – for the future. (It won’t help you get enough to eat at holiday parties, though.) 2015 Ethan Marcotte ethanmarcotte 2015-12-10T00:00:00+00:00 https://24ways.org/2015/putting-my-patterns-through-their-paces/ code
317 Putting the World into "World Wide Web" Despite the fact that the Web has been international in scope from its inception, the predominant mass of Web sites are written in English or another left-to-right language. Sites are typically designed visually for Western culture, and rely on an enormous body of practices for usability, information architecture and interaction design that are by and large centric to the Western world. There are certainly many reasons this is true, but as more and more Web sites realize the benefits of bringing their products and services to diverse, global markets, the more demand there will be on Web designers and developers to understand how to put the World into World Wide Web. Internationalization According to the W3C, Internationalization is: “…the design and development of a product, application or document content that enables easy localization for target audiences that vary in culture, region, or language.” Many Web designers and developers have at least heard, if not read, about Internationalization. We understand that the Web is in fact worldwide, but many of us never have the opportunity to work with Internationalization. Or, when we do, think of it in purely technical terms, such as “which character set do I use?” At first glance, it might seem to many that Internationalization is the act of making Web sites available to international audiences. And while that is in fact true, this isn’t done by broad-stroking techniques and technologies. Instead, it involves a far more narrow understanding of geographical, cultural and linguistic differences in specific areas of the world. This is referred to as localization and is the act of making a Web site make sense in the context of the region, culture and language(s) the people using the site are most familiar with. Internationalization itself includes the following technical tasks: Ensuring no barrier exists to the localization of sites. Of critical importance in the planning stages of a site for Internationalized audiences, the role of the developer is to ensure that no barrier exists. This means being able to perform such tasks as enabling Unicode and making sure legacy character encodings are properly handled. Preparing markup and CSS with Internationalization in mind. The earlier in the site development process this occurs, the better. Issues such as ensuring that you can support bidirectional text, identifying language, and using CSS to support non-Latin typographic features. Enabling code to support local, regional, language or culturally related references. Examples in this category would include time/date formats, localization of calendars, numbering systems, sorting of lists and managing international forms of addresses. Empowering the user. Sites must be architected so the user can easily choose or implement the localized alternative most appropriate to them. Localization According to the W3C, Localization is the: …adaptation of a product, application or document content to meet the language, cultural and other requirements of a specific target market (a “locale”). So here’s where we get down to thinking about the more sociological and anthropological concerns. Some of the primary localization issues are: Numeric formats. Different languages and cultures use numbering systems unlike ours. So, any time we need to use numbers, such as in an ordered list, we have to have a means of representing the accurate numbering system for the locale in question. Money, honey! That’s right. I’ve got a pocketful of ugly U.S. dollars (why is U.S. money so unimaginative?). But I also have a drawer full of Japanese Yen, Australian Dollars, and Great British Pounds. Currency, how it’s calculated and how it’s represented is always a consideration when dealing with localization. Using symbols, icons and colors properly. Using certain symbols or icons on sites where they might offend or confuse is certainly not in the best interest of a site that wants to sell or promote a product, service or information type. Moreover, the colors we use are surprisingly persuasive – or detrimental. Think about colors that represent death, for example. In many parts of Asia, white is the color of death. In most of the Western world, black represents death. For Catholic Europe, shades of purple (especially lavender) have represented Christ on the cross and mourning since at least Victorian times. When Walt Disney World Europe launched an ad campaign using a lot of purple and very glitzy imagery, millions of dollars were lost as a result of this seeming subtle issue. Instead of experiencing joy and celebration at the ads, the European audience, particularly the French, found the marketing to be overly American, aggressive, depressing and basically unappealing. Along with this and other cultural blunders, Disney Europe has become a well-known case study for businesses wishing to become international. By failing to understand localization differences, and how powerful color and imagery act on the human psyche, designers and developers are put to more of a disadvantage when attempting to communicate with a given culture. Choosing appropriate references to objects and ideas. What seems perfectly natural in one culture in terms of visual objects and ideas can get confused in another environment. One of my favorite cases of this has to do with Gerber baby food. In the U.S., the baby food is marketed using a cute baby on the package. Most people in the U.S. culturally do not make an immediate association that what is being represented on the label is what is inside the container. However, when Gerber expanded to Africa, where many people don’t read, and where visual associations are less abstract, people made the inference that a baby on the cover of a jar of food represented what is in fact in the jar. You can imagine how confused and even angry people became. Using such approaches as a marketing ploy in the wrong locale can and will render the marketing a failure. As you can see, the act of localization is one that can have profound impact on the success of a business or organization as it seeks to become available to more and more people across the globe. Rethinking Design in the Context of Culture While well-educated designers and those individuals working specifically for companies that do a lot of localization understand these nuances, most of us don’t get exposed to these ideas. Yet, we begin to see how necessary it becomes to have an awareness of not just the technical aspects of Internationalization, but the socio-cultural ones within localization. What’s more, the bulk of information we have when it comes to designing sites typically comes from studies and work done on sites built in English and promoted to Western culture at large. We’re making a critical mistake by not including diverse languages and cultural issues within our usability and information architecture studies. Consider the following design from the BBC: In this case, we’re dealing with English, which is read left to right. We are also dealing with U.K. cultural norms. Notice the following: Location of of navigation Use of the color red Use of diverse symbols Mix of symbols, icons and photos Location of Search Now look at this design, which is the Arabic version of the BBC News, read right to left, and dealing with cultural norms within the Arabic-speaking world. Notice the following: Location of of navigation (location switches to the right) Use of the color blue (blue is considered the “safest” global color) No use of symbols and icons whatsoever Limitation of imagery to photos In most cases, the photos show people, not objects Location of Search Admittedly, some choices here are more obvious than others in terms of why they were made. But one thing that stands out is that the placement of search is the same for both versions. Is this the result of a specific localization decision, or based on what we believe about usability at large? This is exactly the kind of question that designers working on localization have to seek answers to, instead of relying on popular best practices and belief systems that exist for English-only Web sites. It’s a Wide World Web After All From this brief article on Internationalization, it becomes apparent that the art and science of creating sites for global audiences requires a lot more preparation and planning than one might think at first glance. Developers and designers not working to address these issues specifically due to time or awareness will do well to at least understand the basic process of making sites more culturally savvy, and better prepared for any future global expansion. One thing is certain: We not only are on a dramatic learning curve for designing and developing Web sites as it is, the need to localize sites is going to become more and more a part of the day to day work. Understanding aspects of what makes a site international and local will not only help you expand your skill set and make you more marketable, but it will also expand your understanding of the world and the people within it, how they relate to and use the Web, and how you can help make their experience the best one possible. 2005 Molly Holzschlag mollyholzschlag 2005-12-09T00:00:00+00:00 https://24ways.org/2005/putting-the-world-into-world-wide-web/ ux
277 Raising the Bar on Mobile One of the primary challenges of designing for mobile devices is that screen real estate is often in limited supply. Through the advocacy of Luke W and others, we’ve drawn comfort from the idea that this constraint ends up benefiting users and designers alike, from obvious advantages like portability and reach, to influencing our content strategy decisions through focus and restraint. But that doesn’t mean we shouldn’t take advantage of every last pixel of that screen we can snag! As anyone who has designed a website for use on a smartphone can attest, there’s an awful lot of space on mobile screens dedicated to browser functions that would be better off toggled out of view. Unfortunately, the visibility of some of these elements is beyond our control, such as the buttons fixed to the bottom of the viewport in iOS’s Safari and the WebOS browser. However, in many devices, the address bar at the top can be manually hidden, and its absence frees up enough pixel room for a large, impactful heading, a critical piece of navigation, or even just a little more white space to air things out. So, as my humble contribution to this most festive of web publications, today I’ll dig into the approach I used to hide the address bar in a browser-agnostic fashion for sites like BostonGlobe.com, and the jQuery Mobile framework. Surveying the land First, let’s assess the chromes of some popular, current mobile browsers. For example purposes, the following screen-captures feature the homepage of the Boston Globe site, without any address-bar-hiding logic in place. Note: these captures are just mockups – actual experience on these platforms may vary. On the left is iOS5’s Safari (running on iPhone), and on the right is Windows Phone 7 (pre-Mango). BlackBerry 7 (left), and Android 2.3 (right). WebOS (left), Opera Mini (middle), and Opera Mobile (right). Some browsers, such the default browsers on WebOS and BlackBerry 5, hide the bar automatically without any developer intervention, but many of them don’t. Of these, we can only manually hide the address bar on iOS Safari and Android (according to Opera Web Opener, Mike Taylor, some discussion is underway for support in Opera Mini and Mobile as well, which would be great!). This is unfortunate, but iOS and Android are incredibly popular, so let’s direct our focus there. Great API, or greatest API? As it turns out, iOS and Android not only allow you to hide the address bar, they use the same JavaScript method to do so, too (this shouldn’t be surprising, given that they are both WebKit browsers, but nothing expected happens in mobile). However, the method they use is not exactly intuitive. You might set out looking for a JavaScript API dedicated to this purpose, like, say, window.toolbar.hide(), but alas, to hide the address bar you need to use the window.scrollTo method! window.scrollTo(0, 0); The scrollTo method is not new, it’s just this particular use of it that is. For the uninitiated, scrollTo is designed to scroll a document to a particular set of coordinates, assuming the document is large enough to scroll to that spot. The method accepts two arguments: a left coordinate; and a top coordinate. It’s both simple and supported well pretty much everywhere. In iOS and Android, these coordinates are calculated from the top of the browser’s viewport, just below the address bar (interestingly, it seems that some platforms like BlackBerry 6 treat the top of the browser chrome as 0 instead, meaning the page content is closer to 20px from the top). Anyway, by passing the coordinates 0, 0 to the scrollTo method, the browser will jump to the top of the page and pull the address bar out of view! Of course, if a quick call to scrollTo was all we need to do to hide the address bar in iOS and Android, this article would be pretty short, and nothing new. Unfortunately, the first issue we need to deal with is that this method alone will not usually do the trick: it must be called after the page has finished loading. The browser gives us a load event for just that purpose, so we’ll wrap our scrollTo method in it and continue on our merry way! We’ll use the standard, addEventListener method to bind the the load event, passing arguments for event name load, and a callback function to execute when the event is triggered. window.addEventListener("load",function() { window.scrollTo(0, 0); }); For the sake of preventing errors in those using browsers that don’t support addEventListener, such as Internet Explorer 8 and under, let’s make sure that method exists before we use it: if( window.addEventListener ){ window.addEventListener("load",function() { window.scrollTo(0, 0); }); } Now we’re getting somewhere, but we must also call the method after the load event’s default behavior has been applied. For this, we can use the setTimeout method, delaying its execution to after the load event has run its course. if( window.addEventListener ){ window.addEventListener("load",function() { setTimeout(function(){ window.scrollTo(0, 0); }, 0); }); } Sweet sugar of Christmas! Hit this demo in iOS and watch that address bar drift up and away! Not so fast… We’ve got a little problem: the approach above does work in iOS but, in some cases, it works a little too well. In the process of applying this behavior, we’ve broken one of the primary tenets of responsible web development: don’t break the browser’s default behaviour. This usability rule of thumb is often violated by developers with even the best of intentions, from breaking the browser’s back button through unrecorded Ajax page refreshes, to fancy momentum touch scrolling scripts that can wreak havoc in all but the most sophisticated of devices. In this case, we’ve prevented the browser’s native support of deep-linking to sections of a page (a hash identifier in the URL matching a page element’s id attribute, for example, http://example.com#contact) from working properly, because our script always scrolls to the top. To avoid this collision, we’ll need to detect whether a deep link, or hash, is present in the URL before applying our logic. We can do this by ensuring that the location.hash property is falsey: if( !window.location.hash && window.addEventListener ){ window.addEventListener( "load",function() { setTimeout(function(){ window.scrollTo(0, 0); }, 0); }); } Still works great! And a quick test using a hash-based URL confirms that our script will not execute when a deep anchor is in play. Now iOS is looking sharp, and we’ve added our feature defensively to avoid conflicts. Now, on to Android… Wait. You didn’t expect that we could write code for one browser and be finished, right? Of course you didn’t. I mentioned earlier that Android uses the same method for getting rid of the scrollbar, but I left out the fact that the arguments it prefers vary slightly, but significantly, from iOS. Bah! Differering from the earlier logic from iOS, to remove the address bar on Android’s default browser, you need to pass a Y coordinate of 1 instead of 0. Aside from being just plain odd, this is particularly unfortunate because to any other browser on the planet, 1px is a very real, however small, distance from the top of the page! window.scrollTo( 0, 1 ); Looks like we’re going to need a fork… R UA Android? At this point, some developers might decide to simply not support this feature in Android, and more determined devs might decide that a quick check of the User Agent string would be a reliable way to determine the browser and tweak the scroll value accordingly. Neither of those decisions would be tragic, but in the spirit of cross-browser and future-friendly development, I’ll propose an alternative. By this point, it should be clear that neither of the implementations above offer a particularly intuitive way to hide an address bar. As such, one might be skeptical that these approaches will stick around very long in their present state in either browser. Perhaps at some point, Android will decide to use 0 like iOS, making our lives a little easier, or maybe some new browser will decide to model their address bar hiding method after one of these implementations. In any case, detecting the User Agent only allows us to apply logic based on the known present, and in the world of mobile, let’s face it, the present is already the past. Writing a check In this next step of today’s technique, we’ll apply some logic to quickly determine the behavior model of the browser we’re using, then capitalize on that model – without caring which browser it happens to come from – by applying the appropriate scroll distance. To do this, we’ll rely on a fortunate side effect of Android’s implementation, which is when you programatically scroll the page to 1 using scrollTo, Android will report that it’s still at 0 because oddly enough, it is! Of course, any other browser in this situation will report a scroll distance of 1. Thus, by scrolling the page to 1, then asking the browser its scroll distance, we can use this artifact of their wacky implementation to our advantage and scroll to the location that makes sense for the browser in play. Getting the scroll distance To pull off our test, we’ll need to ask the browser for its current scroll distance. The methods for getting scroll distance are not entirely standardized across popular browsers, so we’ll need to use some cross-browser logic. The following scroll distance function is similar to what you’d find in a library like jQuery. It checks the few common ways of getting scroll distance before eventually falling back to 0 for safety’s sake (that said, I’m unaware of any browsers that won’t return a numeric value from one of the first three properties). // scrollTop getter function getScrollTop(){ return scrollTop = window.pageYOffset || document.compatMode === "CSS1Compat" && document.documentElement.scrollTop || document.body.scrollTop || 0; } In order to execute that code above, the body object (referenced here as document.body) will need to be defined already, or we’ll risk an error. To determine that it’s defined, we can run a quick timer to execute code as soon as that object is defined and ready for use. var bodycheck = setInterval(function(){ if( document.body ){ clearInterval( bodycheck ); //more logic can go here!! } }, 15 ); Above, we’ve defined a 15 millisecond interval called bodycheck that checks if document.body is defined and, if so, clears itself of running again. Within that if statement, we can extend our logic further to run other code, such as our check for the scroll distance, defined via the variable scrollTop below: var scrollTop, bodycheck = setInterval(function(){ if( document.body ){ clearInterval( bodycheck ); scrollTop = getScrollTop(); } }, 15 ); With this working, we can immediately scroll to 1, then check the scroll distance when the body is defined. If the distance reports 1, we’re likely in a non-Android browser, so we’ll scroll back to 0 and clean up our mess. window.scrollTo( 0, 1 ); var scrollTop, bodycheck = setInterval(function(){ if( document.body ){ clearInterval( bodycheck ); scrollTop = getScrollTop(); window.scrollTo( 0, scrollTop === 1 ? 0 : 1 ); } }, 15 ); Cashing in All of the pieces are written now, so all we need to do is combine them with our previous logic for scrolling when the window is loaded, and we’ll have a cross-browser solution of which John Resig would be proud. Here’s our combined code snippet, with some formatting updates rolled in as well: (function( win ){ var doc = win.document; // If there’s a hash, or addEventListener is undefined, stop here if( !location.hash && win.addEventListener ){ //scroll to 1 window.scrollTo( 0, 1 ); var scrollTop = 1, getScrollTop = function(){ return win.pageYOffset || doc.compatMode = "CSS1Compat" && doc.documentElement.scrollTop || doc.body.scrollTop || 0; }, //reset to 0 on bodyready, if needed bodycheck = setInterval(function(){ if( doc.body ){ clearInterval( bodycheck ); scrollTop = getScrollTop(); win.scrollTo( 0, scrollTop = 1 ? 0 : 1 ); } }, 15 ); win.addEventListener( “load”, function(){ setTimeout(function(){ //reset to hide addr bar at onload win.scrollTo( 0, scrollTop === 1 ? 0 : 1 ); }, 0); } ); } })( this ); View code example And with that, we’ve got a bunch more room to play with on both iOS and Android. Break out the eggnog …because we’re not done yet! In the spirit of making our script act more defensively, there’s still another use case to consider. It was essential that we used the window’s load event to trigger our scripting, but on pages with a lot of content, its use can come at a cost. Often, a user will begin interacting with a page, scrolling down as they read, before the load event has fired. In those situations, our script will jump the user back to the top of the page, resulting in a jarring experience. To prevent this problem from occurring, we’ll need to ensure that the page has not been scrolled beyond a certain amount. We can add a simple check using our getScrollTop function again, this time ensuring that its value is not greater than 20 pixels or so, accounting for a small tolerance. if( getScrollTop() < 20 ){ //reset to hide addr bar at onload window.scrollTo( 0, scrollTop === 1 ? 0 : 1 ); } And with that, we’re pretty well protected! Here’s a final demo. The completed script can be found on Github (full source: https://gist.github.com/1183357 ). It’s MIT licensed. Feel free to use it anywhere or any way you’d like! Your thoughts? I hope this article provides you with a browser-agnostic approach to hiding the address bar that you can use in your own projects today. Perhaps alternatively, the complications involved in this approach convinced you that doing this well is more trouble than it’s worth and, depending on the use case, that could be a fair decision. But at the very least, I hope this demonstrates that there’s a lot of work involved in pulling off this small task in only two major platforms, and that there’s a real need for standardization in this area. Feel free to leave a comment or criticism and I’ll do my best to answer in a timely fashion. Thanks, everyone! Some parting notes I scream, you scream… At the time of writing, I was not able to test this method on the latest Android 4.0 (Ice Cream Sandwich) build. According to Sencha Touch’s browser scorecard, the browser in 4.0 may have a different way of managing the address bar, so I’ll post in the comments once I get a chance to dig into it further. Short pages get no love Today’s technique only works when the page is as tall, or taller than, the device’s available screen height, so that the address bar may be scrolled out of view. On a short page, you might work around this issue by applying a minimum height to the body element ( body { min-height: 460px; } ), but given the variety of screen sizes out there, not to mention changes in orientation, it’s tough to find a value that makes much sense (unless you manipulate it with JavaScript). 2011 Scott Jehl scottjehl 2011-12-20T00:00:00+00:00 https://24ways.org/2011/raising-the-bar-on-mobile/ design
131 Random Lines Made With Mesh I know that Adobe Illustrator can be a bit daunting for people who aren’t really advanced users of the program, but you would be amazed by how easy you can create cool effects or backgrounds. In this short tutorial I show you how to create a cool looking background only in 5 steps. Step 1 – Create Lines Create lines using random widths and harmonious suitable colors. If you get stuck on finding the right colors, check out Adobe’s Kuler and start experimenting. Step 2 – Convert Strokes to Fills Select all lines and convert them to fills. Go to the Object menu, select Path > Outline Stroke. Select the Rectangle tool and draw 1 big rectangle on top the lines. Give the rectangle a suitable color. With the rectangle still selected, go to the Object menu, select Arrange > Send to Back. Step 3 – Convert to Mesh Select all objects by pressing the command key (for Mac users), control key (for Windows users) + the “a” key. Go to the Object menu and select the Envelope Distort > Make with Mesh option. Enter 2 rows and 2 columns. Check the preview box to see what happens and click the OK button. Step 4 – Play Around with The Mesh Points Play around with the points of the mesh using the Direct Selection tool (the white arrow in the Toolbox). Click on the top right point of the mesh. Once you’re starting to drag hold down the shift key and move the point upwards. Now start dragging the bezier handles on the mesh to achieve the effect as shown in the above picture. Of course you can try out all kind of different effects here. The Final Result This is an example of how the final result can look. You can try out all kinds of different shapes dragging the handles of the mesh points. This is just one of the many results you can get. So next time you haven’t got inspiration for a background of a header, a banner or whatever, just experiment with a few basic shapes such as lines and try out the ‘Envelope Distort’ options in Illustrator or the ‘Make with Mesh’ option and experiment, you’ll be amazed by the unexpected creative results. 2006 Veerle Pieters veerlepieters 2006-12-08T00:00:00+00:00 https://24ways.org/2006/random-lines-made-with-mesh/ design
235 Real Animation Using JavaScript, CSS3, and HTML5 Video When I was in school to be a 3-D animator, I read a book called Timing for Animation. Though only 152 pages long, it’s essentially the bible for anyone looking to be a great animator. In fact, Pixar chief creative officer John Lasseter used the first edition as a reference when he was an animator at Walt Disney Studios in the early 1980s. In the book, authors John Halas and Harold Whitaker advise: Timing is the part of animation which gives meaning to movement. Movement can easily be achieved by drawing the same thing in two different positions and inserting a number of other drawings between the two. The result on the screen will be movement; but it will not be animation. But that’s exactly what we’re doing with CSS3 and JavaScript: we’re moving elements, not animating them. We’re constantly specifying beginning and end states and allowing the technology to interpolate between the two. And yet, it’s the nuances within those middle frames that create the sense of life we’re looking for. As bandwidth increases and browser rendering grows more consistent, we can create interactions in different ways than we’ve been able to before. We’re encountering motion more and more on sites we’d generally label ‘static.’ However, this motion is mostly just movement, not animation. It’s the manipulation of an element’s properties, most commonly width, height, x- and y-coordinates, and opacity. So how do we create real animation? The metaphor In my experience, animation is most believable when it simulates, exaggerates, or defies the real world. A bowling ball falls differently than a racquetball. They each have different weights and sizes, which affect the way they land, bounce, and impact other objects. This is a major reason that JavaScript animation frequently feels mechanical; it doesn’t complete a metaphor. Expanding and collapsing a <div> feels very different than a opening a door or unfolding a piece of paper, but it often shouldn’t. The interaction itself should tie directly to the art direction of a page. Physics Understanding the physics of a situation is key to creating convincing animation, even if your animation seeks to defy conventional physics. Isaac Newton’s first law of motion’s_laws_of_motion states, “Every body remains in a state of rest or uniform motion (constant velocity) unless it is acted upon by an external unbalanced force.” Once a force acts upon an object, the object’s shape can change accordingly, depending on the strength of the force and the mass of the object. Another nugget of wisdom from Halas and Whitaker: All objects in nature have their own weight, construction, and degree of flexibility, and therefore each behaves in its own individual way when a force acts upon it. This behavior, a combination of position and timing, is the basis of animation. The basic question which an animator is continually asking himself is this: “What will happen to this object when a force acts upon it?” And the success of his animation largely depends on how well he answers this question. In animating with CSS3 and JavaScript, keep physics in mind. How ‘heavy’ is the element you’re interacting with? What kind of force created the action? A gentle nudge? A forceful shove? These subtleties will add a sense of realism to your animations and make them much more believable to your users. Misdirection Magicians often use misdirection to get their audience to focus on one thing rather than another. They fool us into thinking something happened that actually didn’t. Animation is the same, especially on a screen. By changing the arrangement of pixels on screen at a fast enough rate, your eyes fool your mind into thinking an object is actually in motion. Another important component of misdirecting in animation is the use of multiple objects. Try to recall a cartoon where a character vanishes. More often, the character makes some sort of exaggerated motion (this is called anticipation) then disappears, and a puff a smoke follows. That smoke is an extra element, but it goes a long way into make you believe that character actually disappeared. Very rarely does a vanishing character’s opacity simply go from one hundred per cent to zero. That’s not believable. So why do we do it with <div>s? Armed with the ammunition of metaphors and misdirection, let’s code an example. Shake, rattle, and roll (These demos require at least a basic understanding of jQuery and CSS3. Run away if your’re afraid, or brush up on CSS animation and resources for learning jQuery. Also, these demos use WebKit-specific features and are best viewed in the latest version of Safari, so performance in other browsers may vary.) We often see the design pattern of clicking a link to reveal content. Our “first demo”:”/examples/2010/real-animation/demo1/ shows us exactly that. It uses jQuery’s “ slideDown()”:http://api.jquery.com/slideDown/ method, as many instances do. But what force acted on the <div> that caused it to open? Did pressing the button unlatch some imaginary hook? Did it activate an unlocking sequence with some gears? Take 2 Our second demo is more explicit about what happens: the button fell on the <div> and shook its content loose. Here’s how it’s done. function clickHandler(){ $('#button').addClass('animate'); return false; } Clicking the link adds a class of animate to our button. That class has the following CSS associated with it: <style> .animate { -webkit-animation-name: ANIMATE; -webkit-animation-duration: 0.25s; -webkit-animation-iteration-count: 1; -webkit-animation-timing-function: ease-in; } @-webkit-keyframes ANIMATE { from { top: 72px; } to { top: 112px; } } </style> In our keyframe definition, we’ve specified from and to states. This is great, because we can be explicit about how an object starts and finishes moving. What’s also extra handy is that these CSS keyframes broadcast events that you can react to with JavaScript. In this example, we’re listening to the webkitAnimationEnd event and opening the <div> only when the sequence is complete. Here’s that code. function attachAnimationEventHandlers(){ var wrap = document.getElementById('wrap'); wrap.addEventListener('webkitAnimationEnd', function($e) { switch($e.animationName){ case "ANIMATE" : openMain(); break; default: } }, false); } function openMain(){ $('#main .inner').slideDown('slow'); } (For more info on handling animation events, check out the documentation at the Safari Reference Library.) Take 3 The problem with the previous demo is that the subtleties of timing aren’t evident. It still feels a bit choppy. For our third demo, we’ll use percentages instead of keywords so that we can insert as many points as we need to communicate more realistic timing. The percentages allow us to add the keys to well-timed animation: anticipation, hold, release, and reaction. <style> @-webkit-keyframes ANIMATE { 0% { top: 72px; } 40% { /* anticipation */ top: 57px; } 70% { /* hold */ top: 56px; } 80% { /* release */ top: 112px; } 100% { /* return */ top: 72px; } } </style> Take 4 The button animation is starting to feel much better, but the reaction of the <div> opening seems a bit slow. This fourth demo uses jQuery’s delay() method to time the opening precisely when we want it. Since we know the button’s animation is one second long and its reaction starts at eighty per cent of that, that puts our delay at 800ms (eighty per cent of one second). However, here’s a little pro tip: let’s start the opening at 750ms instead. The extra fifty milliseconds makes it feel more like the opening is a reaction to the exact hit of the button. Instead of listening for the webkitAnimationEnd event, we can start the opening as soon as the button is clicked, and the movement plays on the specified delay. function clickHandler(){ $('#button').addClass('animate'); openMain(); return false; } function openMain(){ $('#main .inner').delay(750).slideDown('slow'); } Take 5 We can tweak the timing of that previous animation forever, but that’s probably as close as we’re going to get to realistic animation with CSS and JavaScript. However, for some extra sauce, we could relegate the whole animation in our final demo to a video sequence which includes more nuances and extra elements for misdirection. Here’s the basis of video replacement. Add a <video> element to the page and adjust its opacity to zero. Once the button is clicked, fade the button out and start playing the video. Once the video is finished playing, fade it out and bring the button back. function clickHandler(){ if($('#main .inner').is(':hidden')){ $('#button').fadeTo(100, 0); $('#clickVideo').fadeTo(100, 1, function(){ var clickVideo = document.getElementById('clickVideo'); clickVideo.play(); setTimeout(removeVideo, 2400); openMain(); }); } return false; } function removeVideo(){ $('#button').fadeTo(500, 1); $('#clickVideo').fadeOut('slow'); } function openMain(){ $('#main .inner').delay(1100).slideDown('slow'); } Wrapping up I’m no JavaScript expert by any stretch. I’m sure a lot of you scripting wizards out there could write much cleaner and more efficient code, but I hope this gives you an idea of the theory behind more realistic motion with the technology we’re using most. This is just one model of creating more convincing animation, but you can create countless variations of this, including… Exporting <video> animations in 3-D animation tools or 2-D animation tools like Flash or After Effects Using <canvas> or SVG instead of <video> Employing specific JavaScript animation frameworks Making use of all the powerful properties of CSS Transforms and CSS Animation Trying out emerging CSS3 animation tools like Sencha Animator If it wasn’t already apparent, these demos show an exaggerated example and probably aren’t practical in a lot of environments. However, there are a handful of great sites out there that honor animation techniques—metaphor, physics, and misdirection, among others—like Benjamin De Cock’s vCard, 20 Things I Learned About Browsers and the Web by Fantasy Interactive, and the Nike Snowboarding site by Ian Coyle and HEGA. They’re wonderful testaments to what you can do to aid interaction for users. My goal was to show you the ‘why’ and the ‘how.’ Your charge is to discern the ‘where’ and the ‘when.’ Happy animating! 2010 Dan Mall danmall 2010-12-15T00:00:00+00:00 https://24ways.org/2010/real-animation-using-javascript-css3-and-html5-video/ code
173 Real Fonts and Rendering: The New Elephant in the Room My friend, the content strategist Kristina Halvorson, likes to call content “the elephant in the room” of web design. She means it’s the huge problem that no one on the web development team or client side is willing to acknowledge, face squarely, and plan for. A typical web project will pass through many helpful phases of research, and numerous beneficial user experience design iterations, while the content—which in most cases is supposed to be the site’s primary focus—gets handled haphazardly at the end. Hence, elephant in the room, and hence also artist Kevin Cornell’s recent use of elephantine imagery to illustrate A List Apart articles on the subject. But I digress. Without discounting the primacy of the content problem, we web design folk have now birthed ourselves a second lumbering mammoth, thanks to our interest in “real fonts on the web“ (the unfortunate name we’ve chosen for the recent practice of serving web-licensed fonts via CSS’s decade-old @font-face declaration—as if Georgia, Verdana, and Times were somehow unreal). For the fact is, even bulletproof and mo’ bulletproofer @font-face CSS syntax aren’t really bulletproof if we care about looks and legibility across browsers and platforms. Hyenas in the Breakfast Nook The problem isn’t just that foundries have yet to agree on a standard font format that protects their intellectual property. And that, even when they do, it will be a while before all browsers support that standard—leaving aside the inevitable politics that impede all standardization efforts. Those are problems, but they’re not the elephant. Call them the coyotes in the room, and they’re slowly being tamed. Nor is the problem that workable, scalable business models (of which Typekit‘s is the most visible and, so far, the most successful) are still being shaken out and tested. The quality and ease of use of such services, their stability on heavily visited sites (via massively backed-up server clusters), and the fairness and sustainability of their pricing will determine how licensing and serving “real fonts” works in the short and long term for the majority of designer/developers. Nor is our primary problem that developers with no design background may serve ugly or illegible fonts that take forever to load, or fonts that take a long time to download and then display as ordinary system fonts (as happens on, say, about.validator.nu). Ugliness and poor optimization on the web are nothing new. That support for @font-face in Webkit and Mozilla browsers (and for TrueType fonts converted to Embedded OpenType in Internet Explorer) adds deadly weapons to the non-designer’s toolkit is not the technology’s fault. JavaScript and other essential web technologies are equally susceptible to abuse. Beauty is in the Eye of the Rendering Engine No, the real elephant in the room—the thing few web developers and no “web font” enthusiasts are talking about—has to do with legibility (or lack thereof) and aesthetics (or lack thereof) across browsers and platforms. Put simply, even fonts optimized for web use (which is a whole thing: ask a type designer) will not look good in every browser and OS. That’s because every browser treats hinting differently, as does every OS, and every OS version. Firefox does its own thing in both Windows and Mac OS, and Microsoft is all over the place because of its need to support multiple generations of Windows and Cleartype and all kinds of hardware simultaneously. Thus “real type” on a single web page can look markedly different, and sometimes very bad, on different computers at the same company. If that web page is your company’s, your opinion of “web fonts” may suffer, and rightfully. (The advantage of Apple’s closed model, which not everyone likes, is that it allows the company to guarantee the quality and consistency of user experience.) As near as my font designer friends and I can make out, Apple’s Webkit in Safari and iPhone ignores hinting and creates its own, which Apple thinks is better, and which many web designers think of as “what real type looks like.” The forked version of Webkit in Chrome, Android, and Palm Pre also creates its own hinting, which is close to iPhone’s—close enough that Apple, Palm, and Google could propose it as a standard for use in all browsers and platforms. Whether Firefox would embrace a theoretical Apple and Google standard is open to conjecture, and I somehow have difficulty imagining Microsoft buying in—even though they know the web is more and more mobile, and that means more and more of their customers are viewing web content in some version of Webkit. The End of Simple There are ways around this ugly type ugliness, but they involve complicated scripting and sniffing—the very nightmares from which web standards and the simplicity of @font-face were supposed to save us. I don’t know that even mighty Typekit has figured out every needed variation yet (although, working with foundries, they probably will). For type foundries, the complexity and expense of rethinking classic typefaces to survive in these hostile environments may further delay widespread adoption of web fonts and the resolution of licensing and formatting issues. The complexity may also force designers (even those who prefer to own) to rely on a hosted rental model simply to outsource and stay current with the detection and programming required. Forgive my tears. I stand in a potter’s field of ideas like “Keep it simple,” by a grave whose headstone reads “Write once, publish everywhere.” 2009 Jeffrey Zeldman jeffreyzeldman 2009-12-22T00:00:00+00:00 https://24ways.org/2009/real-fonts-and-rendering/ design
103 Recession Tips For Web Designers For web designers, there are four keys to surviving bad economic times: do good work, charge a fair price, lower your overhead, and be sure you are communicating with your client. As a reader of 24 ways, you already do good work, so let’s focus on the rest. I know something about surviving bad times, having started my agency, Happy Cog, at the dawn of the dot-com bust. Of course, the recession we’re in now may end up making the dot-com bust look like the years of bling and gravy. But the bust was rough enough at the time. Bad times are hard on overweight companies and over-leveraged start-ups, but can be kind to freelancers and small agencies. Clients who once had money to burn and big agencies to help them burn it suddenly consider the quality of work more important than the marquee value of the business card. Fancy offices and ten people at every meeting are out. A close relationship with an individual or small team that listens is in. Thin is in If you were good in client meetings when you were an employee, print business cards and pick a name for your new agency. Once some cash rolls in, see an accountant. If the one-person entrepreneur model isn’t you, it’s no problem. Form a virtual agency with colleagues who complement your creative, technical, and business skills. Athletics is a Brooklyn-based multi-disciplinary “art and design collective.” Talk about low overhead: they don’t have a president, a payroll, or a pension plan. But that hasn’t stopped clients like adidas, Nike, MTV, HBO, Disney, DKNY, and Sundance Channel from knocking on their (virtual) doors. Running a traditional business is like securing a political position in Chicago: it costs a fortune. That’s why bad times crush so many companies. But you are a creature of the internets. You don’t need an office to do great work. I ran Happy Cog out of my apartment for far longer than anyone realized. My clients, when they learned my secret, didn’t care. Keep it lean: if you can budget your incoming freelance money, you don’t have to pay yourself a traditional salary. Removing the overhead associated with payroll means more of the budget stays in your pocket, enabling you to price your projects competitively, while still within industry norms. (Underpricing is uncool, and clients who knowingly choose below-market-rate vendors tend not to treat those vendors with respect.) Getting gigs Web design is a people business. If things are slow, email former clients. If you just lost your job, email former agency clients with whom you worked closely to inform them of your freelance business and find out how they’re doing. Best practice: focus the email on wishing them a happy holiday and asking how they’re doing. Let your email signature file tell them you’re now the president of Your Name Design. Leading with the fact that you just lost your job may earn sympathy (or commiseration: the client may have lost her job, too) but it’s not exactly a sure-fire project getter. The qualities that help you land a web design project are the same in good times or bad. Have a story to tell about the kind of services you offer, and the business benefits they provide. (If you design with web standards, you already have one great story line. What are the others?) Don’t be shy about sharing your story, but don’t make it the focus of the meeting. The client is the focus. Before you meet her, learn as much as you can about her users, her business, and her competitors. At the very least, read her site’s About pages, and spend some quality time with Google. Most importantly, go to the meeting knowing how much you don’t know. Arrive curious, and armed with questions. Maintain eye contact and keep your ears open. If a point you raise causes two people to nod at each other, follow up on that point, don’t just keep grinding through your Keynote presentation. If you pay attention and think on your feet, it tells the potential client that they can expect you to listen and be flexible. (Clients are like unhappy spouses: they’re dying for someone to finally listen.) If you stick to a prepared presentation, it might send the message that you are inflexible or nervous or both. “Nervous” is an especially bad signal to send. It indicates that you are either dishonest or inexperienced. Neither quality invites a client to sign on. Web design is a people business for the client, too: they should feel that their interactions with you will be pleasant and illuminating. And that you’ll listen. Did I mention that? Give it time Securing clients takes longer and requires more effort in a recession. If two emails used to land you a gig, it will now take four, plus an in-person meeting, plus a couple of follow-up calls. This level of salesmanship is painful to geeks and designers, who would rather spend four hours kerning type or debugging a style sheet than five minutes talking business on the telephone. I know. I’m the same way. But we must overcome our natural shyness and inwardness if we intend not to fish our next meal out of a neighbor’s garbage can. As a bonus, once the recession ends, your hard-won account management skills will help you take your business to the next level. By the time jobs are plentiful again, you may not want to work for anyone but yourself. You’ll be a captain of our industry. And talented people will be emailing to ask you for a job. 2008 Jeffrey Zeldman jeffreyzeldman 2008-12-24T00:00:00+00:00 https://24ways.org/2008/recession-tips-for-web-designers/ business
92 Redesigning the Media Query Responsive web design is showing us that designing content is more important than designing containers. But if you’ve given RWD a serious try, you know that shifting your focus from the container is surprisingly hard to do. There are many factors and instincts working against you, and one culprit is a perpetrator you’d least suspect. The media query is the ringmaster of responsive design. It lets us establish the rules of the game and gives us what we need most: control. However, like some kind of evil double agent, the media query is actually working against you. Its very nature diverts your attention away from content and forces you to focus on the container. The very act of choosing a media query value means choosing a screen size. Look at the history of the media query—it’s always been about the container. Values like screen, print, handheld and tv don’t have anything to do with content. The modern media query lets us choose screen dimensions, which is great because it makes RWD possible. But it’s still the act of choosing something that is completely unpredictable. Content should dictate our breakpoints, not the container. In order to get our focus back to the only thing that matters, we need a reengineered media query—one that frees us from thinking about screen dimensions. A media query that works for your content, not the window. Fortunately, Sass 3.2 is ready and willing to take on this challenge. Thinking in Columns Fluid grids never clicked for me. I feel so disoriented and confused by their squishiness. Responsive design demands their use though, right? I was ready to surrender until I found a grid that turned my world upright again. The Frameless Grid by Joni Korpi demonstrates that column and gutter sizes can stay fixed. As the screen size changes, you simply add or remove columns to accommodate. This made sense to me and armed with this concept I was able to give Sass the first component it needs to rewrite the media query: fixed column and gutter size variables. $grid-column: 60px; $grid-gutter: 20px; We’re going to want some resolution independence too, so let’s create a function that converts those nasty pixel values into ems. @function em($px, $base: $base-font-size) { @return ($px / $base) * 1em; } We now have the components needed to figure out the width of multiple columns in ems. Let’s put them together in a function that will take any number of columns and return the fixed width value of their size. @function fixed($col) { @return $col * em($grid-column + $grid-gutter) } With the math in place we can now write a mixin that takes a column count as a parameter, then generates the perfect media query necessary to fit that number of columns on the screen. We can also build in some left and right margin for our layout by adding an additional gutter value (remembering that we already have one gutter built into our fixed function). @mixin breakpoint($min) { @media (min-width: fixed($min) + em($grid-gutter)) { @content } } And, just like that, we’ve rewritten the media query. Instead of picking a minimum screen size for our layout, we can simply determine the number of columns needed. Let’s add a wrapper class so that we can center our content on the screen. @mixin breakpoint($min) { @media (min-width: fixed($min) + em($grid-gutter)) { .wrapper { width: fixed($min) - em($grid-gutter); margin-left: auto; margin-right: auto; } @content } } Designing content with a column count gives us nice, easy, whole numbers to work with. Sizing content, sidebars or widgets is now as simple as specifying a single-digit number. @include breakpoint(8) { .main { width: fixed(5); } .sidebar { width: fixed(3); } } Those four lines of Sass just created a responsive layout for us. When the screen is big enough to fit eight columns, it will trigger a fixed width layout. And give widths to our main content and sidebar. The following is the outputted CSS… @media (min-width: 41.25em) { .wrapper { width: 38.75em; margin-left: auto; margin-right: auto; } .main { width: 25em; } .sidebar { width: 15em; } } Demo I’ve created a Codepen demo that demonstrates what we’ve covered so far. I’ve added to the demo some grid classes based on Griddle by Nicolas Gallagher to create a floatless layout. I’ve also added a CSS gradient overlay to help you visualize columns. Try changing the column variable sizes or the breakpoint includes to see how the layout reacts to different screen sizes. Responsive Images Responsive images are a serious problem, but I’m excited to see the community talk so passionately about a solution. Now, there are some excellent stopgaps while we wait for something official, but these solutions require you to mirror your breakpoints in JavaScript or HTML. This poses a serious problem for my Sass-generated media queries, because I have no idea what the real values of my breakpoints are anymore. For responsive images to work, JavaScript needs to recognize which media query is active so that proper images can be loaded for that layout. What I need is a way to label my breakpoints. Fortunately, people much smarter than I have figured this out. Jeremy Keith devised a labeling method by using CSS-generated content as the storage method for breakpoint labels. We can use this technique in our breakpoint mixin by passing a label as another argument. @include breakpoint(8, 'desktop') { /* styles */ } Sass can take that label and use it when writing the corresponding media query. We just need to slightly modify our breakpoint mixin. @mixin breakpoint($min, $label) { @media (min-width: fixed($min) + em($grid-gutter)) { // label our mq with CSS generated content body::before { content: $label; display: none; } .wrapper { width: fixed($min) - em($grid-gutter); margin-left: auto; margin-right: auto; } @content } } This allows us to label our breakpoints with a user-friendly string. Now that our media queries are defined and labeled, we just need JavaScript to step in and read which label is active. // get css generated label for active media query var label = getComputedStyle(document.body, '::before')['content']; JavaScript now knows which layout is active by reading the label in the current media query—we just need to match that label to an image. I prefer to store references to different image sizes as data attributes on my image tag. <img class="responsive-image" data-mobile="mobile.jpg" data-desktop="desktop.jpg" /> <noscript><img src="desktop.jpg" /></noscript> These data attributes have names that match the labels set in my CSS. So while there is some duplication going on, setting a keyword like ‘tablet’ in two places is much easier than hardcoding media query values. With matching labels in CSS and HTML our script can marry the two and load the right sized image for our layout. // get css generated label for active media query var label = getComputedStyle(document.body, '::before')['content']; // select image var $image = $('.responsive-image'); // create source from data attribute $image.attr('src', $image.data(label)); Demo With some slight additions to our previous Codepen demo you can see this responsive image technique in action. While the above JavaScript will work it is not nearly robust enough for production so the demo uses a jQuery plugin that can accomodate multiple images, reloading on screen resize and fallbacks if something doesn’t match up. Creating a Framework This media query mixin and responsive image JavaScript are the center piece of a front end framework I use to develop websites. It’s a fluid, mobile first foundation that uses the breakpoint mixin to structure fixed width layouts for tablet and desktop. Significant effort was focused on making this framework completely cross-browser. For example, one of the problems with using media queries is that essential desktop structure code ends up being hidden from legacy Internet Explorer. Respond.js is an excellent polyfill, but if you’re comfortable serving a single desktop layout to older IE, we don’t need JavaScript. We simply need to capture layout code outside of a media query and sandbox it under an IE only class name. // set IE fallback layout to 8 columns $ie-support = 8; // inside of our breakpoint mixin (but outside the media query) @if ($ie-support and $min <= $ie-support) { .lt-ie9 { @content; } } Perspective Regained Thinking in columns means you are thinking about content layout. How big of a screen do you need for 12 columns? Who cares? Having Sass write media queries means you can use intuitive numbers for content layout. A fixed grid means more layout control and less edge cases to test than a fluid grid. Using CSS labels for activating responsive images means you don’t have to duplicate breakpoints across separations of concern. It’s a harmonious blend of approaches that gives us something we need—responsive design that feels intuitive. And design that, from the very outset, focuses on what matters most. Just like our kindergarten teachers taught us: It’s what’s inside that counts. 2012 Les James lesjames 2012-12-13T00:00:00+00:00 https://24ways.org/2012/redesigning-the-media-query/ code
212 Refactoring Your Way to a Design System I love refactoring code. Absolutely love it. There’s 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. I 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. Una 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’s definitely easier to establish these before project work begins, that doesn’t mean it is the only path to success. It’s 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. This is where refactoring comes into play. According to Martin Fowler, “refactoring 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.” It’s 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. Build a solid foundation When 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. During 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. If 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. I want to note that if your refactor includes creating new coding standards or a CSS architecture, don’t 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. Focus on the features The key principle to cleaning up a complex codebase is to always refactor in the service of a feature. — Max Kanat-Alexander Refactoring 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’t 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. For 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’t 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. Ideally, you’ll 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. In addition, if you’re 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’ value. By providing a concrete example of how working towards a design system contributed to the project’s success, you’re gathering the data necessary to secure buy-in for a larger-scale effort. It’s a great way to show value, rather than just talking about it. Show, don’t tell Perhaps 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. There 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. I’ve listed just a few tools below; for even more, check out the tools sections of styleguides.io. Fractal Pattern Lab Drizzle Fabricator Astrum Catalog Regardless of what tool you settle on, it needs to integrate well with your current workflow. Conclusion: always be refactoring If you’re 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’s built. After a few projects, you’ll find yourself with a decent start to a design system. Good luck, and happy holidays! Further reading: Why Design Systems Fail CSS Architecture for Design Systems Refactoring: Improving the Design of Existing Code Refactoring CSS: The Three I’s Refactoring is About Features 2017 Mina Markham minamarkham 2017-12-23T00:00:00+00:00 https://24ways.org/2017/refactoring-your-way-to-a-design-system/ code
243 Researching a Property in the CSS Specifications I frequently joke that I’m “reading the specs so you don’t have to”, as I unpack some detail of a CSS spec in a post on my blog, some documentation for MDN, or an article on Smashing Magazine. However waiting for someone like me to write an article about something is a pretty slow way to get the information you need. Sometimes people like me get things wrong, or specifications change after we write a tutorial. What if you could just look it up yourself? That’s what you get when you learn to read the CSS specifications, and in this article my aim is to give you the basic details you need to grab quick information about any CSS property detailed in the CSS specs. Where are the CSS Specifications? The easiest way to see all of the CSS specs is to take a look at the Current Work page in the CSS section of the W3C Website. Here you can see all of the specifications listed, the level they are at and their status. There is also a link to the specification from this page. I explained CSS Levels in my article Why there is no CSS 4. Who are the specifications for? CSS specifications are for everyone who uses CSS. You might be a browser engineer - referred to as an implementor - needing to know how to implement a feature, or a web developer - referred to as an author - wanting to know how to use the feature. The fact that both parties are looking at the same document hopefully means that what the browser displays is what the web developer expected. Which version of a spec should I look at? There are a couple of places you might want to look. Each published spec will have the latest published version, which will have TR in the URL and can be accessed without a date (which is always the newest version) or at a date, which will be the date of that publication. If I’m referring to a particular Working Draft in an article I’ll typically link to the dated version. That way if the information changes it is possible for someone to see where I got the information from at the time of writing. If you want the very latest additions and changes to the spec, then the Editor’s Draft is the place to look. This is the version of the spec that the editors are committing changes to. If I make a change to the Multicol spec and push it to GitHub, within a few minutes that will be live in the Editor’s Draft. So it is possible there are errors, bits of text that we are still working out and so on. The Editor’s Draft however is definitely the place to look if you are wanting to raise an issue on a spec, as it may be that the issue you are about to raise is already fixed. If you are especially keen on seeing updates to specifications keep an eye on https://drafts.csswg.org/ as this is a list of drafts, along with the date they were last updated. How to approach a spec The first thing to understand is that most CSS Specifications start with the most straightforward information, and get progressively further into the weeds. For an author the initial examples and explanations are likely to be of interest, and then the property definitions and examples. Therefore, if you are looking at a vast spec, know that you probably won’t need to read all the way to the bottom, or read every section in detail. The second thing that is useful to know about modern CSS specifications is how modularized they are. It really never is a case of finding everything you need in a single document. If we tried to do that, there would be a lot of repetition and likely inconsistency between specs. There are some key specifications that many other specifications draw on, such as: Values and Units Intrinsic and Extrinsic Sizing Box Alignment When something is defined in another specification the spec you are reading will link to it, so it is worth opening that other spec in a new tab in order that you can refer back to it as you explore. Researching your property As an example we will take a look at the property grid-auto-rows, this property defines row tracks in the implicit grid when using CSS Grid Layout. The first thing you will need to do is find out which specification defines this property. You might already know which spec the property is part of, and therefore you could go directly to the spec and search using your browser or look in the navigation for the spec to find it. Alternatively, you could take a look at the CSS Property Index, which is an automatically generated list of CSS Properties. Clicking on a property will take you to the TR version of the spec, the latest published draft, and the definition of that property in it. This definition begins with a panel detailing the syntax of this property. For grid-auto-rows, you can see that it is listed along with grid-auto-columns as these two properties are essentially identical. They take the same values and work in the same way, one for rows and the other for columns. Value For value we can see that the property accepts a value <track-size>. The next thing to do is to find out what that actually means, clicking will take you to where it is defined in the Grid spec. The <track-size> value is defined as accepting various values: <track-breadth> minmax( <inflexible-breadth> , <track-breadth> ) fit-content( <length-percentage> We need to head down the rabbit hole to find out what each of these mean. From here we essentially go down line by line until we have unpacked the value of track-size. <track-breadth> is defined just below <track-size> as: <length-percentage> <flex> min-content max-content auto So these are all things that would be valid to use as a value for grid-auto-rows. The first value of <length-percentage> is something you will see in many specifications as a value. It means that you can use a length unit - for example px or em - or a percentage. Some properties only accept a <length> in which case you know that you cannot use a percentage as the value. This means that you could have grid-auto-rows with any of the following values. grid-auto-rows: 100px; grid-auto-rows: 1em; grid-auto-rows: 30%; When using percentages, it is important to know what it is a percentage of. As a percentage has to resolve from something. There is text in the spec which explains how column and row percentages work. “<percentage> values are relative to the inline size of the grid container in column grid tracks, and the block size of the grid container in row grid tracks.” This means that in a horizontal writing mode such as when using English, a percentage when used as a track-size in grid-auto-columns would be a percentage of the width of the grid, and a percentage in grid-auto-rows a percentage of the height of the grid. The second value of <flex> is also defined here, as “A non-negative dimension with the unit fr specifying the track’s flex factor.” This is the fr unit, and the spec links to a fuller definition of fr as this unit is only used in Grid Layout so it is therefore defined in the grid spec. We now know that a valid value would be: grid-auto-rows: 1fr; There is some useful information about the fr unit in this part of the spec. It is noted that the fr unit has an automatic minimum. This means that 1fr is really minmax(auto, 1fr). This is why having a number of tracks all at 1fr does not mean that all are equal sized, as a larger item in any of the tracks would have a large auto size and therefore would be larger after spare space had been distributed. We then have min-content and max-content. These keywords can be used for track sizing and the specification defines what they mean in the context of sizing a track, representing the min and max-sizing contributions of the grid tracks. You will see that there are various terms linked in the definition, so if you do not know what these mean you can follow them to find out. For example the spec links max-content contribution to the CSS Intrinsic and Extrinsic Sizing specification. This is one of those specs which is drawn on by many other specifications. If we follow that link we can read the definition there and follow further links to understand what each term means. The more that you read specifications the more these terms will become familiar to you. Just like learning a foreign language, at first you feel like you have to look up every little thing. After a while you remember the vocabulary. We can now add min-content and max-content to our available values. grid-auto-rows: min-content; grid-auto-rows: max-content; The final item in our list is auto. If you are familiar with using Grid Layout, then you are probably aware that an auto sized track for will grow to fit the content used. There is an interesting note here in the spec detailing that auto sized rows will stretch to fill the grid container if there is extra space and align-content or justify-content have a value of stretch. As stretch is the default value, that means these tracks stretch by default. Tracks using other types of length will not behave like this. grid-auto-rows: auto; So, this was the list for <track-breadth>, the next possible value is minmax( <inflexible-breadth> , <track-breadth> ). So this is telling us that we can use minmax() as a value, the final (max) value will be <track-breadth> and we have already unpacked all of the allowable values there. The first value (min) is detailed as an <inflexible-breadth>. If we look at the values for this, we discover that they are the same as <track-breadth>, minus the <flex> value: <length-percentage> min-content max-content auto We already know what all of these do, so we can add possible minmax() values to our list of values for <track-size>. grid-auto-rows: minmax(100px, 200px); grid-auto-rows: minmax(20%, 1fr); grid-auto-rows: minmax(1em, auto); grid-auto-rows: minmax(min-content, max-content); Finally we can use fit-content( <length-percentage>. We can see that fit-content takes a value of <length-percentage> which we already know to be either a length unit, or a percentage. The spec details how fit-content is worked out, and it essentially allows a track which acts as if you had used the max-content keyword, however the track stops growing when it hits the length passed to it. grid-auto-rows: fit-content(200px); grid-auto-rows: fit-content(20%); Those are all of our possible values, and to round things off, check again at the initial <track-size> value, you can see it has a little + sign next to it, click that and you will be taken to the CSS Values and Units module to find that, “A plus (+) indicates that the preceding type, word, or group occurs one or more times.” This means that we can pass a single track size to grid-auto-rows or multiple track sizes as a space separated list. Below the box is an explanation of what happens if you pass in more than one track size: “If multiple track sizes are given, the pattern is repeated as necessary to find the size of the implicit tracks. The first implicit grid track after the explicit grid receives the first specified size, and so on forwards; and the last implicit grid track before the explicit grid receives the last specified size, and so on backwards.” Therefore with the following CSS, if five implicit rows were needed they would be as follows: 100px 1fr auto 100px 1fr .grid { display: grid; grid-auto-rows: 100px 1fr auto; } Initial We can now move to the next line in the box, and you’ll be glad to know that it isn’t going to require as much unpacking! This simply defines the initial value for grid-auto-rows. If you do not specify anything, created rows will be auto sized. All CSS properties have an initial value that they will use if they are invoked as part of the usage of the specification they are in, but you do not set a value for them. In the case of grid-auto-rows it is used whenever rows are created in the implicit grid, so it needs to have a value to be used even if you do not set one. Applies to This line tells us what this property is used for. Some properties are used in multiple places. For example if you look at the definition for justify-content in the Box Alignment specification you can see it is used in multicol containers, flex containers, and grid containers. In our case the property only applies for grid containers. Inherited This tells us if the property can be inherited from a parent element if it is not set. In the case of grid-auto-rows it is not inherited. A property such as color is inherited, so you do not need to set it on each element. Percentages Are percentages allowed for this property, and if so how are they calculated. In this case we are referred to the definition for grid-template-columns and grid-template-rows where we discover that the percentage is from the corresponding dimension of the content area. Media This defines the media group that the property belongs to. In this case visual. Computed Value This details how the value is resolved. The grid-auto-rows property again refers to track sizing as defined for grid-template-columns and grid-template-rows, which tells us the computed value is as specified with lengths made absolute. Canonical Order If you have a property–generally a shorthand property–which takes multiple values in a set order, then those values need to be serialized in the order detailed in the grammar for that property. In general you don’t need to worry about this value in the table. Animation Type This details whether the property can be animated, and if so what type of animation. This is useful if you are trying to animate something and not getting the result that you expect. Note that just because something is listed in the spec as animatable does not mean that browsers will have implemented animation for that property yet! That’s (mostly) it! Sometimes the property will have additional examples - there is one underneath the table for grid-auto-rows. These are worth looking at as they will highlight usage of the property that the spec editor has felt could use an example. There may also be some additional text explaining anythign specific to this property. In selecting grid-auto-rows I chose a fairly complex property in terms of the work we needed to do to unpack the value. Many properties are far simpler than this. However ultimately, even when you come across a complex value, it really is just a case of stepping through the definitions until you come to the bottom of the rabbit hole. Being able to work out what is valid for each property is incredibly useful. It means you don’t waste time trying to use a value that doesn’t work for that property. You also may find that there are values you weren’t aware of, that solve problems for you. Further reading Specifications are not designed to be user manuals, and while they often contain examples, these are pretty terse as they need to be clear to demonstrate their particular point. The manual for the Web Platform is MDN Web Docs. Pairing reading a specification with the examples and information on an MDN property page such as the one for grid-auto-rows is a really great way to ensure that you have all the information and practical usage examples you might need. You may also find useful: Value Definition Syntax on MDN. The MDN Glossary defines many common terms. Understanding the CSS Property Value Syntax goes into more detail in terms of reading the syntax. How to read W3C Specs - from 2001 but still relevant. I hope this article has gone some way to demystify CSS specifications for you. Even if the specifications are not your preferred first stop to learn about new CSS, being able to go directly to the source and avoid having your understanding filtered by someone else, can be very useful indeed. 2018 Rachel Andrew rachelandrew 2018-12-14T00:00:00+00:00 https://24ways.org/2018/researching-a-property-in-the-css-specifications/ code
46 Responsive Enhancement 24 ways has been going strong for ten years. That’s an aeon in internet timescales. Just think of all the changes we’ve seen in that time: the rise of Ajax, the explosion of mobile devices, the unrecognisably changed landscape of front-end tooling. Tools and technologies come and go, but one thing has remained constant for me over the past decade: progressive enhancement. Progressive enhancement isn’t a technology. It’s more like a way of thinking. Instead of thinking about the specifics of how a finished website might look, progressive enhancement encourages you to think about the fundamental meaning of what the website is providing. So instead of thinking of a website in terms of its ideal state in a modern browser on a nice widescreen device, progressive enhancement allows you to think about the core functionality in a more abstract way. Once you’ve figured out what the core functionality is – adding an item to a shopping cart, posting a message, sharing a photo – then you can enable that functionality in the simplest possible way. That usually means starting with good old-fashioned HTML. Links and forms are often all you need. Then, once you have the core functionality working in a basic way, you can start to enhance to make a progressively better experience for more modern browsers. The advantage of working this way isn’t just that your site will work in older browsers (albeit in a rudimentary way). It also ensures that if anything goes wrong in a modern browser, it won’t be catastrophic. There’s a common misconception that progressive enhancement means that you’ll spend your time dealing with older browsers, but in fact the opposite is true. Putting the basic functionality into place doesn’t take very long at all. And once you’ve done that, you’re free to spend all your time experimenting with the latest and greatest browser technologies, secure in the knowledge that even if they aren’t universally supported yet, that’s OK: you’ve already got your fallback in place. The key to thinking about web development this way is realising that there isn’t one final interface – there could be many, slightly different interfaces depending on the properties and capabilities of any particular user agent at any particular moment. And that’s OK. Websites do not need to look the same in every browser. Once you truly accept that, it’s an immensely liberating idea. Instead of spending your time trying to make websites look the same in wildly varying browsers, you can spend your time making sure that the core functionality of what you build works everywhere, while providing the best possible experience for more capable browsers. Allow me to demonstrate with a simple example: navigation. Step one: core functionality Let’s say we have a straightforward website about the twelve days of Christmas, with a page for each day. The core functionality is pretty clear: To read about any particular day. To browse from day to day. The first is easily satisfied by marking up the text with headings, paragraphs and all the usual structural HTML elements. The second is satisfied by providing a list of good ol’ hyperlinks. Now where’s the best place to position this navigation list? Personally, I’m a big fan of the jump-to-footer pattern. This puts the content first and the navigation second. At the top of the page there’s a link with an href attribute pointing to the fragment identifier for the navigation. <body> <main role="main" id="top"> <a href="#menu" class="control">Menu</a> ... </main> <nav role="navigation" id="menu"> ... <a href="#top" class="control">Dismiss</a> </nav> </body> See the footer-anchor pattern in action. Because it’s nothing more than a hyperlink, this works in just about every browser since the dawn of the web. Following hyperlinks is what web browsers were made to do (hence the name). Step two: layout as an enhancement The footer-anchor pattern is a particularly neat solution on small-screen devices, like mobile phones. Once more screen real estate is available, I can use the magic of CSS to reposition the navigation above the content. I could use position: absolute, flexbox or, in this case, display: table. @media all and (min-width: 35em) { .control { display: none; } body { display: table; } [role="navigation"] { display: table-caption; columns: 6 15em; } } See the styles for wider screens in action Step three: enhance! Right. At this point I’m providing core functionality to everyone, and I’ve got nice responsive styles for wider screens. I could stop here, but the real advantage of progressive enhancement is that I don’t have to. From here on, I can go crazy adding all sorts of fancy enhancements for modern browsers, without having to worry about providing a fallback for older browsers – the fallback is already in place. What I’d really like is to provide a swish off-canvas pattern for small-screen devices. Here’s my plan: Position the navigation under the main content. Listen out for the .control links being activated and intercept that action. When those links are activated, toggle a class of .active on the body. If the .active class exists, slide the content out to reveal the navigation. Here’s the CSS for positioning the content and navigation: @media all and (max-width: 35em) { [role="main"] { transition: all .25s; width: 100%; position: absolute; z-index: 2; top: 0; right: 0; } [role="navigation"] { width: 75%; position: absolute; z-index: 1; top: 0; right: 0; } .active [role="main"] { transform: translateX(-75%); } } In my JavaScript, I’m going to listen out for any clicks on the .control links and toggle the .active class on the body accordingly: (function (win, doc) { 'use strict'; var linkclass = 'control', activeclass = 'active', toggleClassName = function (element, toggleClass) { var reg = new RegExp('(s|^)' + toggleClass + '(s|$)'); if (!element.className.match(reg)) { element.className += ' ' + toggleClass; } else { element.className = element.className.replace(reg, ''); } }, navListener = function (ev) { ev = ev || win.event; var target = ev.target || ev.srcElement; if (target.className.indexOf(linkclass) !== -1) { ev.preventDefault(); toggleClassName(doc.body, activeclass); } }; doc.addEventListener('click', navListener, false); }(this, this.document)); I’m all set, right? Not so fast! Cutting the mustard I’ve made the assumption that addEventListener will be available in my JavaScript. That isn’t a safe assumption. That’s because JavaScript – unlike HTML or CSS – isn’t fault-tolerant. If you use an HTML element or attribute that a browser doesn’t understand, or if you use a CSS selector, property or value that a browser doesn’t understand, it’s no big deal. The browser will just ignore what it doesn’t understand: it won’t throw an error, and it won’t stop parsing the file. JavaScript is different. If you make an error in your JavaScript, or use a JavaScript method or property that a browser doesn’t recognise, that browser will throw an error, and it will stop parsing the file. That’s why it’s important to test for features before using them in JavaScript. That’s also why it isn’t safe to rely on JavaScript for core functionality. In my case, I need to test for the existence of addEventListener: (function (win, doc) { if (!win.addEventListener) { return; } ... }(this, this.document)); The good folk over at the BBC call this kind of feature test cutting the mustard. If a browser passes the test, it cuts the mustard, and so it gets the enhancements. If a browser doesn’t cut the mustard, it doesn’t get the enhancements. And that’s fine because, remember, websites don’t need to look the same in every browser. I want to make sure that my off-canvas styles are only going to apply to mustard-cutting browsers. I’m going to use JavaScript to add a class of .cutsthemustard to the document: (function (win, doc) { if (!win.addEventListener) { return; } ... var enhanceclass = 'cutsthemustard'; doc.documentElement.className += ' ' + enhanceclass; }(this, this.document)); Now I can use the existence of that class name to adjust my CSS: @media all and (max-width: 35em) { .cutsthemustard [role="main"] { transition: all .25s; width: 100%; position: absolute; z-index: 2; top: 0; right: 0; } .cutsthemustard [role="navigation"] { width: 75%; position: absolute; z-index: 1; top: 0; right: 0; } .cutsthemustard .active [role="main"] { transform: translateX(-75%); } } See the enhanced mustard-cutting off-canvas navigation. Remember, this only applies to small screens so you might have to squish your browser window. Enhance all the things! This was a relatively simple example, but it illustrates the thinking behind progressive enhancement: once you’re providing the core functionality to everyone, you’re free to go crazy with all the latest enhancements for modern browsers. Progressive enhancement doesn’t mean you have to provide all the same functionality to everyone – quite the opposite. That’s why it’s key to figure out early on what the core functionality is, and make sure that it can be provided with the most basic technology. But from that point on, you’re free to add many more features that aren’t mission-critical. You should reward more capable browsers by giving them more of those features, such as animation in CSS, geolocation in JavaScript, and new input types in HTML. Like I said, progressive enhancement isn’t a technology. It’s a way of thinking. Once you start thinking this way, you’ll be prepared for whatever the next ten years throws at us. 2014 Jeremy Keith jeremykeith 2014-12-09T00:00:00+00:00 https://24ways.org/2014/responsive-enhancement/ code
79 Responsive Images: What We Thought We Needed If you were to read a web designer’s Christmas wish list, it would likely include a solution for displaying images responsively. For those concerned about users downloading unnecessary image data, or serving images that look blurry on high resolution displays, finding a solution has become a frustrating quest. Having experimented with complex and sometimes devilish hacks, consensus is forming around defining new standards that could solve this problem. Two approaches have emerged. The <picture> element markup pattern was proposed by Mat Marquis and is now being developed by the Responsive Images Community Group. By providing a means of declaring multiple sources, authors could use media queries to control which version of an image is displayed and under what conditions: <picture width="500" height="500"> <source media="(min-width: 45em)" src="large.jpg"> <source media="(min-width: 18em)" src="med.jpg"> <source src="small.jpg"> <img src="small.jpg" alt=""> <p>Accessible text</p> </picture> A second proposal put forward by Apple, the srcset attribute, uses a more concise syntax intended for use with the <img> element, although it could be compatible with the <picture> element too. This would allow authors to provide a set of images, but with the decision on which to use left to the browser: <img src="fallback.jpg" alt="" srcset="small.jpg 640w 1x, small-hd.jpg 640w 2x, med.jpg 1x, med-hd.jpg 2x "> Enter Scrooge Men’s courses will foreshadow certain ends, to which, if persevered in, they must lead. Ebenezer Scrooge Given the complexity of this issue, there’s a heated debate about which is the best option. Yet code belies a certain truth. That both feature verbose and opaque syntax, I’m not sure either should find its way into the browser – especially as alternative approaches have yet to be fully explored. So, as if to dampen the festive cheer, here are five reasons why I believe both proposals are largely redundant. 1. We need better formats, not more markup As we move away from designs defined with fixed pixel values, bitmap images look increasingly unsuitable. While simple images and iconography can use scalable vector formats like SVG, for detailed photographic imagery, raster formats like GIF, PNG and JPEG remain the only suitable option. There is scope within current formats to account for varying bandwidth but this requires cooperation from browser vendors. Newer formats like JPEG2000 and WebP generate higher quality images with smaller file sizes, but aren’t widely supported. While it’s tempting to try to solve this issue by inventing new markup, the crux of it remains at the file level. Daan Jobsis’s experimentation with image compression strengthens this argument. He discovered that by increasing the dimensions of a JPEG image while simultaneously reducing its quality, a smaller files could be produced, with the resulting image looking just as good on both standard and high-resolution displays. This may be a hack in lieu of a more permanent solution, but it’s applied in the right place. Easy to accomplish with existing tools and without compatibility issues, it has few downsides. Further experimentation in this area should be encouraged, with standardisation efforts more helpful if focused on developing new image formats or, preferably, extending existing ones. 2. Art direction doesn’t belong in markup A desired benefit of the <picture> markup pattern is to allow for greater art direction. For example, rather than scaling down images on smaller displays to the point that their content is hard to discern, we could present closer crops instead: This can be achieved with CSS of course, although with a download penalty for those parts of an image not shown. This point may be negligible, however, since in the context of adaptable layouts, these hidden areas may end up being revealed anyway. Art direction concerns design, not content. If we wish to maintain a separation of concerns, including presentation within our markup seems misguided. 3. The size of a display has little relation to the size of an image By using media queries, the <picture> element allows authors to choose which characteristics of the screen or viewport to query for different images to be displayed. In developing sites at Clearleft, we have noticed that the viewport is essentially arbitrary, with the size of an image’s containing element more important. For example, look at how this grid of images may adapt at different viewport widths: As we build more modular systems, components need to be adaptable in and of themselves. There is a case to be made for developing more contextual methods of querying, rather than those based on attributes of the display. 4. We haven’t lived with the problem long enough A key strength of the web is that the underlying platform can be continually iterated. This can also be problematic if snap judgements are made about what constitutes an improvement. The early history of the web is littered with such examples, be it the perceived need for blinking text or inline typographic styling. To build a platform for the future, additions to it should be carefully considered. And if we want more consistent support across browsers, burdening vendors with an ever increasing list of features seems counterproductive. Only once the need for a new feature is sufficiently proven, should we look to standardise it. Before we could declare hover effects, rounded corners and typographic styling in CSS, we used JavaScript as a polyfill. Sure, doing so was painful, but use cases were fully explored, and the CSS specification better reflected the needs of authors. 5. Images and the web aesthetic The srcset proposal has emerged from a company that markets its phones as being able to browse the real – yet squashed down, tapped and zoomable – web. Perhaps Apple should make its own website responsive before suggesting how the rest of us should do so. Converserly, while the <picture> proposal has the backing of a few respected developers and designers, it was born out of the work Mat Marquis and Filament Group did for the Boston Globe. As the first large-scale responsive design, this was a landmark project that ignited the responsive web design movement and proved its worth. But it was the first. Its design shares a vernacular to that of contemporary newspaper websites, with a columnar, image-laden and densely packed layout. Compared to more recent examples – Quartz, The Next Web and the New York Times Skimmer – it feels out of step with the future direction of news sites. In seeking out a truer aesthetic for the web in which software interfaces have greater influence, we might discover that the need for responsive images isn’t as great as originally thought. Building for the future With responsive design, we’ve accepted the idea that a fully fluid layout, rather than a set of fixed layouts, is best suited to the web’s unpredictable nature. Current responsive image proposals are antithetical to this approach. We need solutions that lack complexity, are device-agnostic and work within existing workflows. Any proposal that requires different versions of the same image to be created, is likely to have to acquiesce under the pressure of reality. While it’s easy to get distracted about the size and quality of an image, and how we might choose to serve it, often the simplest solution is not to include it at all. After years of gluttonous design practice, in which fast connections and expansive display sizes were an accepted norm, we have got use to filling pages with needless images and countless items of page furniture. To design more adaptable experiences, the presence of every element needs to be questioned, for its existence requires additional data to be downloaded or futher complexity within a design system. Conditional loading techniques mean that the inclusion of images is no longer a binary choice, but can instead appear in a progressively enhanced manner. So here is my proposal. Instead of spending the next year worrying about responsive images, let’s embrace the constraints of the medium, and seek out new solutions that can work within them. 2012 Paul Lloyd paulrobertlloyd 2012-12-11T00:00:00+00:00 https://24ways.org/2012/responsive-images-what-we-thought-we-needed/ code
84 Responsive Responsive Design Now more than ever, we’re designing work meant to be viewed along a gradient of different experiences. Responsive web design offers us a way forward, finally allowing us to “design for the ebb and flow of things.” With those two sentences, Ethan closed the article that introduced the web to responsive design. Since then, responsive design has taken the web by storm. Seemingly every day, some company is touting their new responsive redesign. Large brands such as Microsoft, Time and Disney are getting in on the action, blowing away the once common criticism that responsive design was a technique only fit for small blogs. Certainly, this is a good thing. As Ethan and John Allsopp before him, were right to point out, the inherent flexibility of the web is a feature, not a bug. The web’s unique ability to be consumed and interacted with on any number of devices, with any number of input methods is something to be embraced. But there’s one part of the web’s inherent flexibility that seems to be increasingly overlooked: the ability for the web to be interacted with on any number of networks, with a gradient of bandwidth constraints and latency costs, on devices with varying degrees of hardware power. A few months back, Stephanie Rieger tweeted “Shoot me now…responsive design has seemingly become confused with an opportunity to reduce performance rather than improve it.” I would love to disagree, but unfortunately the evidence is damning. Consider the size and number of requests for four highly touted responsive sites that were launched this year: 74 requests, 1,511kb 114 requests, 1,200kb 99 requests, 1,298kb 105 requests, 5,942kb And those numbers were for the small screen versions of each site! These sites were praised for their visual design and responsive nature, and rightfully so. They’re very easy on the eyes and a lot of thought went into their appearance. But the numbers above tell an inconvenient truth: for all the time spent ensuring the visual design was airtight, seemingly very little (if any) attention was given to their performance. It would be one thing if these were the exceptions, but unfortunately they’re not. Guy Podjarny, who has done a lot of research around responsive performance, discovered that 86% of the responsive sites he tested were either the same size or larger on the small screen as they were on the desktop. The reality is that high performance should be a requirement on any web project, not an afterthought. Poor performance has been tied to a decrease in revenue, traffic, conversions, and overall user satisfaction. Case study after case study shows that improving performance, even marginally, will impact the bottom line. The situation is no different on mobile where 71% of people say they expect sites to load as quickly or faster on their phone when compared to the desktop. The bottom line: performance is a fundamental component of the user experience. So, given it’s extreme importance in the success of any web project, why is it that we’re seeing so many bloated responsive sites? First, I adamantly disagree with the belief that poor performance is inherent to responsive design. That’s not a rule – it’s a cop-out. It’s an example of blaming the technique when we should be blaming the implementation. This argument also falls flat because it ignores the fact that the trend of fat sites is increasing on the web in general. While some responsive sites are the worst offenders, it’s hardly an issue resigned to one technique. To fix the issue, we need to stop making excuses and start making improvements instead. Here, then, are some things we can do to start improving the state of responsive performance, and performance in general, right now. Create a culture of performance If you understand just how important performance is to the success of a project, the natural next step is to start creating a culture where high performance is a key consideration. One of the things you can do is set a baseline. Determine the maximum size and number of requests you are going to allow, and don’t let a page go live if either of those numbers is exceeded. The BBC does this with its responsive mobile site. A variation of that, which Steve Souders discussed in a recent podcast is to create a performance budget based on those numbers. Once you have that baseline set, if someone comes along and wants to add a something to the page, they have to make sure the page remains under budget. If it exceeds the budget, you have three options: Optimize an existing feature or asset on the page Remove an existing feature or asset from the page Don’t add the new feature or asset The idea here is that you make performance part of the process instead of something that may or may not get tacked on at the end. Embrace the pain This troubling trend of web bloat can be blamed in part on the lack of pain associated with poor performance. Most of us work on high-speed connections with low latency. When we fire up a 4Mb site, it doesn’t feel so bad. When I tested the previously mentioned 5,942kb site on a 3G network, it took over 93 seconds to load. A minute and a half just staring at a white screen. Had anyone working on that project experienced that, you can bet the site wouldn’t have launched in that state. Don’t just crunch numbers. Fire up your site on a slower network and see what it feels like to wait. If you don’t have access to a slow network, simulate one using a tool like Slowy, Throttle or the Network Conditioner found in Mac OS X 10.7. Watch for low-hanging fruit There are a bunch of general performance improvements that apply to any site (responsive or not) but often aren’t made. A great starting point is to refer to Yahoo!‘s list of rules. Some of this might sound complicated or intimidating, but it doesn’t have to be. You can grab an .htaccess file from HTML 5 Boilerplate or use Sergey Chernyshev’s drop-in .htaccess file. You can use tools like SpriteMe to simplify the creation of sprites, and ImageOptim to compress images. Just by implementing these simple optimizations you will achieve a noticeable improvement in terms of weight and page load time. Be careful with images The most common offender for poor responsive performance is downloading unnecessarily large images, or worse yet, multiple sizes of the same image. For background images, simply being careful with where and how you include the image can ensure you don’t get caught in the trap of multiple background images being downloaded without being used. Don’t count on display:none to help. While it may hide elements from displaying on screen, those images will still be requested and downloaded. Content images can be a little trickier. Whatever you do, don’t serve a large image that works on a large screen display to small screens. It’s wasteful, not only in terms of adding weight to the page, but also in wasting precious memory. Instead, use a tool like Adaptive Images or src.sencha.io to make sure only appropriately sized images are being downloaded. The new <picture> element that has been so often discussed is another excellent solution if you’re feeling particularly future-oriented. A picture polyfill exists so that you can start using the element now without any worries about support. Conditional loading Don’t load any more than you absolutely need to. If a script isn’t needed at certain sizes, use the matchMedia polyfill to ensure it only loads when needed. Use eCSSential to do the same for unnecessary CSS files. Last year on 24 ways, Jeremy Keith wrote an article about conditional loading of content in a responsive design based on the screen width. The technique was later refined by the Filament Group into what they dubbed the Ajax-Include Pattern. It’s a powerful and simple way to lighten the load on small screens as well as reduce clutter. Go vanilla? If you take a look at the HTTP Archive you’ll see that other than image size, JavaScript is the heaviest asset on a page weighing in at 215kb on average. It also boasts the fifth highest correlation to load time as well as the second highest correlation to render time. Much of the weight can be attributed to our industry’s increasing reliance on frameworks. This is especially a concern on mobile devices. PPK recently exclaimed that current JavaScript libraries are just “too heavy for mobile”. “Research from Stoyan Stefanov on parse times supports this. On some Android and iOS devices, it can take as long as 200-300ms just to parse jQuery. There’s nothing wrong about using a framework, but the problem is that they’ve become the default. Before dropping another framework or plugin into a page, we should stop to consider the value it adds and whether we could accomplish what we need to do using a combination of vanilla JavaScript and CSS instead. (This is a great example of a scenario where a performance budget could help.) Start thinking beyond visual aesthetics We love to tout the web’s universality when discussing the need for responsive design. But that universality is not limited simply to screen size. Networks and hardware capabilities must factor in as well. The web is an incredibly dynamic and interactive medium, and designing for it demands that we consider more than just visual aesthetics. Let’s not forget to give those other qualities the attention they deserve. 2012 Tim Kadlec timkadlec 2012-12-05T00:00:00+00:00 https://24ways.org/2012/responsive-responsive-design/ design
142 Revealing Relationships Can Be Good Form A few days ago, a colleague of mine – someone I have known for several years, who has been doing web design for several years and harks back from the early days of ZDNet – was running through a prototype I had put together for some user testing. As with a lot of prototypes, there was an element of ‘smoke and mirrors’ to make things look like they were working. One part of the form included a yes/no radio button, and selecting the Yes option would, in the real and final version of the form, reveal some extra content. Rather than put too much JavaScript in the prototype, I took a preverbial shortcut and created a link which I wrapped around the text next to the radio button – clicking on that link would cause the form to mimic a change event on the radio button. But it wasn’t working for him. Why was that? Because whereas I created the form using a <label> tag for each <input> and naturally went to click on the text rather than the form control itself, he was going straight for the control (and missing the sneaky little <a href> I’d placed around the text). Bah! There goes my time-saver. So, what did I learn? That a web professional who has used the Internet for years had neither heard of the <label> tag, nor had he ever tried clicking on the text. It just goes to show that despite its obvious uses, the label element is not as well known as it rightfully deserves to be. So, what’s a web-standards-loving guy to do? Make a bit more bleedin’ obvious, that’s what! The Mouse Pointer Trick OK, this is the kind of thing that causes some people outrage. A dead simple way of indicating that the label does something is to use a snippet of CSS to change the default mouse cursor to a hand. It’s derided because the hand icon is usually used for links, and some would argue that using this technique is misleading: label { cursor: pointer; } This is not a new idea, though, and you didn’t come here for this. The point is that with something very simple, you’ve made the label element discoverable. But there are other ways that you can do this that are web standards friendly and won’t upset the purists quite so much as the hand/pointer trick. Time to wheel in the JavaScript trolley jack … Our Old Friend AddEvent First things, first, you’ll need to use the addEvent function (or your favourite variation thereof) that Scott Andrew devised and make that available to the document containing the form: function addEvent(elm, evType, fn, useCapture) { if(elm.addEventListener) { elm.addEventListener(evType, fn, useCapture); return true; } else if (elm.attachEvent) { var r = elm.attachEvent('on' + evType, fn); return r; } else { elm['on' + evType] = fn; } } Finding All Your Labels Once you’ve linked to the addEvent function (or embedded it on the page), you can start to get your JavaScripting fingers a-flexing. Now, what I’m suggesting you do here is: Identify all the label elements on the page by working your way through the DOM Find out the value of the for attribute for each label that you uncover Attach a behaviour or two to each of those label elements – and to the input that the label relates to (identified with the for attribute) Here’s the technobabble version of the steps above: function findLabels() { var el = document.getElementsByTagName("label"); for (i=0;i<el.length;i++) { var thisId = el[i].getAttribute("for"); if ((thisId)==null) { thisId = el[i].htmlFor; } if(thisId!="") { //apply these behaviours to the label el[i].onmouseover = highlightRelationship; el[i].onmouseout = hideRelationship; } } } function highlightRelationship() { var thisId = this.getAttribute("for"); if ((thisId)==null) { thisId = this.htmlFor; } this.className="showRel"; document.getElementById(thisId).className="showRel"; //if (document.getElementById(thisId).type=="text") document.getElementById(thisId).select(); } function hideRelationship() { var thisId = this.getAttribute("for"); if ((thisId)==null) { thisId = this.htmlFor; } this.className=""; document.getElementById(thisId).className=""; } addEvent(window, 'load', findLabels, false); Using the above script, you can apply a CSS class (I’ve called it showRel) to the elements when you hover over them. How you want it to look is up to you, of course. Here are a few examples of the idea. Note: the design is not exactly what you’d call ‘fancy’, and in the examples there is one input that looks broken but it is deliberately moved away from the label it relates to, just to demonstrate that you can show the relationship even from afar. Background colour changes on hover Background colour change + mouse pointer trick Background colour change + mouse pointer trick + text selection Hopefully you’ll agree that using an unobtrusive piece of JavaScript you can make otherwise ‘shy’ elements like the label reveal their true colours. Although you might want to tone down the colours from the ones I’ve used in this demo! 2006 Ian Lloyd ianlloyd 2006-12-13T00:00:00+00:00 https://24ways.org/2006/revealing-relationships-can-be-good-form/ ux
171 Rock Solid HTML Emails At some stage in your career, it’s likely you’ll be asked by a client to design a HTML email. Before you rush to explain that all the cool kids are using social media, keep in mind that when done correctly, email is still one of the best ways to promote you and your clients online. In fact, a recent survey showed that every dollar spent on email marketing this year generated more than $40 in return. That’s more than any other marketing channel, including the cool ones. There are a whole host of ingredients that contribute to a good email marketing campaign. Permission, relevance, timeliness and engaging content are all important. Even so, the biggest challenge for designers still remains building an email that renders well across all the popular email clients. Same same, but different Before getting into the details, there are some uncomfortable facts that those new to HTML email should be aware of. Building an email is not like building for the web. While web browsers continue their onward march towards standards, many email clients have stubbornly stayed put. Some have even gone backwards. In 2007, Microsoft switched the Outlook rendering engine from Internet Explorer to Word. Yes, as in the word processor. Add to this the quirks of the major web-based email clients like Gmail and Hotmail, sprinkle in a little Lotus Notes and you’ll soon realize how different the email game is. While it’s not without its challenges, rest assured it can be done. In my experience the key is to focus on three things. First, you should keep it simple. The more complex your email design, the more likely is it to choke on one of the popular clients with poor standards support. Second, you need to take your coding skills back a good decade. That often means nesting tables, bringing CSS inline and following the coding guidelines I’ll outline below. Finally, you need to test your designs regularly. Just because a template looks nice in Hotmail now, doesn’t mean it will next week. Setting your lowest common denominator To maintain your sanity, it’s a good idea to decide exactly which email clients you plan on supporting when building a HTML email. While general research is helpful, the email clients your subscribers are using can vary significantly from list to list. If you have the time there are a number of tools that can tell you specifically which email clients your subscribers are using. Trust me, if the testing shows almost none of them are using a client like Lotus Notes, save yourself some frustration and ignore it altogether. Knowing which email clients you’re targeting not only makes the building process easier, it can save you lots of time in the testing phase too. For the purpose of this article, I’ll be sharing techniques that give the best results across all of the popular clients, including the notorious ones like Gmail, Lotus Notes 6 and Outlook 2007. Just remember that pixel perfection in all email clients is a pipe dream. Let’s get started. Use tables for layout Because clients like Gmail and Outlook 2007 have poor support for float, margin and padding, you’ll need to use tables as the framework of your email. While nested tables are widely supported, consistent treatment of width, margin and padding within table cells is not. For the best results, keep the following in mind when coding your table structure. Set the width in each cell, not the table When you combine table widths, td widths, td padding and CSS padding into an email, the final result is different in almost every email client. The most reliable way to set the width of your table is to set a width for each cell, not for the table itself. <table cellspacing="0" cellpadding="10" border="0"> <tr> <td width="80"></td> <td width="280"></td> </tr> </table> Never assume that if you don’t specify a cell width the email client will figure it out. It won’t. Also avoid using percentage based widths. Clients like Outlook 2007 don’t respect them, especially for nested tables. Stick to pixels. If you want to add padding to each cell, use either the cellpadding attribute of the table or CSS padding for each cell, but never combine the two. Err toward nesting Table nesting is far more reliable than setting left and right margins or padding for table cells. If you can achieve the same effect by table nesting, that will always give you the best result across the buggier email clients. Use a container table for body background colors Many email clients ignore background colors specified in your CSS or the <body> tag. To work around this, wrap your entire email with a 100% width table and give that a background color. <table cellspacing="0" cellpadding="0" border="0" width="100%"> <tr> <td bgcolor=”#000000”> Your email code goes here. </td> </tr> </table> You can use the same approach for background images too. Just remember that some email clients don’t support them, so always provide a fallback color. Avoid unnecessary whitespace in table cells Where possible, avoid whitespace between your <td> tags. Some email clients (ahem, Yahoo! and Hotmail) can add additional padding above or below the cell contents in some scenarios, breaking your design for no apparent reason. CSS and general font formatting While some email designers do their best to avoid CSS altogether and rely on the dreaded <font> tag, the truth is many CSS properties are well supported by most email clients. See this comprehensive list of CSS support across the major clients for a good idea of the safe properties and those that should be avoided. Always move your CSS inline Gmail is the culprit for this one. By stripping the CSS from the <head> and <body> of any email, we’re left with no choice but to move all CSS inline. The good news is this is something you can almost completely automate. Free services like Premailer will move all CSS inline with the click of a button. I recommend leaving this step to the end of your build process so you can utilize all the benefits of CSS. Avoid shorthand for fonts and hex notation A number of email clients reject CSS shorthand for the font property. For example, never set your font styles like this. p { font:bold 1em/1.2em georgia,times,serif; } Instead, declare the properties individually like this. p { font-weight: bold; font-size: 1em; line-height: 1.2em; font-family: georgia,times,serif; } While we’re on the topic of fonts, I recently tested every conceivable variation of @font-face across the major email clients. The results were dismal, so unfortunately it’s web-safe fonts in email for the foreseeable future. When declaring the color property in your CSS, some email clients don’t support shorthand hexadecimal colors like color:#f60; instead of color:#ff6600;. Stick to the longhand approach for the best results. Paragraphs Just like table cell spacing, paragraph spacing can be tricky to get a consistent result across the board. I’ve seen many designers revert to using double <br /> or DIVs with inline CSS margins to work around these shortfalls, but recent testing showed that paragraph support is now reliable enough to use in most cases (there was a time when Yahoo! didn’t support the paragraph tag at all). The best approach is to set the margin inline via CSS for every paragraph in your email, like so: p { margin: 0 0 1.6em 0; } Again, do this via CSS in the head when building your email, then use Premailer to bring it inline for each paragraph later. If part of your design is height-sensitive and calls for pixel perfection, I recommend avoiding paragraphs altogether and setting the text formatting inline in the table cell. You might need to use table nesting or cellpadding / CSS to get the desired result. Here’s an example: <td width="200" style="font-weight:bold; font-size:1em; line-height:1.2em; font-family:georgia,'times',serif;">your height sensitive text</td> Links Some email clients will overwrite your link colors with their defaults, and you can avoid this by taking two steps. First, set a default color for each link inline like so: <a href="http://somesite.com/" style="color:#ff00ff">this is a link</a> Next, add a redundant span inside the a tag. <a href="http://somesite.com/" style="color:#ff00ff"><span style="color:#ff00ff">this is a link</span></a> To some this may be overkill, but if link color is important to your design then a superfluous span is the best way to achieve consistency. Images in HTML emails The most important thing to remember about images in email is that they won’t be visible by default for many subscribers. If you start your design with that assumption, it forces you to keep things simple and ensure no important content is suppressed by image blocking. With this in mind, here are the essentials to remember when using images in HTML email: Avoid spacer images While the combination of spacer images and nested tables was popular on the web ten years ago, image blocking in many email clients has ruled it out as a reliable technique today. Most clients replace images with an empty placeholder in the same dimensions, others strip the image altogether. Given image blocking is on by default in most email clients, this can lead to a poor first impression for many of your subscribers. Stick to fixed cell widths to keep your formatting in place with or without images. Always include the dimensions of your image If you forget to set the dimensions for each image, a number of clients will invent their own sizes when images are blocked and break your layout. Also, ensure that any images are correctly sized before adding them to your email. Some email clients will ignore the dimensions specified in code and rely on the true dimensions of your image. Avoid PNGs Lotus Notes 6 and 7 don’t support 8-bit or 24-bit PNG images, so stick with the GIF or JPG formats for all images, even if it means some additional file size. Provide fallback colors for background images Outlook 2007 has no support for background images (aside from this hack to get full page background images working). If you want to use a background image in your design, always provide a background color the email client can fall back on. This solves both the image blocking and Outlook 2007 problem simultaneously. Don’t forget alt text Lack of standards support means email clients have long destroyed the chances of a semantic and accessible HTML email. Even still, providing alt text is important from an image blocking perspective. Even with images suppressed by default, many email clients will display the provided alt text instead. Just remember that some email clients like Outlook 2007, Hotmail and Apple Mail don’t support alt text at all when images are blocked. Use the display hack for Hotmail For some inexplicable reason, Windows Live Hotmail adds a few pixels of additional padding below images. A workaround is to set the display property like so. img {display:block;} This removes the padding in Hotmail and still gives you the predicable result in other email clients. Don’t use floats Both Outlook 2007 and earlier versions of Notes offer no support for the float property. Instead, use the align attribute of the img tag to float images in your email. <img src="image.jpg" align="right"> If you’re seeing strange image behavior in Yahoo! Mail, adding align=“top” to your images can often solve this problem. Video in email With no support for JavaScript or the object tag, video in email (if you can call it that) has long been limited to animated gifs. However, some recent research I did into the HTML5 video tag in email showed some promising results. Turns out HTML5 video does work in many email clients right now, including Apple Mail, Entourage 2008, MobileMe and the iPhone. The real benefit of this approach is that if the video isn’t supported, you can provide reliable fallback content such as an animated GIF or a clickable image linking to the video in the browser. Of course, the question of whether you should add video to email is another issue altogether. If you lean toward the “yes” side check out the technique with code samples. What about mobile email? The mobile email landscape was a huge mess until recently. With the advent of the iPhone, Android and big improvements from Palm and RIM, it’s becoming less important to think of mobile as a different email platform altogether. That said, there are a few key pointers to keep in mind when coding your emails to get a decent result for your more mobile subscribers. Keep the width less than 600 pixels Because of email client preview panes, this rule was important long before mobile email clients came of age. In truth, the iPhone and Pre have a viewport of 320 pixels, the Droid 480 pixels and the Blackberry models hover around 360 pixels. Sticking to a maximum of 600 pixels wide ensures your design should still be readable when scaled down for each device. This width also gives good results in desktop and web-based preview panes. Be aware of automatic text resizing In what is almost always a good feature, email clients using webkit (such as the iPhone, Pre and Android) can automatically adjust font sizes to increase readability. If testing shows this feature is doing more harm than good to your design, you can always disable it with the following CSS rule: -webkit-text-size-adjust: none; Don’t forget to test While standards support in email clients hasn’t made much progress in the last few years, there has been continual change (for better or worse) in some email clients. Web-based providers like Yahoo!, Hotmail and Gmail are notorious for this. On countless occasions I’ve seen a proven design suddenly stop working without explanation. For this reason alone it’s important to retest your email designs on a regular basis. I find a quick test every month or so does the trick, especially in the web-based clients. The good news is that after designing and testing a few HTML email campaigns, you will find that order will emerge from the chaos. Many of these pitfalls will become quite predictable and your inbox-friendly designs will take shape with them in mind. Looking ahead Designing HTML email can be a tough pill for new designers and standardistas to swallow, especially given the fickle and retrospective nature of email clients today. With HTML5 just around the corner we are entering a new, uncertain phase. Will email client developers take the opportunity to repent on past mistakes and bring email clients into the present? The aim of groups such as the Email Standards Project is to make much of the above advice as redundant as the long-forgotten <blink> and <marquee> tags, however, only time will tell if this is to become a reality. Although not the most compliant (or fashionable) medium, the results speak for themselves – email is, and will continue to be one of the most successful and targeted marketing channels available to you. As a designer with HTML email design skills in your arsenal, you have the opportunity to not only broaden your service offering, but gain a unique appreciation of how vital standards are. Next steps Ready to get started? There are a number of HTML email design galleries to provide ideas and inspiration for your own designs. http://www.campaignmonitor.com/gallery/ http://htmlemailgallery.com/ http://inboxaward.com/ Enjoy! 2009 David Greiner davidgreiner 2009-12-13T00:00:00+00:00 https://24ways.org/2009/rock-solid-html-emails/ code
119 Rocking Restrictions I love my job. I live my job. For every project I do, I try to make it look special. I’ll be honest: I have a fetish for comments like “I never saw anything like that!” or, “I wish I thought of that!”. I know, I have an ego-problem. (Eleven I’s already) But sometimes, you run out of inspiration. Happens to everybody, and everybody hates it. “I’m the worst designer in the world.” “Everything I designed before this was just pure luck!” No it wasn’t. Countless articles about finding inspiration have already been written. Great, but they’re not the magic potion you’d expect them to be when you need it. Here’s a list of small tips that can have immediate effect when applying them/using them. Main theme: Liberate yourself from the designers’ block by restricting yourself. Do’s Grids If you aren’t already using grids, you’re doing something wrong. Not only are they a great help for aligning your design, they also restrict you to certain widths and heights. (For more information about grids, I suggest you read Mark Boulton’s series on designing grid systems. Oh, he’s also publishing a book I think.) So what’s the link between grids and restrictions? Instead of having the option to style a piece of layout with a width of 1 to 960 pixels, you have to choose from values like 60 pixels, 140, 220, 300, … Start small Having a hard time finding a style for the layout, why don’t you start with one small object? No, not that small object, I meant a piece of a form, or a link, or try styling your headers (h1 – h6). Let’s take a submit button of a form: it’s small, but needs much attention. People will click it. People will hover it. Maybe sometimes it’s disabled? Also: a button needs to look like a button, so typically it requires more styling then a regular link. Once you’ve got the button, move on, following the button’s style. Color palettes There are lots of resources on the web for finding inspiration for color palettes. Some of the most famous are COLOURlovers, wear palettes and Adobe’s Kuler. Browse through them (or create your own from a picture), pick a color palette you like and which works with the subject you’re handling, and stick with it. 4-5 colors, maybe with some tonal variations, but that’s it. Fonts There aren’t many fonts available for the web (Richard Rutter has a great article on this subject), but you’d be surprised how long they go. A simple text-transform: uppercase; or font-style: italic; can change a dull looking font into something entirely fresh. Play around with the fonts you want to use and the variations you’ll be using, and make a list. Pick five combinations of fonts and their variations, and stick with them throughout the layout. Single-task Most of us use multiple monitors. They’re great to increase productivity, but make it harder to focus on a single task. Here’s what you do: try using only your smallest monitor. Maybe it’s the one from your laptop, maybe it’s an old 1024×768 you found in the attic. Having Photoshop (or Fireworks or…) taking over your entire workspace blocks out all the other distractions on your screen, and works quite liberating. Mute everything… …but not entirely. I noticed I was way more focused when I set NetNewsWire to refresh it’s feeds only once every two hours. After two hours, I need a break anyway. Turning off Twitterrific was a mistake, as it’s my window to the world, and it’s the place where the people I like to call colleagues live. You can’t exactly ask them to bring you a cup of coffee when they go to the vending machine, but they do keep you fresh, and it stops you from going human-shy. Instead I changed the settings to not play a notification sound when new Tweets arrive so it doesn’t disturb me when I’m zoning. Don’ts CSS galleries Don’t start browsing all kinds of CSS galleries. Either you’ll feel bad, or you just start using elements in a way you can’t call “inspired” anymore. Instead gather your own collection of inspiration. Example: I use LittleSnapper in which I dump everything I find inspiring. This goes from a smart layout idea, to a failed picture someone posted on Flickr. Everything is inspiring. Panicking Don’t panic. It’s the worst thing you could do. Instead, get away from the computer, and go to bed early. A good night of sleep combined with a hot/cold shower can give you a totally new perspective on a design. Got a deadline by tomorrow? Well, you should’ve started earlier. Got a good excuse to start on this design this late? Tell your client it was either that or a bad design. 120-hour work-week Don’t work all day long, including evenings and early mornings. Write off that first hour, you don’t really think you’ll get anything productive done before 9AM?! I don’t even think you should work on one and the same design all day long. If you’re stuck, try working in blocks of 1 or 2 hours on a certain design. Mixing projects isn’t for everyone, but it might just do the trick for you. Summary Use grids, not only for layout purposes. Pick a specific element to start with. Use a colour palette. Limit the amount of fonts and variations you’ll use. Search for the smallest monitor around, and restrict yourself to that one. Reduce the amount of noise. Don’t start looking on the internet for inspiration. Build your own little inspirarchive. Work in blocks. 2008 Tim Van Damme timvandamme 2008-12-14T00:00:00+00:00 https://24ways.org/2008/rocking-restrictions/ process
138 Rounded Corner Boxes the CSS3 Way If you’ve been doing CSS for a while you’ll know that there are approximately 3,762 ways to create a rounded corner box. The simplest techniques rely on the addition of extra mark-up directly to your page, while the more complicated ones add the mark-up though DOM manipulation. While these techniques are all very interesting, they do seem somewhat of a kludge. The goal of CSS is to separate structure from presentation, yet here we are adding superfluous mark-up to our code in order to create a visual effect. The reason we are doing this is simple. CSS2.1 only allows a single background image per element. Thankfully this looks set to change with the addition of multiple background images into the CSS3 specification. With CSS3 you’ll be able to add not one, not four, but eight background images to a single element. This means you’ll be able to create all kinds of interesting effects without the need of those additional elements. While the CSS working group still seem to be arguing over the exact syntax, Dave Hyatt went ahead and implemented the currently suggested mechanism into Safari. The technique is fiendishly simple, and I think we’ll all be a lot better off once the W3C stop arguing over the details and allow browser vendors to get on and provide the tools we need to build better websites. To create a CSS3 rounded corner box, simply start with your box element and apply your 4 corner images, separated by commas. .box { background-image: url(top-left.gif), url(top-right.gif), url(bottom-left.gif), url(bottom-right.gif); } We don’t want these background images to repeat, which is the normal behaviour, so lets set all their background-repeat properties to no-repeat. .box { background-image: url(top-left.gif), url(top-right.gif), url(bottom-left.gif), url(bottom-right.gif); background-repeat: no-repeat, no-repeat, no-repeat, no-repeat; } Lastly, we need to define the positioning of each corner image. .box { background-image: url(top-left.gif), url(top-right.gif), url(bottom-left.gif), url(bottom-right.gif); background-repeat: no-repeat, no-repeat, no-repeat, no-repeat; background-position: top left, top right, bottom left, bottom right; } And there we have it, a simple rounded corner box with no additional mark-up. As well as using multiple background images, CSS3 also has the ability to create rounded corners without the need of any images at all. You can do this by setting the border-radius property to your desired value as seen in the next example. .box { border-radius: 1.6em; } This technique currently works in Firefox/Camino and creates a nice, if somewhat jagged rounded corner. If you want to create a box that works in both Mozilla and WebKit based browsers, why not combine both techniques and see what happens. 2006 Andy Budd andybudd 2006-12-04T00:00:00+00:00 https://24ways.org/2006/rounded-corner-boxes-the-css3-way/ code
6 Run Ragged You care about typography, right? Do you care about words and how they look, read, and are understood? If you pick up a book or magazine, you notice the moment something is out of place: an orphan, rivers within paragraphs of justified prose, or caps masquerading as small caps. So why, I ask you, is your stance any different on the web? We’re told time and time again that as a person who makes websites we have to get comfortable with our lack of control. On the web, this is a feature, not a bug. But that doesn’t mean we have to lower our standards, or not strive for the same amount of typographic craft of our print-based cousins. We shouldn’t leave good typesetting at the door because we can’t control the line length. When I typeset books, I’d spend hours manipulating the text to create a pleasurable flow from line to line. A key aspect of this is manicuring the right rag — the vertical line of words on ranged-left text. Maximising the space available, but ensuring there are no line breaks or orphaned words that disrupt the flow of reading. Setting a right rag relies on a bunch of guidelines — or as I was first taught to call them, violations! Violation 1. Never break a line immediately following a preposition Prepositions are important, frequently used words in English. They link nouns, pronouns and other words together in a sentence. And links should not be broken if you can help it. Ending a line on a preposition breaks the join from one word to another and forces the reader to work harder joining two words over two lines. For example: The container is for the butter The preposition here is for and shows the relationship between the butter and the container. If this were typeset on a line and the line break was after the word for, then the reader would have to carry that through to the next line. The sentence would not flow. There are lots of prepositions in English – about 150 – but only 70 or so in use. Violation 2. Never break a line immediately following a dash A dash — either an em-dash or en-dash — can be used as a pause in the reading, or as used here, a point at which you introduce something that is not within the flow of the sentence. Like an aside. Ending with a pause on the end of the line would have the same effect as ending on a preposition. It disrupts the flow of reading. Violation 3. No small words at the end of a line Don’t end a line with small words. Most of these will actually be covered by violation №1. But there will be exceptions. My general rule of thumb here is not to leave words of two or three letters at the end of a line. Violation 4. Hyphenation In print, hyphens are used at the end of lines to join words broken over a line break. Mostly, this is used in justified body text, and no doubt you will be used to seeing it in newspapers or novels. A good rule of thumb is to not allow more than two consecutive lines to end with a hyphen. On the web, of course, we can use the CSS hyphens property. It’s reasonably supported with the exception of Chrome. Of course, it works best when combined with justified text to retain the neat right margin. Violation 5. Don’t break emphasised phrases of three or fewer words If you have a few words emphasised, for example: He calls this problem definition escalation …then try not to break the line among them. It’s important the reader reads through all the words as a group. How do we do all of that on the web? All of those guidelines are relatively easy to implement in print. But what about the web? Where content is poured into a template from a CMS? Well, there are things we can do. Meet your new friend, the non-breaking space, or as you may know them:  . The guidelines above are all based on one decision for the typesetter: when should the line break? We can simply run through a body of text and add the   based on these sets of questions: Are there any prepositions in the text? If so, add a   after them. Are there any dashes? If so, add a   after them. Are there any words of fewer than three characters that you haven’t already added spaces to? If so, add a   after them. Are there any emphasised groups of words either two or three words long? If so, add a   in between them. For a short piece of text, this isn’t a big problem. But for longer bodies of text, this is a bit arduous. Also, as I said, lots of websites use a CMS and just dump the text into a template. What then? We can’t expect our content creators to manually manicure a right rag based on these guidelines. In this instance, we really need things to be automatic. There isn’t any reason why we can’t just pass the question of when to break the line straight to the browser by way of a script which compares the text against a set of rules. In plain English, this script could be to scan the text for: Prepositions. If found, add   after them. Dashes. If found, add   after them. Words fewer than three characters long that aren’t prepositions. If found, add   after them. Emphasised phrases of up to three words in length. If found, add   between all of the words. And there we have it. A note on fluidity An important consideration of this script is that it doesn’t scan the text to see what is at the end of a line. It just looks for prepositions, dashes, words fewer than three characters long, and emphasised words within paragraphs and applies the   accordingly regardless of where the thing lives. This is because in a fluid layout a word might appear in the beginning, middle or the end of a line depending on the width of the browser. And we want it to behave in the right way when it does find itself at the end. See it in action! My friend and colleague, Nathan Ford, has written a small JavaScript called Ragadjust that does all of this automatically. The script loops through a webpage, compares the text against the conditions, and then inserts   in the places that violate the conditions above. You can get the script from GitHub and see it in action on my own website. Some caveats As my friend Jon Tan says, “There are no rules in typography, just good or bad decisions”, and typesetting the right rag is no different. The guidelines for the violations above are useful for justified text, too. But we need to be careful here. Too stringent adherence to these violations could lead to ugly gaps in our words — called rivers — as the browser forces justification. The violation regarding short words at the end of sentences is useful for longer line lengths, or measures, of text. When the measure gets shorter, maybe five or six words, then we need to be more forgiving as to what wraps to the next line and what doesn’t. In fact, you can see this happening on my site where I’ve not included a check on the size of the browser window (purposefully, for this demo, of course. Ahem). This article is about applying these guidelines to English. Some of them will, no doubt, cross over to other languages quite well. But for those languages, like German for instance, where longer words tend to be in more frequent use, then some of the rules may result in a poor right rag. Marginal gains In 2007, I spoke with Richard Rutter at SXSW on web typography. In that talk, Richard and I made a point that good typographic design — on the web, in print; anywhere, in fact — relies on small, measurable improvements across an entire body of work. From heading hierarchy to your grid system, every little bit helps. In and of themselves, these little things don’t really mean that much. You may well have read this article, shrugged your shoulders and thought, “Huh. So what?” But these little things, when added up, make a difference. A difference between good typographic design and great typographic design. Appendix Preposition whitelist aboard about above across after against along amid among anti around as at before behind below beneath beside besides between beyond but by concerning considering despite down during except excepting excluding following for from in inside into like minus near of off on onto opposite outside over past per plus regarding round save since than through to toward towards under underneath unlike until up upon versus via with within without 2013 Mark Boulton markboulton 2013-12-24T00:00:00+00:00 https://24ways.org/2013/run-ragged/ design
35 SEO in 2015 (and Why You Should Care) If your business is healthy, you can always find plenty of reasons to leave SEO on your to-do list in perpetuity. After all, SEO is technical, complicated, time-consuming and potentially dangerous. The SEO industry is full of self-proclaimed gurus whose lack of knowledge can be deadly. There’s the terrifying fact that even if you dabble in SEO in the most gentle and innocent way, you might actually end up in a worse state than you were to begin with. To make matters worse, Google keeps changing the rules. There have been a bewildering number of major updates, which despite their cuddly names have had a horrific impact on website owners worldwide. Fear aside, there’s also the issue of time. It’s probably tricky enough to find the time to read this article. Setting up, planning and executing an SEO campaign might well seem like an insurmountable obstacle. So why should you care enough about SEO to do it anyway? The main reason is that you probably already see between 30% and 60% of your website traffic come from the search engines. That might make you think that you don’t need to bother, because you’re already doing so well. But you’re almost certainly wrong. If you have a look through the keyword data in your Google Webmaster Tools account, you’ll probably see that around 30–50% of the keywords used to find your website are brand names – the names of your products or companies. These are searches carried out by people who already know about you. But the people who don’t know who you are but are searching for what you sell aren’t finding you right now. This is your opportunity. If a person goes looking for a company or product by name, Google will steer them towards what they’re looking for. Their intelligence does have limits, however, and even though they know your name they won’t be completely clear about what you sell. That’s where SEO would come in. Still need more convincing? How about the fact that the seeming complexities of SEO mean that your competition are almost certainly neglecting it too. They have the same reservations as you about complexity, time and danger, and hopefully they aren’t reading this article and so are none the wiser of the well-kept secret: that 70% of SEO is easy. I’m going to lead you through what you need to do to tap into that stream of people looking for what you sell right now. What is real SEO? Real SEO is all about helping Google understand the content of your website. It’s about steering, guiding and assisting Google. Not manipulating it. It’s easy to assume that Google already understands the content and relevance of each and every page on your website, but the fact is that it needs a fair amount of hand-holding. Fortunately, helping Google along really isn’t very difficult at all. Rest assured that real SEO has nothing to do with keyword stuffing, keyword density, hacks, tricks or cunning techniques. If you hear any of these terms from your SEO advisor, run away from them as quickly as you can. Understanding your current situation – Google Analytics Before you can do anything to improve your SEO status, you need to get an idea of how you’re already doing. Below is a very quick and easy way of doing so. 1. Open up your Google Analytics account. 2. Click on the date range selector on the top-right of the interface and change the year of the first date to last year. So 12 Dec 2014 will become 12 Dec 2013. Then click on Apply. 3. Click on the All Sessions rectangle towards the top-left, click once on Organic Traffic and click Apply. 4. Click the little black-and-white squares icon that has now appeared under the date selector on the top-right, and drag the slider all the way over to Higher Precision. 5. Change the interval buttons on the top-right of the graph to Week to make this easier to digest. At this point your graph should look something like this: It’s worth noting the approximate proportion of your visitors that currently come from organic sources. 6. Click the little downwards arrow to the right of the All Sessions rectangle and choose Remove, so that we’re only looking at the organic traffic on its own. 7. Click on Select a metric next to the Sessions button above the graph and select Pages / Session. You should then see something like this: In the example above we can see that the quantity of traffic has been increasing since the middle of August, but the quality of the traffic (as measured by the number of pages per session) has fallen significantly. How you choose to view this is down to your own graph, recent history and interpretation of events, but this should give you an indication of how things stand at the present time. Trends are often much more revealing than a snapshot of a brief moment in time. Your Google Webmaster Tools data If you’re not very familiar with your Google Webmaster Tools account, it’s really worth taking ten to fifteen minutes to see what’s on offer. I can’t recommend this enough. From the point of view of an SEO health check, I’d advise you to look into the HTML Improvements, Crawl Errors and Crawl Stats, and most importantly the Search Queries. From what you see here and the trends shown in your Analytics data, you should now have a good idea of your current status. If you want to explore further, I recommend Screaming Frog as a good diagnostics tool, or Botify if your website is large or unusually complex. Combining the data into something useful Your Google Analytics session will have shown you how you’re doing from an SEO point of view in terms of the quantity and, to some extent, the quality of your visitors. But it’s only showing you what is already working. In other words: the people who are finding you on the search engines, and clicking on your links. The Google Webmaster Tools search query data, on the other hand, will give you a better idea of what isn’t working. It will show you the keyword searches that are getting you listed in the results, but which aren’t necessarily getting clicked. And it doesn’t take much by the way of expertise to see why. For example, if you see your targeted keyword, which you feel is extremely relevant, has generated over 2,000 impressions in the last month but produced only two clicks, you’ll probably find a very low average position. Bear in mind that an average position of fourteen will mean being around halfway down the second page of results. Think about how rarely you go beyond the first two or three listings, never mind to the second page of results, and you’ll understand why the click-through rate is so low. So now you have an idea of what you’re being found for at the present time. But what about the other terms? What would you like to be found for? This is one of the more common SEO mistakes, on a number of different levels. Many businesses assume that they don’t need to worry about keyword research. They think they know what terms people use to find what they sell, and they also assume that Google understands the content on their website. This is incorrect on all counts. A better starting point is to brainstorm a small number of your most obvious keywords, then run them through Google’s Keyword Planner. Ignore the information in the Ad group ideas tab, and instead go straight to the Keyword ideas tab. Rather than wade through the very unfriendly interface, I recommend downloading the data as a spreadsheet, in which not only is more detail included, but you can also slice, dice, sort and report the data as required. From there you can delete all the irrelevant columns, and start working your way through the list, deleting any irrelevant keywords as you go along. It’s around this stage that you may hit a problem in terms of where to focus your efforts. The number of reported searches for a given keyword is of course important, but so is the level of competition. Ideally, you’d like keywords with plenty of searches but not too much competition. I personally like to factor both together by adding a column that simply divides the number of searches squared by the level of competition: (number of searches × number of searches) ÷ competition There are plenty of alternatives to this basic formula, but I like it for ease of use and simplicity. Once I’ve added this column, I then sort the data by this value (largest to smallest) and I then only usually need ten to fifteen keywords at most to give me plenty of ideas to work with. This is a slightly involved but effective methodology for keyword research, as what you’re left with is a list of keywords that both Google and you consider to be relevant to the content of your website. And relevance is an important concept in SEO. Real SEO keyword research is about making sure that your customers, website and Google are all in agreement and alignment over the content of your website. Other sources of inspiration and ideas include having a look at what terms your competition are targeting, Google Trends and, of course, Google Suggest. If you’re not sure where to find these things, you can probably work out where to search for them! If you want to dive further into understanding your current search engine status, search for some of the better keywords that you just discovered and see where you rank compared to your competition. Note that it’s vital to avoid Google serving up personalised results, so either use the privacy, incognito or anonymous mode of your browser for the searches, or use a browser that you don’t normally use. I hope this is Internet Explorer. If what you find isn’t great, don’t despair: everything in SEO is fixable (terms and conditions may apply). Putting it all together You should now have a good idea of where things stand with your current search engine traffic, and a solid list of keywords that you’re not getting visitors for but very much want. All that’s left now is to work out how to use these keywords. But before we do, let’s take a quick step back. If you have in any way kept up with what’s been happening in SEO over the last couple of years, you’ll have probably heard about Google updates with names like Panda, Hummingbird, Phantom, Pirate and more. I won’t go into the technical details of what Google is doing, but it is important to understand why they’re trying to do it. At the most basic level, Google understands that there’s a very real problem with people who are trying manipulate its index. In response to this, Google is trying to clean up its results. They don’t want people getting fed up with bad results and considering other options – have you even tried Bing? This is extremely important. Remember earlier when I said that 70% of SEO was easy? That rule still applies. So, for example, if you have a list of keywords that you know are relevant to what you sell, then all you need to do is create great content for them. Incredibly, that’s all there is to it (terms and conditions apply again, unfortunately – see below). There is, however, one simple rule to be consistently followed without exception: that the content you create should not only be good quality and completely original, but it should also be written primarily for the human visitor and not the search engine spider. In other words, if you create some fantastic content for a keyword like “choosing a small business HR service”, then the article should not only make perfect sense if read out loud (as opposed to the same phrase being repeated fifteen times), but also provide real value to the person reading it. So the process is simple: Choose your keywords Create spectacular content Wait. Is it really that simple? Unfortunately there’s a lot more to the other 30% of SEO than just creating great content and waiting for the visitors. There are issues like helping Google understand the content on your pages and website, incoming links, page authority, domain authority, usage patterns, spam factors, canonical issues and much more. But there’s the often overlooked fact about Google: it actually does a reasonable job of working out what’s on your website and (to some extent) understanding the gist of it. If you’ve never done any SEO on your website but still get some traffic from Google, this is why. Even without dabbling in the other 30% of SEO, by creating the right content for the right visitors using the precise language and terminology that your potential customers are using, you’re significantly better off than your competition. And you can only gain from this. When you’ve checked this off your to-do list and made it an ingrained part of your content creation process, then you’re ready to delve into the other 30% of SEO. The not-so-easy side. Until then, work on understanding your current situation, exploring the opportunities, creating a list of good keywords, creating the right content for them, and starting 2015 with a little bit of smart, safe and real SEO. 2014 Dave Collins davecollins 2014-12-15T00:00:00+00:00 https://24ways.org/2014/seo-in-2015-and-why-you-should-care/ business
81 Science! Sometimes we want to capture people’s attention at a glance to communicate something fast. At other times we want to have the interface fade away into the background, letting people paint pictures in their minds with our words (if you’ll forgive a little flowery festive flourish). I tend to distinguish between these two broad objectives as designing for impact on the one hand, and designing for immersion on the other. What defines them is interruption. Impact needs an attention-grabbing interruption. Immersion requires us to remove interruption from the interface. Careful design deliberately interrupts but doesn’t accidentally disrupt. If that seems to make sense to you, then you’ll find the following snippets of science as useful as I did. Saccades and fixations As you’re reading this your eyes are skipping along the lines in tiny jumps. During each jump everything is blurred. Each jump ends in a small pause so your brain can take a snapshot of the letters. It arranges them into words, and then parses out the meaning — fast — in around a quarter of a second. The jumps are called saccades. The pauses are called fixations. Sometimes we take regressive saccades, skipping back to reread. There’s a simple example in the excellent little book, Detail in Typography, by Jost Hochuli. If you want to explore the science of reading in much more depth, I recommend the excellent paper, “The Science of Word Recognition”, by Dr Kevin Larson of Microsoft. To design for legibility and readability is to design for saccades and fixations. It’s the craft of making it easy for people’s brains to extract meaning, using techniques like good contrast, font size, spacing and structure, and only interrupting the reading experience deliberately. Scan paths At some point when visiting 24 ways you probably scanned the screen to get orientated. The journey your eyes took is known as a scan path. Scan paths are made up of saccades and fixations. Right now you’re following a scan path as you read, along one line, and down to the next. This is a map of the scan paths found by Olivier Le Meur from observing people looking at Rembrandt’s Leçon d’anatomie: For websites, the scan path is a little different. This is an aggregate scan path of Google from LC Technologies: The average shape of a website scan path becomes clearer in this average scan path taken by forty-six people during research by the Poynter Institute, the Estlow Center for Journalism & New Media, and Eyetools: Just like when we read text arranged left to right in a vertical column, scan paths follow a roughly Z-shaped pattern from the top left to bottom right. Sometimes we skip back to reread a word or sentence, or glance again at a specific element, but the Z-shaped scan path persists. Designing for scan paths is to organise content to help people move through an interface to get orientated, and to read. The elements that are important enough to need impact must interrupt the scan path and clearly call attention to themselves. However, they don’t always need to clip people round the ear from multiple directions at once to get attention. It helps to list elements by importance. That gives us an interruption hierarchy to work with. Elements can then interrupt the design with degrees of contrast to the rest of the content using either positioning, treatment, or both. Ta-da! Impact achieved, but gently. No clips round the ear required. Swinging mood Human beings are resilient. Among the immersion and occasional interruptions, we even like a little disruption, especially if it’s absurd and funny. The Ling’s Cars website proves it. In fact, we’re so resilient that we can work around all kinds of mayhem to get a seemingly simple task done. In one study, “The Aesthetics of Reading” (PDF, 480Kb), Dr Kevin Larson of Microsoft and Dr Rosalind Picard of MIT explored the effect of good typography on mood. Two versions of the New Yorker ePeriodical were created. One was typeset well and the other poorly. They engaged twenty volunteers — half male, half female — and showed the good version to half of the participants. The other half saw the poor version. The good doctors found that, “there are important differences between good and poor typography that appear to have little effect on common performance measures such as reading speed and comprehension.” In short, good typography didn’t help people read faster or comprehend better. Oh. On the face of it that seems to invalidate what we designers do. Hold your horses, though! They also found that “the participants who received the good typography performed better on relative subjective duration and on certain cognitive tasks”, and that “good typography induces a good mood.” This means that even though there were no actual differences in reading speed and comprehension, the people who read the version with good typography thought that it took less time to read, and were induced into a good mood by doing so. Not only that, but by being in a good mood, people were more capable of completing creative tasks faster. That was a revelation to me. It means that the study showed there is a positive, measurable, emotional and perceptual benefit to good typography and design. To paraphrase: time and tasks fly when you’re having fun! Source: Nationaal Archief of the Netherlands: Cheering man after the first goal, Netherlands vs. Belgium, Amsterdam, 1931. So, among all my talk of saccades, fixations, scan paths and typesetting, there is science, and the science helps us qualify our design decisions when we need to, and do our jobs better. The science helps us understand how people will interact with our work, and what the actual benefits are for them, and the products or organisations we serve. Good design equals a subjectively quicker experience, a good mood, objectively faster completion of tasks, and happiness for everyone. Thank you, science! 2012 Jon Tan jontan 2012-12-24T00:00:00+00:00 https://24ways.org/2012/science/ design
263 Securing Your Site like It’s 1999 Running a website in the early years of the web was a scary business. The web was an evolving medium, and people were finding new uses for it almost every day. From book stores to online auctions, the web was an expanding universe of new possibilities. As the web evolved, so too did the knowledge of its inherent security vulnerabilities. Clever tricks that were played on one site could be copied on literally hundreds of other sites. It was a normal sight to log in to a website to find nothing working because someone had breached its defences and deleted its database. Lessons in web security in those days were hard-earned. What follows are examples of critical mistakes that brought down several early websites, and how you can help protect yourself and your team from the same fate. Bad input validation: Trusting anything the user sends you Our story begins in the most unlikely place: Animal Crossing. Animal Crossing was a 2001 video game set in a quaint town, filled with happy-go-lucky inhabitants that co-exist peacefully. Like most video games, Animal Crossing was the subject of many fan communities on the early web. One such unofficial web forum was dedicated to players discussing their adventures in Animal Crossing. Players could trade secrets, ask for help, and share pictures of their virtual homes. This might sound like a model community to you, but you would be wrong. One day, a player discovered a hidden field in the forum’s user profile form. Normally, this page allows users to change their name, their password, or their profile photo. This person discovered that the hidden field contained their unique user ID, which identifies them when the forum’s backend saves profile changes to its database. They discovered that by modifying the form to change the user ID, they could make changes to any other player’s profile. Needless to say, this idyllic online community descended into chaos. Users changed each other’s passwords, deleted each other’s messages, and attacked each-other under the cover of complete anonymity. What happened? There aren’t any official rules for developing software on the web. But if there were, my golden rule would be: Never trust user input. Ever. Always ask yourself how users will send you data that isn’t what it seems to be. If the nicest community of gamers playing the happiest game on earth can turn on each other, nowhere on the web is safe. Make sure you validate user input to make sure it’s of the correct type (e.g. string, number, JSON string) and that it’s the length that you were expecting. Don’t forget that user input doesn’t become safe once it is stored in your database; any data that originates from outside your network can still be dangerous and must be escaped before it is inserted into HTML. Make sure to check a user’s actions against what they are allowed to do. Create a clear access control policy that defines what actions a user may take, and to whose data they are allowed access to. For example, a newly-registered user should not be allowed to change the user profile of a web forum’s owner. Finally, never rely on client-side validation. Validating user input in the browser is a convenience to the user, not a security measure. Always assume the user has full control over any data sent from the browser and make sure you validate any data sent to your backend from the outside world. SQL injection: Allowing the user to run their own database queries A long time ago, my favourite website was a web forum dedicated to the Final Fantasy video game series. Like the users of the Animal Crossing forum, I’d while away many hours arguing with other people on the internet about my favourite characters, my favourite stories, and the greatest controversies of the day. One day, I noticed people were acting strangely. Users were being uncharacteristically nasty and posting in private areas of the forum they wouldn’t normally have access to. Then messages started disappearing, and user accounts for well-respected people were banned. It turns out someone had discovered a way of logging in to any other user account, using a secret password that allowed them to do literally anything they wanted. What was this password that granted untold power to those who wielded it? ' OR '1'='1 SQL is a computer language that is used to query databases. When you fill out a login form, just like the one above, your username and your password are usually inserted into an SQL query like this: SELECT COUNT(*) FROM USERS WHERE USERNAME='Alice' AND PASSWORD='hunter2' This query selects users from the database that match the username Alice and the password hunter2. If there is at least one user matching record, the user will be granted access. Let’s see what happens when we use our magic password instead! SELECT COUNT(*) FROM USERS WHERE USERNAME='Admin' AND PASSWORD='' OR '1'='1' Does the password look like part of the query to you? That’s because it is! This password is a deliberate attempt to inject our own SQL into the query, hence the term SQL injection. The query is now looking for users matching the username Admin, with a password that is blank, or 1=1. In an SQL query, 1=1 is always true, which makes this query select every single record in the database. As long as the forum software is checking for at least one matching user, it will grant the person logging in access. This password will work for any user registered on the forum! So how can you protect yourself from SQL injection? Never build SQL queries by concatenating strings. Instead, use parameterised query tools. PHP offers prepared statements, and Node.JS has the knex package. Alternatively, you can use an ORM tool, such as Propel or sequelize. Expert help in the form of language features or software tools is a key ally for securing your code. Get all the help you can! Cross site request forgery: Getting other users to do your dirty work for you Do you remember Netflix? Not the Netflix we have now, the Netflix that used to rent you DVDs by mailing them to you. My next story is about how someone managed to convince Netflix users to send him their DVDs - free of charge. Have you ever clicked on a hyperlink, only to find something that you weren’t expecting? If you were lucky, you might have just gotten Rickrolled. If you were unlucky… Let’s just say there are older and fouler things than Rick Astley in the dark places of the web. What if you could convince people to visit a page you controlled? And what if those people were Netflix users, and they were logged in? In 2006, Dave Ferguson did just that. He created a harmless-looking page with an image on it: <img src="http://www.netflix.com/JSON/AddToQueue?movieid=70110672" /> Did you notice the source URL of the image? It’s deliberately crafted to add a particular DVD to your queue. Sprinkle in a few more requests to change the user’s name and shipping address, and you could ship yourself DVDs completely free of charge! This attack is possible when websites unconditionally trust a user’s session cookies without checking where HTTP requests come from. The first check you can make is to verify that a request’s origin and referer headers match the location of the website. These headers can’t be programmatically set. Another check you can use is to add CSRF tokens to your web forms, to verify requests have come from an actual form on your website. Tokens are long, unpredictable, unique strings that are generated by your server and inserted into web forms. When users complete a form, the form data sent to the server can be checked for a recently generated token. This is an effective deterrent of CSRF attacks because CSRF tokens aren’t stored in cookies. You can also set SameSite=Strict when setting cookies with the Set-Cookie HTTP header. This communicates to browsers that cookies are not to be sent with cross-site requests. This is a relatively new feature, though it is well supported in evergreen browsers. Cross site scripting: Someone else’s code running on your website In 2005, Samy Kamkar became famous for having lots of friends. Lots and lots of friends. Samy enjoyed using MySpace which, at the time, was the world’s largest social network. Social networks at that time were more limited than today. For instance, MySpace let you upload photos to your photo gallery, but capped the limit at twelve. Twelve photos. At least you didn’t have to wade through photos of avocado toast back then… Samy discovered that MySpace also locked down the kinds of content that you could post on your MySpace page. He discovered he could inject <img /> and <div /> tags into his headline, but <script /> was filtered. MySpace wasn’t about to let someone else run their own code on MySpace. Intrigued, Samy set about finding out exactly what he could do with <img /> and <div /> tags. He found that you could add style properties to <div /> tags to style them with CSS. <div style="background:url('javascript:alert(1)')"> This 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 <div />. <div style="background:url('java script:alert(1)')"> Samy 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’s 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. alert(document.body.innerHTML) Samy wondered if he could inspect the page’s 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. alert(eval('document.body.inne' + 'rHTML')) This isn’t 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’ pages. One 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. if (location.hostname == 'profile.myspace.com') { document.location = 'http://www.myspace.com' + location.pathname + location.search } Samy 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’s 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’s API. Samy installed this code on his profile page, and he waited. Over the course of the next day, over a million people unwittingly installed Samy’s 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’s 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. This is the power of installing a little bit of JavaScript on someone else’s 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. So how can you help protect yourself from cross-site scripting? Always 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’t 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. You can also use an auto-escaping templating language to make sure nobody else’s HTML can get into your pages. Both Angular and React will do this for you, and they are extremely convenient to use. You 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. For 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. npm audit: Protecting yourself from code you don’t own JavaScript and npm run the modern web. Together, they make it easy to take advantage of the world’s largest public registry of open source software. How do you protect yourself from code written by someone you’ve never met? Enter npm audit. npm audit reviews the security of your website’s dependency tree. You can start using it by upgrading to the latest version of npm: npm install npm -g npm audit When 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. If your website has a known cross-site scripting vulnerability, npm audit will tell you about it. What’s more, if the vulnerability has been patched, running npm audit fix will automatically install the patched package for you! Securing your site like it’s 2019 The 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. However, 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. As we roll over into 2019, let’s take the opportunity to reflect on the security of the code we write and be grateful for the everything we’ve learned in the last twenty years. 2018 Katie Fenn katiefenn 2018-12-01T00:00:00+00:00 https://24ways.org/2018/securing-your-site-like-its-1999/ code
190 Self-Testing Pages with JavaScript Working at an agency I am involved more and more on projects in which client side code is developed internally then sent out to a separate team for implementation. You provide static HTML, CSS and JavaScript which then get placed into the CMS and brought to life as an actual website. As you can imagine this can sometimes lead to frustrations. However many safeguards you include, handing over your code to someone else is always a difficult thing to do effectively. In this article I will show you how you can create a JavaScript implementation checker and that will give you more time for drink based activity as your web site and apps are launched quicker and with less unwanted drama! An all too frequent occurrence You’ve been working on a project for weeks, fixed all your bugs and send it to be implemented. You hear nothing and assume all is going well then a few days before it’s meant to launch you get an email from the implementation team informing you of bugs in your code that you need to urgently fix. The 24ways website with a misspelt ID for the years menu Being paranoid you trawl through the preview URL, check they have the latest files, check your code for errors then notice that a required HTML attribute has been omitted from the build and therefore CSS or JavaScript you’ve hooked onto that particular attribute isn’t being applied and that’s what is causing the “bug”. It takes you seconds drafting an email informing them of this, it takes then seconds putting the required attribute in and low and behold the bug is fixed, everyone is happy but you’ve lost a good few hours of your life – this time could have been better spent in the pub. I’m going to show you a way that these kind of errors can be alerted immediately during implementation of your code and ensure that when you are contacted you know that there actually is a bug to fix. You probably already know the things that could be omitted from a build and look like bugs so you’ll soon be creating tests to look for these and alert when they are not found on the rendered page. The error is reported directly to those who need to know about it and fix it. Less errant bug reports and less frantic emails ahoy! A page with an implementation issue and instant feedback on the problem JavaScript selector engines to the rescue Whether you’re using a library or indeed tapping into the loveliness of the new JavaScript Selector APIs looking for particular HTML elements in JavaScript is fairly trivial now. For instance this is how you look for a div element with the id attribute of year (the missing attribute from top image) using jQuery (the library I’ll be coding my examples in): if ($(‘div#year’).length) { alert(‘win’); } Using this logic you can probably imagine how you can write up a quick method to check for the existence of a particular element and alert when it’s not present — but assuming you have a complex page you’re going to be repeating yourself a fair bit and we don’t want to be doing that. Test scripts If you’ve got a lot of complex HTML patterns that need testing across a number of different pages it makes sense to keep your tests out of production code. Chances are you’ve already got a load of heavy JavaScript assets, and when it comes to file size saving every little helps. I don’t think that tests should contain code inside of them so keep mine externally as JSON. This also means that you can use the one set of tests in multiple places. We already know that it’s a good idea to keep our CSS and JavaScript separate so lets continue along those lines here. The test script for this example looks like this: { "title": "JS tabs implementation test", "description": "Check that the correct HTML patterns has been used", "author": "Ross Bruniges", "created": "20th July 2009", "tests": [ { "name": "JS tabs elements", "description": "Checking that correct HTML elements including class/IDs are used on the page for the JS to progressively enhance", "selector": "div.tabbed_content", "message": "We couldn't find VAR on the page - it's required for our JavaScript to function correctly", "check_for": { "contains": { "elements": [ "div.tab_content", "h2" ], "message": "We've noticed some missing HTML:</p><ul><li>VAR</li></ul><p>please refer to the examples sent for reference" } } } ] } The first four lines are just a little bit of meta data so we remember what this test was all about when we look at it again in the future, or indeed if it ever breaks. The tests are the really cool parts and firstly you’ll notice that it’s an array – we’re only going to show one example test here but there is no reason why you can’t place in as many as you want. I’ll explain what each of the lines in the example test means: name – short test name, I use this in pass/fail messaging later description – meta data for future reference selector – the root HTML element from which your HTML will be searched message – what the app will alert if the initial selector isn’t found check_for – a wrapper to hold inner tests – those run if the initial selector does match contains – the type of check, we’re checking that the selector contains specified elements elements – the HTML elements we are searching for message – a message for when these don’t match (VAR is substituted when it’s appended to the page with the name of any elements that don’t exist) It’s very important to pass the function valid JSON (JSONLint is a great tool for this) otherwise you might get a console showing no tests have even been run. The JavaScript that makes this helpful Again, this code should never hit a production server so I’ve kept it external. This also means that the only thing that’s needed to be done by the implementation team when they are ready to build is that they delete this code. <script src="sleuth.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function() { sleuth.test_page.init(‘js_tabs_test.js'); }); </script> “View the full JavaScript:/examples/self-testing-pages-with-javascript/js/tests/test_suite.js The init function appends the test console to the page and inserts the CSS file required to style it (you don’t need to use pictures of me when tests pass and fail though I see no reason why you shouldn’t), goes and grabs the JSON file referenced and parses it. The methods to pass (tests_pass) and fail (haz_fail) the test I hope are pretty self-explanatory as is the one which creates the test summary once everything has been run (create_summary). The two interesting functions are init_tests and confirm_html. init_tests init_tests:function(i,obj) { var $master_elm = $(obj.selector); sleuth.test_page.$logger.append("<div id='test_" + i + "' class='message'><p><em>" + obj.name + "</em></p></div>"); var $container = $('#test_' + i); if (!$master_elm.length) { var err_sum = obj.message.replace(/VAR/gi, obj.selector); sleuth.test_page.haz_failed(err_sum, $container); return; } if (obj.check_for) { $.each(obj.check_for,function(key, value){ sleuth.test_page.assign_checks($master_elm, $container, key, value); }); } else { sleuth.test_page.tests_passed($container); return; } } The function gets sent the number of the current iteration (used to create a unique id for its test summary) and the current object that contains the data we’re testing against as parameters. We grab a reference to the root element and this is used (pretty much in the example shown right at the start of this article) and its length is checked. If the length is positive we know we can continue to the inner tests (if they exist) but if not we fail the test and don’t go any further. We append the error to the test console for everyone to see. If we pass the initial check we send the reference to the root element, message contains and the inner object to a function that in this example sends us on to confirm_html (if we had a more complex test suite it would do a lot more). confirm_html confirm_html:function(target_selector, error_elm, obj) { var missing_elms = []; $.each(obj.elements, function(i, val) { if (!target_selector.find(val).length) { missing_elms.push(val); } }); if (missing_elms.length) { var file_list = missing_elms.join('</li><li>'); var err_sum = obj.message.replace(/VAR/gi, file_list); sleuth.test_page.haz_failed(err_sum, error_elm); return; } sleuth.test_page.tests_passed(error_elm); return; } We’re again using an array to check for a passed or failed test and checking its length but this time we push in a reference to each missing element we find. If the test does fail we’re providing even more useful feedback by informing what elements have been missed out. All the implementation team need do is look for them in the files we’ve sent and include them as expected. No more silly implementation bugs! Here is an example of a successful implementation. Here are some examples of failed implementations – one which fails at finding the root node and one that has the correct root node but none of the inner HTML tests pass. Is this all we can check for? Certainly not! JavaScript provides pretty easy ways to check for attributes, included files (if the files being checked for are being referenced correctly and not 404ing) and even applied CSS. Want to check that those ARIA attributes are being implemented correctly or that all images contain an alt attribute well this simple test suite can be extended to include tests for this – the sky is pretty much up to your imagination. 2009 Ross Bruniges rossbruniges 2009-12-12T00:00:00+00:00 https://24ways.org/2009/self-testing-pages-with-javascript/ process
110 Shiny Happy Buttons Since Mac OS X burst onto our screens, glossy, glassy, shiny buttons have been almost de rigeur, and have essentially, along with reflections and rounded corners, become a cliché of Web 2.0 “design”. But if you can’t beat ‘em you’d better join ‘em. So, in this little contribution to our advent calendar, we’re going to take a plain old boring HTML button, and 2.0 it up the wazoo. But, here’s the catch. We’ll use no images, either in our HTML or our CSS. No sliding doors, no image replacement techniques. Just straight up, CSS, CSS3 and a bit of experimental CSS. And, it will be compatible with pretty much any browser (though with some progressive enhancement for those who keep up with the latest browsers). The HTML We’ll start with our HTML. <button type="submit">This is a shiny button</button> OK, so it’s not shiny yet – but boy will it ever be. Before styling, that’s going to look like this. Ironically, depending on the operating system and browser you are using, it may well be a shiny button already, but that’s not the point. We want to make it shiny 2.0. Our mission is to make it look something like this If you want to follow along at home keep in mind that depending on which browser you are using you may see fewer of the CSS effects we’ve added to create the button. As of writing, only in Safari are all the effects we’ll apply supported. Taking a look at our finished product, here’s what we’ve done to it: We’ve given the button some padding and a width. We’ve changed the text color, and given the text a drop shadow. We’ve given the button a border. We’ve given the button some rounded corners. We’ve given the button a drop shadow. We’ve given the button a gradient background. and remember, all without using any images. Styling the button So, let’s get to work. First, we’ll add given the element some padding and a width: button { padding: .5em; width: 15em; } Next, we’ll add the text color, and the drop shadow: color: #ffffff; text-shadow: 1px 1px 1px #000; A note on text-shadow If you’ve not seen text-shadows before well, here’s the quick back-story. Text shadow was introduced in CSS2, but only supported in Safari (version 1!) some years later. It was removed from CSS2.1, but returned in CSS3 (in the text module). It’s now supported in Safari, Opera and Firefox (3.1). Internet Explorer has a shadow filter, but the syntax is completely different. So, how do text-shadows work? The three length values specify respectively a horizontal offset, a vertical offset and a blur (the greater the number the more blurred the shadow will be), and finally a color value for the shadow. Rounding the corners Now we’ll add a border, and round the corners of the element: border: solid thin #882d13; -webkit-border-radius: .7em; -moz-border-radius: .7em; border-radius: .7em; Here, we’ve used the same property in three slightly different forms. We add the browser specific prefix for Webkit and Mozilla browsers, because right now, both of these browsers only support border radius as an experimental property. We also add the standard property name, for browsers that do support the property fully in the future. The benefit of the browser specific prefix is that if a browser only partly supports a given property, we can easily avoid using the property with that browser simply by not adding the browser specific prefix. At present, as you might guess, border-radius is supported in Safari and Firefox, but in each the relevant prefix is required. border-radius takes a length value, such as pixels. (It can also take two length values, but that’s for another Christmas.) In this case, as with padding, I’ve used ems, which means that as the user scales the size of text up and down, the radius will scale as well. You can test the difference by making the radius have a value of say 5px, and then zooming up and down the text size. We’re well and truly on the way now. All we need to do is add a shadow to the button, and then a gradient background. In CSS3 there’s the box-shadow property, currently only supported in Safari 3. It’s very similar to text-shadow – you specify a horizontal and vertical offset, a blur value and a color. -webkit-box-shadow: 2px 2px 3px #999; box-shadow: 2px 2px 2px #bbb; Once more, we require the “experimental” -webkit- prefix, as Safari’s support for this property is still considered by its developers to be less than perfect. Gradient Background So, all we have left now is to add our shiny gradient effect. Now of course, people have been doing this kind of thing with images for a long time. But if we can avoid them all the better. Smaller pages, faster downloads, and more scalable designs that adapt better to the user’s font size preference. But how can we add a gradient background without an image? Here we’ll look at the only property that is not as yet part of the CSS standard – Apple’s gradient function for use anywhere you can use images with CSS (in this case backgrounds). In essence, this takes SVG gradients, and makes them available via CSS syntax. Here’s what the property and its value looks like: background-image: -webkit-gradient(linear, left top, left bottom, from(#e9ede8), to(#ce401c),color-stop(0.4, #8c1b0b)); Zooming in on the gradient function, it has this basic form: -webkit-gradient(type, point, point, from(color), to(color),color-stop(where, color)); Which might look complicated, but is less so than at first glance. The name of the function is gradient (and in this case, because it is an experimental property, we use the -webkit- prefix). You might not have seen CSS functions before, but there are others, including the attr() function, used with generated content. A function returns a value that can be used as a property value – here we are using it as a background image. Next we specify the type of the gradient. Here we have a linear gradient, and there are also radial gradients. After that, we specify the start and end points of the gradient – in our case the top and bottom of the element, in a vertical line. We then specify the start and end colors – and finally one stop color, located at 40% of the way down the element. Together, this creates a gradient that smoothly transitions from the start color in the top, vertically to the stop color, then smoothly transitions to the end color. There’s one last thing. What color will the background of our button be if the browser doesn’t support gradients? It will be white (or possibly some default color for buttons). Which may make the text difficult or impossible to read. So, we’ll add a background color as well (see why the validator is always warning you when a color but not a background color is specified for an element?). If we put it all together, here’s what we have: button { width: 15em; padding: .5em; color: #ffffff; text-shadow: 1px 1px 1px #000; border: solid thin #882d13; -webkit-border-radius: .7em; -moz-border-radius: .7em; border-radius: .7em; -webkit-box-shadow: 2px 2px 3px #999; box-shadow: 2px 2px 2px #bbb; background-color: #ce401c; background-image: -webkit-gradient(linear, left top, left bottom, from(#e9ede8), to(#ce401c),color-stop(0.4, #8c1b0b)); } Which looks like this in various browsers: In Safari (3) In Firefox 3.1 (3.0 supports border-radius but not text-shadow) In Opera 10 and of course in Internet Explorer (version 8 shown here) But it looks different in different browsers Yes, it does look different in different browsers, but we all know the answer to the question “do web sites need to look the same in every browser?“. Even if you really think sites should look the same in every browser, hopefully this little tutorial has whet your appetite for what CSS3 and experimental CSS that’s already supported in widely used browsers (and we haven’t even touched on animations and similar effects!). I hope you’ve enjoyed out little CSSMas present, and look forward to seeing your shiny buttons everywhere on the web. Oh, and there’s just a bit of homework – your job is to use the :hover selector, and make a gradient in the hover state. 2008 John Allsopp johnallsopp 2008-12-18T00:00:00+00:00 https://24ways.org/2008/shiny-happy-buttons/ code
74 Should We Be Reactive? Evolution Looking at the evolution of the web and the devices we use should help remind us that the times we’re adjusting to are just another step on a journey. These times seem to be telling us that we need to embrace flexibility. Imagine an HTML file containing nothing but text. It’s viewable on any web-capable device and reasonably readable: the notion of the universality of the web was very much a founding principle. Right from the beginning, browser vendors understood that we’d want text to reflow (why wouldn’t we?), so I consider the first websites to have been fluid. As we attempted to exert more control through our designs in the early days of the web, debates about whether we should produce fixed or fluid sites raged. We could create fluid designs using tables, but what we didn’t have then was a wide range of web capable devices or the ability to control this fluidity. The biggest changes occurred when stats showed enough people using a different screen resolution we could cater for. To me, the techniques of responsive web design provide the control we were missing. Combining new approaches to layout and images with media queries empowered us to learn how to embrace the inherent flexibility of the web in ways to suit our work and the devices used by our audience. Perhaps another kind of flexibility might be found in how we use context to affect how we present our content; to consider how we might use the information we can access from people, browsers and devices to provide web experiences – effectively creating sites that react to initial or changing circumstances in the relationship between people and our content. Embracing flexibility So what is context? Put simply, you could think of it as a secondary piece of information that helps clarify the meaning of the first. It helps set a scene or describe circumstances. I think that Cennydd Bowles has summed it up really well through talks he’s given recently, in which he’s arrived at the acronym DETAILS (Device, Environment, Time, Activity, Individual, Location, Social) – I encourage you to keep an eye out for his next book due in the new year where he’ll explore this idea much further. This clarity over what context could mean in terms of what we do on the web is fundamental, directing us towards ways we might use it. When you stop to think about it, we’ve been using some basic pieces of this information right from the beginning, like bits of JavaScript or Java applets that serve an appropriate greeting to your site’s visitors, or show their location, or even local weather. But what if we think of this from the beginning of our projects? We should think about our content first. Once we know this and have a direction, perhaps then we can think about what context, or even multiple contexts, might help us to communicate more effectively. The real world There’s always been a disconnect between the real world and the web, which is to be expected. But the world around us is a sea of data; every fundamental building block: people, places, events and things have information waiting to be explored. For sites based around physical objects or locations, this divide is really apparent. We don’t ordinarily take the time to describe in code the properties of a place, or consider whether your relationship to the place in the real world should have any impact on your relationship with a site about it. When I think about local businesses, they have such rich properties to draw on and yet we don’t really explore them in any meaningful way, even through something as simple as opening hours. Now we have data… We’ve long had access to the current time both on server- and client-sides. The use of geolocation is easier than ever, but when we look at the range of information we could glean to help us make some choices, maybe there’s some help on the horizon from projects like the W3C Device APIs Working Group. This might prove useful to help make us aware of network and battery conditions of a device, along with the potential to gain data from other sensors, which could tell us about lighting conditions, ambient noise levels and temperature depending on the capabilities of the device. It may be that our sites have some form of login or access to your profile from another site. Along with data from our devices and browsers, this should give us a sense of how best to talk to our audience in certain situations. We don’t necessarily need to know any personal details, just enough to make decisions about how to present our sites. The reactive web? So why reactive web design? I’m hoping that a name might help us to have a common vocabulary not only about what we mean when we talk about context, but how it could be considered through our projects, right from the early stages. How could this manifest itself? A simple example might be a location-aware panel on your site. Perhaps the space is a little down in your content hierarchy but serves a perfectly valid purpose by default. To visitors outside the country perhaps this works fine, but within your country maybe this panel could be used to communicate more effectively. Further still, if we knew the visitors were in the vicinity, we could talk to them more directly. What if both time and location were relevant? This space could work as before but you could consider how time could intersect with your local audience. If you know they’re local and it’s a certain time of day, you could communicate directly with them. This example isn’t beyond what banner ads often do and uses easily accessible information. There are more unusual combinations we may be able to find, such as movement and presence. Perhaps a site that tells a story, which changes design and content based on whether you’re moving, how long you’ve been on the site and how far you’ve travelled. This isn’t what we typically expect from websites, but we should bear in mind that what websites are now will not be what they become in the future. You could do much of this contextual presentation through native apps, of course. The Silent History, an app novel written and designed for iPad and iPhone, uses an exploration element, providing “hundreds of location-based stories across the U.S. and around the world. These can be read only when your device’s GPS matches the coordinates of the specified location.” But considering the universality of the web, we could redefine what web-based experiences should be like. Not all methods would work well on the web, but that’s a decision that has to be made for a specific project. By thinking more broadly about any web-capable device, we can use what we know to provide relevant experiences for our site’s visitors. We need to be sure what we mean by relevant, of course! Reality bites While there are incredible possibilities, from a simple panel on a site to something bordering on living sites that evolve and change with our circumstances, we need to act with a degree of pragmatism and understand how much of what we could do is based on assumptions and the bias of our own experiences. We could go wild with changing the way our content is presented based on contextual information, but if we’re not careful what we end up with confuses and could provide a very fractured experience. As much as possible we need to think more ethnographically, observe and question people in the situations we think may be relevant, and test our assumptions as early as we can. Even on small projects, there may be ways we can validate our assumptions and test with our audience. The key to applying contextual content or cues is not to break the experience between contextual views (as I think we now wouldn’t when hiding content on a mobile view). It’s another instance of progressive enhancement – as we know certain pieces of information, we can enhance the experience. Also, if you do change content, how can you not make a more cumbersome experience for your visitors? It’s all about communication Content is at the core of what we do, but if we consider context we need to understand the impact on that. The effect could be as subtle as an altered hierarchy, involve swapping out panels of content, or in extreme instances perhaps all of your content might change. In some ways, this extends the notion of adaptive content that Karen McGrane has been talking about, to how we write and store the content we create. Thinking about the the impact of context may require us to re-evaluate our site structure, too. Whatever we decide, we have to be clear what will happen and manage the expectations of our users. The bottom line What I’m proposing isn’t that we go crazy and end up with a confused, disjointed set of experiences across the web. What I hope is that starting right from the beginning of a project, we think about what context is and could be, and see what relevance it might have to what we’re trying to communicate. This strategic process leads us to think about design. We are slowly adapting to what it means to be flexible through responsive and adaptive processes. What does thinking about contextual states mean to us (or designing for state in general)? Does this highlight again how difficult it’ll be for our tools to keep up with our processes and output? In terms of code, the vast majority of this data comes from the client-side through JavaScript. While we can progressively enhance, this could lead to a lot of code bloat through feature or capability detection, and potentially a lot of conditional loading of scripts. It’s a real shame we don’t get much we can rely on from the server-side – we know how unreliable user agents are! We need to understand why we’d do this. Are we trying to communicate well and be useful, or doing it to show off? Underneath it all, what do we base our decisions on? Do we have actual insight or are we proceeding from our assumptions and the bias of our own experiences? Scott Jenson summed it up best for me: (to paraphrase) the pain we put people through has to be greatly outweighed by the value we offer. I see that this could be another potential step in our evolution on the web; continuing this exploration of the flexibility the web allows us. It’s amazing we can do such incredible things from what is essentially a set of disparate, linked documents. 2012 Dan Donald dandonald 2012-12-09T00:00:00+00:00 https://24ways.org/2012/should-we-be-reactive/ design
127 Showing Good Form Earlier this year, I forget exactly when (it’s been a good year), I was building a client site that needed widgets which look like this (designed, incidentally, by my erstwhile writing partner, Cameron Adams): Building this was a challenge not just in CSS, but in choosing the proper markup – how should such a widget be constructed? Mmm … markup It seemed to me there were two key issues to deal with: The function of the interface is to input information, so semantically this is a form, therefore we have to find a way of building it using form elements: fieldset, legend, label and input We can’t use a table for layout, even though that would clearly be the easiest solution! Abusing tables for layout is never good – physical layout is not what table semantics mean. But even if this data can be described as a table, we shouldn’t mix forms markup with non-forms markup, because of the behavioral impact this can have on a screen reader: To take a prominent example, the screen reader JAWS has a mode specifically for interacting with forms (cunningly known as “forms mode”). When running in this mode its output only includes relevant elements – legends, labels and form controls themselves. Any other kind of markup – like text in a previous table cell, a paragraph or list in between – is simply ignored. The user in this situation would have to switch continually in and out of forms mode to hear all the content. (For more about this issue and some test examples, there’s a thread at accessify forum which wanders in that direction.) One further issue for screen reader users is implied by the design: the input fields are associated together in rows and columns, and a sighted user can visually scan across and down to make those associations; but a blind user can’t do that. For such a user the row and column header data will need to be there at every axis; in other words, the layout should be more like this: And constructed with appropriate semantic markup to convey those relationships. By this point the selection of elements seems pretty clear: each row is a fieldset, the row header is a legend, and each column header is a label, associated with an input. Here’s what that form looks like with no CSS: And here’s some markup for the first row (with most of the attributes removed just to keep this example succinct): <fieldset> <legend> <span>Match points</span> </legend> <label> <span>Win</span> <input value="3" /> </label> <label> <span>Draw</span> <input value="1" /> </label> <label> <span>Lose</span> <input value="0" /> </label> <label> <span>Played</span> <input value="0" /> </label> </fieldset> The span inside each legend is because legend elements are highly resistant to styling! Indeed they’re one of the most stubborn elements in the browsers’ vocabulary. Oh man … how I wrestled with the buggers … until this obvious alternative occurred to me! So the legend element itself is just a container, while all the styling is on the inner span. Oh yeah, there was some CSS too I’m not gonna dwell too much on the CSS it took to make this work – this is a short article, and it’s all there in the demo [demo page, style sheet] But I do want to touch on the most interesting bit – where we get from a layout with headers on every row, to one where only the top row has headers – or at least, so it appears to graphical browsers. For screen readers, as we noted, we need those headers on every row, so we should employ some cunning CSS to partly negate their visual presence, without removing them from the output. The core styling for each label span is like this: label span { display:block; padding:5px; line-height:1em; background:#423221; color:#fff; font-weight:bold; } But in the rows below the header they have these additional rules: fieldset.body label span { padding:0 5px; line-height:0; position:relative; top:-10000em; } The rendered width of the element is preserved, ensuring that the surrounding label is still the same width as the one in the header row above, and hence a unified column width is preserved all the way down. But the element effectively has no height, and so it’s effectively invisible. The styling is done this way, rather than just setting the height to zero and using overflow:hidden, because to do that would expose an unrelated quirk with another popular screen reader! (It would hide the output from Window Eyes, as shown in this test example at access matters.) The finished widget It’s an intricate beast allright! But after all that we do indeed get the widget we want: Demo page Style sheet It’s not perfect, most notably because the legends have to have a fixed width; this can be in em to allow for text scaling, but it still doesn’t allow the content to break into multiple lines. It also doesn’t look quite right in Safari; and some CSS hacking was needed to make it look right in IE6 and IE7. Still it worked well enough for the purpose, and satisfied the client completely. And most of all it re-assured me in my faith – that there’s never any need to abuse tables for layout. (Unless of course you think this content is a table anyway, but that’s another story!) 2006 James Edwards jamesedwards 2006-12-11T00:00:00+00:00 https://24ways.org/2006/showing-good-form/ ux
104 Sitewide Search On A Shoe String One of the questions I got a lot when I was building web sites for smaller businesses was if I could create a search engine for their site. Visitors should be able to search only this site and find things without the maintainer having to put “related articles” or “featured content” links on every page by hand. Back when this was all fields this wasn’t easy as you either had to write your own scraping tool, use ht://dig or a paid service from providers like Yahoo, Altavista or later on Google. In the former case you had to swallow the bitter pill of computing and indexing all your content and storing it in a database for quick access and in the latter it hurt your wallet. Times have moved on and nowadays you can have the same functionality for free using Yahoo’s “Build your own search service” – BOSS. The cool thing about BOSS is that it allows for a massive amount of hits a day and you can mash up the returned data in any format you want. Another good feature of it is that it comes with JSON-P as an output format which makes it possible to use it without any server-side component! Starting with a working HTML form In order to add a search to your site, you start with a simple HTML form which you can use without JavaScript. Most search engines will allow you to filter results by domain. In this case we will search “bbc.co.uk”. If you use Yahoo as your standard search, this could be: <form id="customsearch" action="http://search.yahoo.com/search"> <div> <label for="p">Search this site:</label> <input type="text" name="p" id="term"> <input type="hidden" name="vs" id="site" value="bbc.co.uk"> <input type="submit" value="go"> </div> </form> The Google equivalent is: <form id="customsearch" action="http://www.google.co.uk/search"> <div> <label for="p">Search this site:</label> <input type="text" name="as_q" id="term"> <input type="hidden" name="as_sitesearch" id="site" value="bbc.co.uk"> <input type="submit" value="go"> </div> </form> In any case make sure to use the ID term for the search term and site for the site, as this is what we are going to use for the script. To make things easier, also have an ID called customsearch on the form. To use BOSS, you should get your own developer API for BOSS and replace the one in the demo code. There is click tracking on the search results to see how successful your app is, so you should make it your own. Adding the BOSS magic BOSS is a REST API, meaning you can use it in any HTTP request or in a browser by simply adding the right parameters to a URL. Say for example you want to search “bbc.co.uk” for “christmas” all you need to do is open the following URL: http://boss.yahooapis.com/ysearch/web/v1/christmas?sites=bbc.co.uk&format=xml&appid=YOUR-APPLICATION-ID Try it out and click it to see the results in XML. We don’t want XML though, which is why we get rid of the format=xml parameter which gives us the same information in JSON: http://boss.yahooapis.com/ysearch/web/v1/christmas?sites=bbc.co.uk&appid=YOUR-APPLICATION-ID JSON makes most sense when you can send the output to a function and immediately use it. For this to happen all you need is to add a callback parameter and the JSON will be wrapped in a function call. Say for example we want to call SITESEARCH.found() when the data was retrieved we can do it this way: http://boss.yahooapis.com/ysearch/web/v1/christmas?sites=bbc.co.uk&callback=SITESEARCH.found&appid=YOUR-APPLICATION-ID You can use this immediately in a script node if you want to. The following code would display the total amount of search results for the term christmas on bbc.co.uk as an alert: <script type="text/javascript"> var SITESEARCH = {}; SITESEARCH.found = function(o){ alert(o.ysearchresponse.totalhits); } </script> <script type="text/javascript" src="http://boss.yahooapis.com/ysearch/web/v1/christmas?sites=bbc.co.uk&callback=SITESEARCH.found&appid=Kzv_lcHV34HIybw0GjVkQNnw4AEXeyJ9Rb1gCZSGxSRNrcif_HdMT9qTE1y9LdI-"> </script> However, for our example, we need to be a bit more clever with this. Enhancing the search form Here’s the script that enhances a search form to show results below it. SITESEARCH = function(){ var config = { IDs:{ searchForm:'customsearch', term:'term', site:'site' }, loading:'Loading results...', noresults:'No results found.', appID:'YOUR-APP-ID', results:20 }; var form; var out; function init(){ if(config.appID === 'YOUR-APP-ID'){ alert('Please get a real application ID!'); } else { form = document.getElementById(config.IDs.searchForm); if(form){ form.onsubmit = function(){ var site = document.getElementById(config.IDs.site).value; var term = document.getElementById(config.IDs.term).value; if(typeof site === 'string' && typeof term === 'string'){ if(typeof out !== 'undefined'){ out.parentNode.removeChild(out); } out = document.createElement('p'); out.appendChild(document.createTextNode(config.loading)); form.appendChild(out); var APIurl = 'http://boss.yahooapis.com/ysearch/web/v1/' + term + '?callback=SITESEARCH.found&sites=' + site + '&count=' + config.results + '&appid=' + config.appID; var s = document.createElement('script'); s.setAttribute('src',APIurl); s.setAttribute('type','text/javascript'); document.getElementsByTagName('head')[0].appendChild(s); return false; } }; } } }; function found(o){ var list = document.createElement('ul'); var results = o.ysearchresponse.resultset_web; if(results){ var item,link,description; for(var i=0,j=results.length;i<j;i++){ item = document.createElement('li'); link = document.createElement('a'); link.setAttribute('href',results[i].clickurl); link.innerHTML = results[i].title; item.appendChild(link); description = document.createElement('p'); description.innerHTML = results[i]['abstract']; item.appendChild(description); list.appendChild(item); } } else { list = document.createElement('p'); list.appendChild(document.createTextNode(config.noresults)); } form.replaceChild(list,out); out = list; }; return{ config:config, init:init, found:found }; }(); Oooohhhh scary code! Let’s go through this one bit at a time: We start by creating a module called SITESEARCH and give it an configuration object: SITESEARCH = function(){ var config = { IDs:{ searchForm:'customsearch', term:'term', site:'site' }, loading:'Loading results...', appID:'YOUR-APP-ID', results:20 } Configuration objects are a great idea to make your code easy to change and also to override. In this case you can define different IDs than the one agreed upon earlier, define a message to show when the results are loading, when there aren’t any results, the application ID and the number of results that should be displayed. Note: you need to replace “YOUR-APP-ID” with the real ID you retrieved from BOSS, otherwise the script will complain! var form; var out; function init(){ if(config.appID === 'YOUR-APP-ID'){ alert('Please get a real application ID!'); } else { We define form and out as variables to make sure that all the methods in the module have access to them. We then check if there was a real application ID defined. If there wasn’t, the script complains and that’s that. form = document.getElementById(config.IDs.searchForm); if(form){ form.onsubmit = function(){ var site = document.getElementById(config.IDs.site).value; var term = document.getElementById(config.IDs.term).value; if(typeof site === 'string' && typeof term === 'string'){ If the application ID was a winner, we check if the form with the provided ID exists and apply an onsubmit event handler. The first thing we get is the values of the site we want to search in and the term that was entered and check that those are strings. if(typeof out !== 'undefined'){ out.parentNode.removeChild(out); } out = document.createElement('p'); out.appendChild(document.createTextNode(config.loading)); form.appendChild(out); If both are strings we check of out is undefined. We will create a loading message and subsequently the list of search results later on and store them in this variable. So if out is defined, it’ll be an old version of a search (as users will re-submit the form over and over again) and we need to remove that old version. We then create a paragraph with the loading message and append it to the form. var APIurl = 'http://boss.yahooapis.com/ysearch/web/v1/' + term + '?callback=SITESEARCH.found&sites=' + site + '&count=' + config.results + '&appid=' + config.appID; var s = document.createElement('script'); s.setAttribute('src',APIurl); s.setAttribute('type','text/javascript'); document.getElementsByTagName('head')[0].appendChild(s); return false; } }; } } }; Now it is time to call the BOSS API by assembling a correct REST URL, create a script node and apply it to the head of the document. We return false to ensure the form does not get submitted as we want to stay on the page. Notice that we are using SITESEARCH.found as the callback method, which means that we need to define this one to deal with the data returned by the API. function found(o){ var list = document.createElement('ul'); var results = o.ysearchresponse.resultset_web; if(results){ var item,link,description; We create a new list and then get the resultset_web array from the data returned from the API. If there aren’t any results returned, this array will not exist which is why we need to check for it. Once we done that we can define three variables to repeatedly store the item title we want to display, the link to point to and the description of the link. for(var i=0,j=results.length;i<j;i++){ item = document.createElement('li'); link = document.createElement('a'); link.setAttribute('href',results[i].clickurl); link.innerHTML = results[i].title; item.appendChild(link); description = document.createElement('p'); description.innerHTML = results[i]['abstract']; item.appendChild(description); list.appendChild(item); } We then loop over the results array and assemble a list of results with the titles in links and paragraphs with the abstract of the site. Notice the bracket notation for abstract as abstract is a reserved word in JavaScript2 :). } else { list = document.createElement('p'); list.appendChild(document.createTextNode(config.noresults)); } form.replaceChild(list,out); out = list; }; If there aren’t any results, we define a paragraph with the no results message as list. In any case we replace the old out (the loading message) with the list and re-define out as the list. return{ config:config, init:init, found:found }; }(); All that is left to do is return the properties and methods we want to make public. In this case found needs to be public as it is accessed by the API return. We return init to make it accessible and config to allow implementers to override any of the properties. Using the script In order to use this script, all you need to do is to add it after the form in the document, override the API key with your own and call init(): <form id="customsearch" action="http://search.yahoo.com/search"> <div> <label for="p">Search this site:</label> <input type="text" name="p" id="term"> <input type="hidden" name="vs" id="site" value="bbc.co.uk"> <input type="submit" value="go"> </div> </form> <script type="text/javascript" src="boss-site-search.js"></script> <script type="text/javascript"> SITESEARCH.config.appID = 'copy-the-id-you-know-to-get-where'; SITESEARCH.init(); </script> Where to go from here This is just a very simple example of what you can do with BOSS. You can define languages and regions, retrieve and display images and news and mix the results with other data sources before displaying them. One very cool feature is that by adding a view=keyterms parameter to the URL you can get the keywords of each of the results to drill deeper into the search. An example for this written in PHP is available on the YDN blog. For JavaScript solutions there is a handy wrapper called yboss available to help you go nuts. 2008 Christian Heilmann chrisheilmann 2008-12-04T00:00:00+00:00 https://24ways.org/2008/sitewide-search-on-a-shoestring/ code
229 Sketching to Communicate As a web designer I’ve always felt that I’d somehow cheated the system, having been absent on the day God handed out the ability to draw. I didn’t study fine art, I don’t have a natural talent to effortlessly knock out a realistic bowl of fruit beside a water jug, and yet somehow I’ve still managed to blag my way this far. I’m sure many of you may feel the same. I had no intention of becoming an artist, but to have enough skill to convey an idea in a drawing would be useful. Instead, my inadequate instrument would doodle drunkenly across the page leaving a web of unintelligible paths instead of the refined illustration I’d seen in my mind’s eye. This – and the natural scrawl of my handwriting – is fine (if somewhat frustrating) when it’s for my eyes only but, when sketching to communicate a concept to a client, such amateur art would be offered with a sense of embarrassment. So when I had the opportunity to take part in some sketching classes whilst at Clearleft I jumped at the chance. Why sketch? In UX workshops early on in a project’s life, sketching is a useful and efficient way to convey and record ideas. It’s disposable and inexpensive, but needn’t look amateur. A picture may be worth a thousand words, but a well executed sketch of how you’ll combine funny YouTube videos with elephants to make Lolephants.com could be worth millions in venture capital. Actually, that’s not bad… ;-) Although (as you will see) the basics of sketching are easy to master, the kudos you will receive from clients for being a ‘proper designer’ makes it worthwhile! Where to begin? Start by not buying yourself a sketch pad. If you were the type of child who ripped the first page out of a school exercise book and started again if you made even a tiny mistake (you’re not alone!), Wreck This Journal may offer a helping hand. Practicing on plain A4 paper instead of any ‘special’ notepad will make the process a whole lot easier, no matter how deliciously edible those Moleskines look. Do buy yourself a black fine-liner pen and a set of grey Pro Markers for shading. These pens are unlike any you will have used before, and look like blended watercolours once the ink is dry. Although multiple strokes won’t create unsightly blotches of heavy ink on the page, they will go right through your top sheet so always remember to keep a rough sheet in the second position as an ink blotter. photo by Tom Harrison Don’t buy pencils to sketch with, as they lack the confidence afforded by the heavy black ink strokes of marker pens and fine-liners. If you’re going to be sketching with clients then invest in some black markers and larger sheets of paper. At the risk of sounding like a stationery brand whore, Sharpies are ideal, and these comedy-sized Post-Its do the job far better than cheaper, less sticky alternatives. Although they’re thicker than most standard paper, be sure to double-layer them if you’re writing on them on a wall, unless you fancy a weekend redecorating your client’s swanky boardroom. The best way to build confidence and improve your sketching technique is, obviously, to practise. Reading this article will be of no help unless you repeat the following examples several times each. Go grab a pen and some paper now, and notice how you improve within even a short period of time. Sketching web UI Most elements of any website can be drawn as a combination of geometric shapes. photo by Nathanael Boehm Circles To draw a circle, get in position and start by resting your hand on the page and making the circular motion a few times without putting pen to paper. As you lower your pen whilst continuing the motion, you should notice the resulting shape is more regular than it otherwise would have been. Squares and rectangles Draw one pair of parallel lines first, followed by the others to complete the shapes. Slightly overlap the ends of the lines to make corners feel more solid than if you were to leave gaps. If you’re drawing a container, always draw the contents first, that way it won’t be a squash to fit them in. If you’re drawing a grid (of thumbnails, for instance), draw all parallel lines first as a series of long dashes to help keep line lengths and angles consistent. Shadows To lift elements from the page for emphasis, add a subtle shadow with a grey marker. For the most convincing look, assume the light source to be at the top left of the page – the shadow should simply be a thick grey line along the bottom and up the right edge of your shape. If the shape is irregular, the shadow should follow its outline. This is a good way to emphasise featured items, speech bubbles, form buttons, and so on. Sketching ideas Arrows Use arrows to show steps in a process or direction of movement. Giving shadows a 3-D feel, or adding a single colour, will help separate them from the rest of the sketch. Faces Start by drawing the circle. The direction of the nose (merely a point) indicates the direction of the person’s gaze. The eyes and mouth show emotion: more open and curvy for happy thoughts; more closed and jagged for angry thoughts. Try out a few shapes and see what emotions they convey. People Remember, we’re aiming for communication rather than realism here. A stick man would be fine. Give him a solid body, as shown in this example, and it becomes easier to pose him. I know you think hands are hard, but they’re quite important to convey some ideas, and for our purposes we don’t need to draw hands with any detail. An oval with a stick does the job of a pointing hand. Close-ups might need more fingers showing, but still don’t require any degree of realism. Signage Don’t be afraid to use words. We’re sketching to communicate, so if the easiest way to show an office block is a building with a big ‘office’ sign on the roof, that’s fine! Labels Likewise, feel free to label interactions. Use upper-case letters for legibility and slightly angle the horizontal bars upwards to create a more positive feel. Clichés Clichés are your friend! Someone’s having an idea? Light bulb above the head. Computer’s crashed? Cloud of smoke with “$£%*!” It’s good to practise regularly. Try applying these principles to still life, too. Look around you now and draw the cup on the table, or the books on the shelf. Think of it as a combination of shapes and aim for symbolism rather than realism, and it’s not as hard as you’d think. I hope this has given you the confidence to give it a shot, and the ability to at least not be mortified with the results! Tip: If you’re involving clients in design games like Leisa Reichelt’s ‘Design Consequences’ it may be wise to tone down the quality of your drawings at that point so they don’t feel intimidated. Remember, it’s important for them to feel at ease with the idea of wireframing in front of you and their colleagues, no matter how bad their line work. For more information see davegrayinfo.com – Dave Gray taught me everything I know :-) 2010 Paul Annett paulannett 2010-12-19T00:00:00+00:00 https://24ways.org/2010/sketching-to-communicate/ business
66 Solve the Hard Problems So, here we find ourselves on the cusp of 2016. We’ve had a good year – 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. As it’s the time to make resolutions, I wanted to share three small ideas to take into the new year. Get good at what you do “How do you get to Carnegie Hall?” the old joke goes. “Practise, practise, practise.” We work in an industry where there is an awful lot to learn. There’s a lot to learn to get started and then once you do, there’s a lot more to learn to keep your skills current. Just when you think you’ve mastered something, it changes. This 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’m 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. Picking where to spend your time One 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’ll probably now be spending your time relearning Sass instead. If you spent time learning Grunt, chances are you’ll now be thinking about whether you should switch to Gulp. It’s not just that there are new types of tools, there are new tools and frameworks to do the things you’re already doing, but, well, differently. Deciding 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’ve learned and then relearned the tools everyone says you need for your job, there’s rarely enough time to spend really getting to know how best to use them.  Practise, practise, practise Do you know how you don’t 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’re destined to produce amateurish work forever. Learn the new thing, but then stick with it long enough to get really good at it – even if Twitter trolls try to convince you it’s not cool. What’s really not cool is living as a forevernoob. If you’re 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. Audience and purpose Back 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. It’s 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. Being productive It 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’ve 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? Whether 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’s going to be a struggle. Yes, it’s music, but that’s neither the audience nor purpose for which it was created. The same is absolutely true for your in-house tools – 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. That’s 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’t be in the market for your product – they would have built their own. Sometimes you hear the advice to “scratch your own itch” when it comes to product design. I don’t completely agree. Got an itch? Great. Find other itchy people and sell them a backscratcher. Building a product, like designing a website, is a lot of work. It requires knowing your audience and purpose inside out. You can’t fudge it and you can’t just hope you’ll find an audience for some old thing you have lying around. Always consider the audience and purpose for everything you create. It’s often the difference between success and failure. Solve the hard problems Human 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’s not very hard. Do you know what you get at the end of it? Paid. But nothing really great ever happens that way. I 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’t managed carefully, storage sizes would get out of control, content would go unattributed, and everything would get very messy very quickly. I 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. It 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. Turn your hardest problems into your biggest strengths There’s a funny thing about hard problems. The hardest problems are the most fun to solve and have the biggest impact. Maybe you’re the sort of person who clocks in for work, does their job and clocks out at 5pm without another thought. But I don’t think you are, because you’re here reading this. If you really love what you do, I don’t think you can be satisfied in your work unless you’re seeking out and working on those hard problems. That’s where the magic is. The new year is a helpful time to think about breaking bad habits. Whether it’s 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. Get good at what you do. Practise your skills and don’t just flit from one shiny thing to the next. Remember who you’re doing it for and why. Consider the audience and purpose for everything you create. Solve the hard problems. It’s more interesting, more satisfying, and has a greater impact. As we move into 2016, these are the things I’m going to continue to work on. Maybe you’d like to join me. 2015 Drew McLellan drewmclellan 2015-12-24T00:00:00+00:00 https://24ways.org/2015/solve-the-hard-problems/ process
219 Speed Up Your Site with Delayed Content Speed remains one of the most important factors influencing the success of any website, and the first rule of performance (according to Yahoo!) is reducing the number of HTTP requests. Over the last few years we’ve seen techniques like sprites and combo CSS/JavaScript files used to reduce the number of HTTP requests. But there’s one area where large numbers of HTTP requests are still a fact of life: the small avatars attached to the comments on articles like this one. Avatars Many sites like 24 ways use a fantastic service called Gravatar to provide user images. As a user, you can sign up to Gravatar, give them your e-mail address, and upload an image to represent you. Sites can then include your image by generating a one way hash of your e-mail address and using that to build an image URL. For example, the markup for the comments on this page looks something like this: <div> <h4><a href="http://allinthehead.com/"> <img src="http://www.gravatar.com/avatar.php?gravatar_id=13734b0cb20708f79e730809c29c3c48&size=100" class="gravatar" alt="" height="100" width="100" /> Drew McLellan </a></h4> <p>This is a great article!</p> </div> The Gravatar URL contains two parts. 100 is the size in pixels of the image we want. 13734b0cb20708f79e730809c29c3c48 is an MD5 digest of Drew’s e-mail address. Using MD5 means we can request an image for a user without sharing their e-mail address with anyone who views the source of the page. So what’s wrong with avatars? The problem is that a popular article can easily get hundreds of comments, and every one of them means another image has to be individually requested from Gravatar’s servers. Each request is small and the Gravatar servers are fast but, when you add them up, it can easily add seconds to the rendering time of a page. Worse, they can delay the loading of more important assets like the CSS required to render the main content of the page. These images aren’t critical to the page, and don’t need to be loaded up front. Let’s see if we can delay loading them until everything else is done. That way we can give the impression that our site has loaded quickly even if some requests are still happening in the background. Delaying image loading The first problem we find is that there’s no way to prevent Internet Explorer, Chrome or Safari from loading an image without removing it from the HTML itself. Tricks like removing the images on the fly with JavaScript don’t work, as the browser has usually started requesting the images before we get a chance to stop it. Removing the images from the HTML means that people without JavaScript enabled in their browser won’t see avatars. As Drew mentioned at the start of the month, this can affect a large number of people, and we can’t completely ignore them. But most sites already have a textual name attached to each comment and the avatars are just a visual enhancement. In most cases it’s OK if some of our users don’t see them, especially if it speeds up the experience for the other 98%. Removing the images from the source of our page also means we’ll need to put them back at some point, so we need to keep a record of which images need to be requested. All Gravatar images have the same URL format; the only thing that changes is the e-mail hash. Storing this is a great use of HTML5 data attributes. HTML5 data what? Data attributes are a new feature in HTML5. The latest version of the spec says: A custom data attribute is an attribute in no namespace whose name starts with the string “data-”, has at least one character after the hyphen, is XML-compatible, and contains no characters in the range U+0041 to U+005A (LATIN CAPITAL LETTER A to LATIN CAPITAL LETTER Z). […] Custom data attributes are intended to store custom data private to the page or application, for which there are no more appropriate attributes or elements. These attributes are not intended for use by software that is independent of the site that uses the attributes. In other words, they’re attributes of an HTML element that start with “data-” which you can use to share data with scripts running on your site. They’re great for adding small bits of metadata that don’t fit into an existing markup pattern the way microformats do. Let’s see this in action Take a look at the markup for comments again: <div> <h4><a href="http://allinthehead.com/"> <img src="http://www.gravatar.com/avatar.php?gravatar_id=13734b0cb20708f79e730809c29c3c48&size=100" class="gravatar" alt="" height="100" width="100" /> Drew McLellan </a></h4> <p>This is a great article!</p> </div> Let’s replace the <img> element with a data-gravatar-hash attribute on the <a> element: <div> <h4><a href="http://allinthehead.com/" data-gravatar-hash="13734b0cb20708f79e730809c29c3c48"> Drew McLellan </a></h4> <p>This is a great article!</p> </div> Once we’ve done this, we’ll need a small bit of JavaScript to find all these attributes, and replace them with images after the page has loaded. Here’s an example using jQuery: $(window).load(function() { $('a[data-gravatar-hash]').prepend(function(index){ var hash = $(this).attr('data-gravatar-hash') return '<img width="100" height="100" alt="" src="http://www.gravatar.com/avatar.php?size=100&gravatar_id=' + hash + '">' }) }) This code waits until everything on the page is loaded, then uses jQuery.prepend to insert an image into every link containing a data-gravatar-hash attribute. It’s short and relatively simple, but in tests it reduced the rendering time of a sample page from over three seconds to well under one. Finishing touches We still need to consider the appearance of the page before the avatars have loaded. When our script adds extra content to the page it will cause a browser reflow, which is visually annoying. We can avoid this by using CSS to reserve some space for each image before it’s inserted into the HTML: #comments div { padding-left: 110px; min-height: 100px; position: relative; } #comments div h4 img { display: block; position: absolute; top: 0; left: 0; } In a real world example, we’ll also find that the HTML for a comment is more varied as many users don’t provide a web page link. We can make small changes to our JavaScript and CSS to handle this case. Put this all together and you get this example. Taking this idea further There’s no reason to limit this technique to sites using Gravatar; we can use similar code to delay loading any images that don’t need to be present immediately. For example, this year’s redesigned Flickr photo page uses a “data-defer-src” attribute to describe any image that doesn’t need to be loaded straight away, including avatars and map tiles. You also don’t have to limit yourself to loading the extra resources once the page loads. You can get further bandwidth savings by waiting until the user takes an action before downloading extra assets. Amazon has taken this tactic to the extreme on its product pages – extra content is loaded as you scroll down the page. So next time you’re building a page, take a few minutes to think about which elements are peripheral and could be delayed to allow more important content to appear as quickly as possible. 2010 Paul Hammond paulhammond 2010-12-18T00:00:00+00:00 https://24ways.org/2010/speed-up-your-site-with-delayed-content/ ux
331 Splintered Striper Back in March 2004, David F. Miller demonstrated a little bit of DOM scripting magic in his A List Apart article Zebra Tables. His script programmatically adds two alternating CSS background colours to table rows, making them more readable and visually pleasing, while saving the document author the tedious task of manually assigning the styling to large static data tables. Although David’s original script performs its duty well, it is nonetheless very specific and limited in its application. It only: works on a single table, identified by its id, with at least a single tbody section assigns a background colour allows two colours for odd and even rows acts on data cells, rather than rows, and then only if they have no class or background colour already defined Taking it further In a recent project I found myself needing to apply a striped effect to a medium sized unordered list. Instead of simply modifying the Zebra Tables code for this particular case, I decided to completely recode the script to make it more generic. Being more general purpose, the function in my splintered striper experiment is necessarily more complex. Where the original script only expected a single parameter (the id of the target table), the new function is called as follows: striper('[parent element tag]','[parent element class or null]','[child element tag]','[comma separated list of classes]') This new, fairly self-explanatory function: targets any type of parent element (and, if specified, only those with a certain class) assigns two or more classes (rather than just two background colours) to the child elements inside the parent preserves any existing classes already assigned to the child elements See it in action View the demonstration page for three usage examples. For simplicity’s sake, we’re making the calls to the striper function from the body’s onload attribute. In a real deployment situation, we would look at attaching a behaviour to the onload programmatically — just remember that, as we need to pass variables to the striper function, this would involve creating a wrapper function which would then be attached…something like: function stripe() { striper('tbody','splintered','tr','odd,even'); } window.onload=stripe; A final thought Just because the function is called striper does not mean that it’s limited to purely applying a striped look; as it’s more of a general purpose “alternating class assignment” script, you can achieve a whole variety of effects with it. 2005 Patrick Lauke patricklauke 2005-12-15T00:00:00+00:00 https://24ways.org/2005/splintered-striper/ code
184 Spruce It Up The landscape of web typography is changing quickly these days. We’ve gone from the wild west days of sIFR to Cufón to finally seeing font embedding seeing wide spread adoption by browser developers (and soon web designers) with @font-face. For those who’ve felt limited by the typographic possibilities before, this has been a good year. As Mark Boulton has so eloquently elucidated, @font-face embedding doesn’t come without its drawbacks. Font files can be quite large and FOUT—that nasty flash of unstyled text—can be a distraction for users. Data URIs We can battle FOUT by using Data URIs. A Data URI allows the font to be encoded right into the CSS file. When the font comes with the CSS, the flash of unstyled text is mitigated. No extra HTTP requests are required. Don’t be a grinch, though. Sending hundreds of kilobytes down the pipe still isn’t great. Sometimes, all we want to do is spruce up our site with a little typographic sugar. Be Selective Dan Cederholm’s SimpleBits is an attractive site. Take a look at the ampersand within the header of his site. It’s the lovely (and free) Goudy Bookletter 1911 available from The League of Movable Type. The Opentype format is a respectable 28KB. Nothing too crazy but hold on here. Mr. Cederholm is only using the ampersand! Ouch. That’s a lot of bandwidth just for one character. Can we optimize a font like we can an image? Yes. Image optimization essentially works by removing unnecessary image data such as colour data, hidden comments or using compression algorithms. How do you remove unnecessary information from a font? Subsetting. If you’re the adventurous type, grab a copy of FontForge, which is an open source font editing tool. You can open the font, view and edit any of the glyphs and then re-generate the font. The interface is a little clunky but you’ll be able to select any character you don’t want and then cut the glyphs. Re-generate your font and you’ve now got a smaller file. There are certainly more optimizations that can also be made such as removing hinting and kerning information. Keep in mind that removing this information may affect how well the type renders. At this time of year, though, I’m sure you’re quite busy. Save yourself some time and head on over to the Font Squirrel Font Generator. The Font Generator is extremely handy and allows for a number of optimizations and cross-platform options to be generated instantly. Select the font from your local system—make sure that you are only using properly licensed fonts! In this particular case, we only want the ampersand. Click on Subset Fonts which will open up a new menu. Unselect any preselected sets and enter the ampersand into the Single Characters text box. Generate your font and what are you left with? 3KB. The Font Generator even generates a base64 encoded data URI stylesheet to be imported easily into your project. Check out the Demo page. (This demo won’t work in Internet Explorer as we’re only demonstrating the Data URI font embedding and not using the EOT file format that IE requires.) No Unnecessary Additives If you peeked under the hood of that demo, did you notice something interesting? There’s no <span> around the ampersand. The great thing about this is that we can take advantage of the font stack’s natural ability to switch to a fallback font when a character isn’t available. Just like that, we’ve managed to spruce up our page with a little typographic sugar without having to put on too much weight. 2009 Jonathan Snook jonathansnook 2009-12-19T00:00:00+00:00 https://24ways.org/2009/spruce-it-up/ code
85 Starting Your Project on the Right Foot (and Keeping It There) I’m not sure if anything is as terrifying as beginning a new design project. I often spend hours trying to find the best initial footing in a design, so I’ve been working hard to improve my process, particularly for the earliest stages of a project. I want to smooth out the bumps that disrupt my creative momentum and focus on the emotional highs and lows I experience, and then try to minimize the lows and ride the highs as long as possible. Design is often a struggle broken up by blissful moments of creative clarity that provide valuable force to move your work forward. Momentum is a powerful tool in creative work, and it’s something we don’t always maximize when we’re working because of the hectic nature of our field. Obviously, every designer is going to have a different process, but I thought I’d share some of the methods I’ve begun to adopt. I hope this will spark a conversation among designers who are interested in looking at process in a new way. Jump-starting a project I cannot overstate the importance of immersing yourself in design and collecting ample amounts of inspiration when beginning a project. I make it a daily practice to visit a handful of sites (Dribbble, Graphic Exchange, Web Creme, siteInspire, Designspiration, and others) and save any examples of design that I like. I then sort them into general categories (publication design, illustration, typography, web design, and so on). Enjoying a bit of fresh design every day helps me absorb it and analyze why it’s effective instead of just imitating it.  Many designers are afraid to look at too much design for fear that they’ll be tempted to copy it, but I feel a steady influx of design inspiration reduces that possibility. You’re much more likely to take the easy way out and rip off a design if you’re scrambling for inspiration after getting stuck. If you are immersed in design from a variety of mediums, you’ll engage your creative brain on multiple levels and have an easier time creating something unique for your project. Looking at good design will not make you a good designer but it will make you a better designer. Design is design Try not to limit your visual research to the medium you’re working in. Websites, books, posters and packaging all have their own unique limitations and challenges, and any one of those characteristics could be useful to you. Posters need to grab the viewer and pass on a small tidbit of information; packaging needs to encourage physical interaction; and websites need to encourage exploration. If you know the challenges you’ll be facing, you will know where to look for design that tackles those same problems. I find it refreshing to look at design from the turn of the nineteenth century, when type was laid out on objects without thought to aesthetics. Many vintage packages break all sorts of modern design rules, and looking at that kind of work is a great way to spark your creativity. Pulling yourself out of the box and away from the rules of what you’re working on can reveal solutions that are innovative and unique. After a little finessing, the warning label text from a 1940s hazardous chemical box from could have the exact type and icon arrangement you need for your project. There’s a massive pool of design to pull from that doesn’t have the limitations the web has, and exploring those design worlds will help you grow your own repertoire. If all else fails, start with the footer The very beginning of a project is the most frustrating point in a project for me. I’m trying to figure out typeface combinations, colors and the overall voice of the design, and until I find the right solutions, I’m a wreck. I’ve found often that my frustration stems from trying to solve too many problems at once. The beginning of a project has a lot of moving targets, nearly endless possible solutions, and constantly changing variables. You’ll knock out one problem only to discover your solution doesn’t jive with something you worked out earlier — you end up designing in circles. If you find yourself getting stuck at the beginning of a website design, try working out one specific element of the site and see what emerges. I’m going to recommend the footer. Why? Footers can easily be ignored in a design or become a dumping ground for items that couldn’t be worked into the main layout. But, at the start of most projects, the minimum content requirements for the footer are usually established. There needs to be a certain number of links, social media buttons, copyright details, a search bar, and so on. It’s a self-contained item within the design that has a specific purpose, and that’s a great element to focus on when you’re stuck in a design. Colors, typefaces, link styles, input fields and buttons can all be sketched out from just the footer. It’s a very flexible element that can be as prominent or subtle as you want, and it’s a solid starting point for setting the tone and style of a site. Save the details Designers love details. I love details. But don’t let nitpicking early on in your process kill your creative momentum. Design is an emotional process, and being frustrated or defeated by a tricky problem or a graphical detail you just can’t nail down can deflate your creative energies. If you hit a roadblock, set it aside and tackle another piece of the project. As you spend time engaged in a design, the style you develop will evolve according to the needs of the content, and you might arrive naturally at a solution that will work perfectly for the problem that had you stuck before.  If I find myself working on one particular element for more than a half an hour without any clear movement, I shelve it. Designers often wear their obsessive detail-oriented tendencies as a badge of honor, but there’s a difference between making the design better and wasting time. If you’ve spent hours nudging elements around pixel by pixel and can’t settle on something, it probably means what you’re doing isn’t making a huge improvement on the design. Don’t be afraid to let it lie and come at it again with fresh eyes. You will be better equipped to tackle the finer points of a project once you’ve got the broad strokes defined. Have a plan when you start and stop designing We all know that creativity isn’t something you can turn on effortlessly, and it’s easy to forget the emotional process that goes along with design. If you leave a project in a place of frustration, it’s going to stay with you in your free time and affect you negatively, like a dark cloud of impending disaster. Try to end each design session with a victory, a small bit of definable progress that you can take with you in your downtime. Even something as small as finding the right opacity for the interior shadow on the search bar in the header of the site is a win. Likewise, when you return to a project after a break, it can be difficult to get the ball rolling on the design again if you set it down without a clear path for the next steps. I find that I work on details best when I’m returning from downtime, when I’m fresh and re-energized and ready to dig in again. Try to pick out at least one element you’d like to fine-tune when you are winding down in a design session and use it to kick-start your next session. Content is king I would argue there is nothing more crucial to the success of a design than having the content defined from the outset. Designing without content is similar to designing without an audience, and designing with vague ideas of content types and character limits is going to result in a muted design that doesn’t reach its full potential. Images and language go hand in hand with design, and can take a design from functional to outstanding if you have them available from the outset. We don’t always have the luxury of having content to build a design around, but fight for it whenever you can. For example, if the site you are designing is full of technical jargon, your paragraphs might need a longer line length to accommodate the longer words being used.  Often, working with content will lead to design solutions you wouldn’t have come to otherwise. Design speaks to content, and content speaks to design. Lorem ipsum doesn’t speak to anyone (unless you know Latin, in which case, congratulations!). Every project has its own set of needs, and every designer has his or her own method of working. There’s obviously no perfect process to design, and being dogmatic about process can be just as harmful as not having one. Exposing yourself to new design and new ways of designing is an easy way to test your skills and grow. When things are hard and you can’t get any momentum going on a design, this is when your skill set is truly challenged. We all hope to get wonderful projects with great assets and ample creative possibilities, but you won’t always be so blessed, and this is when the quality of your process is really going to shine. 2012 Bethany Heck bethanyheck 2012-12-02T00:00:00+00:00 https://24ways.org/2012/starting-your-project-on-the-right-foot/ process
210 Stop Leaving Animation to the Last Minute Our design process relies heavily on static mockups as deliverables and this makes it harder than it needs to be to incorporate UI animation in our designs. Talking through animation ideas and dancing out the details of those ideas can be fun; but it’s not always enough to really evaluate or invest in animated design solutions. By including deliverables that encourage discussing animation throughout your design process, you can set yourself (and your team) up for creating meaningful UI animations that feel just as much a part of the design as your colour palette and typeface. You can get out of that “running out of time to add in the animation” trap by deliberately including animation in the early phases of your design process. This will give you both the space to treat animation as a design tool, and the room to iterate on UI animation ideas to come up with higher quality solutions. Two deliverables that can be especially useful for this are motion comps and animated interactive prototypes. Motion comps - an animation deliverable Motion comps (also called animatics or motion mock-ups) are usually video representation of UI animations. They are used to explore the details of how a particular animation might play out. And they’re most often made with timeline-based tools like Adobe After Effects, Adobe Animate, or Tumult Hype. The most useful things about motion comps is how they allow designers and developers to share the work of creating animations. (Instead of pushing all the responsibility of animation on one group or the other.) For example, imagine you’re working on a design that has a content panel that can either be open or closed. You might create a mockup like the one below including the two different views: the closed state and the open state. If you’re working with only static deliverables, these two artboards might be exactly what you handoff to developers along with the instruction to animate between the two. On the surface that seems pretty straight forward, but even with this relatively simple transition there’s a lot that those two artboards don’t address. There are seven things that change between the closed state and the open state. That’s seven things the developer building this out has to figure out how to move in and out of view, when, and in what order. And all of that is even before starting to write the code to make it work. By providing only static comps, all the logic of the animation falls on the developer. This might go ok if she has the bandwidth and animation knowledge, but that’s making an awful lot of assumptions. Instead, if you included a motion mock up like this with your static mock ups, you could share the work of figuring out the logic of the animation between design and development. Designers could work out the logic of the animation in the motion comp, exploring which items move at which times and in which order to create the opening and closing transitions. The motion comp can also be used to iterate on different possible animation approaches before any production code has to be committed too. Sharing the work and giving yourself time to explore animation ideas before you’re backed up again the deadline will lead to happier teammates and better design solutions. When to use motion comps I’m not a fan of making more deliverables just for the sake of having more things to make, so I find it helps to narrow down what question I’m trying answer before choosing which sort of deliverable to make to investigate. Motion comps can be most helpful for answering questions like: Exactly how should this animation look? Which items should move? Where? And when? Do the animation qualities reflect our brand or our voice and tone? One of the added bonuses of creating motion comps to answer these questions is that you’ll have a concrete thing to bring to design critiques or reviews to get others’ input on them as well. Using motion comps as handoff Motion comps are often used to handoff animation ideas from design to development. They can be super useful for this, but they’re even more useful when you include the details of the motion specs with them. (It’s difficult, if not impossible, to glean these details from playing back a video.) More specifically, you’ll want to include: Durations and the properties animated for each animation Easing curve values or spring values used Delay values and repeat counts In many cases you’ll have to collect these details up manually. But this isn’t necessarily something that that will take a lot of time. If you take note of them as you’re creating the motion comp, chances are most of these details will already be top of mind. (Also, if you use After Effects for your motion comps, the Inspector Spacetime plugin might be helpful for this task.) Animated prototypes - an interactive deliverable Making prototypes isn’t a new idea for web work by any stretch, but creating prototypes that include animation – or even creating prototypes specifically to investigate potential animation solutions – can go a long way towards having higher quality animations in your final product. Interactive prototypes are web or app-based, or displayed in a particular tool’s preview window to create a useable version of interactions that might end up in the end product. They’re often made with prototyping apps like Principle, Framer, or coded up in HTML, CSS and JS directly like the example below. See the Pen Prototype example by Val Head (@valhead) on CodePen. The biggest different between motion comps and animated prototypes is the interactivity. Prototypes can reposed to taps, drags or gestures, while motion comps can only play back in a linear fashion. Generally speaking, this makes prototypes a bit more of an effort to create, but they can also help you solve different problems. The interactive nature of prototypes can also make them useful for user testing to further evaluate potential solutions. When to use prototypes When it comes to testing out animation ideas, animated prototypes can be especially helpful in answering questions like these: How will this interaction feel to use? (Interactive animations often have different timing needs than animations that are passively viewed.) What will the animation be like with real data or real content? Does this animation fit the context of the task at hand? Prototypes can be used to investigate the same questions that motion comps do if you’re comfortable working in code or your prototyping tool of choice has capabilities to address high fidelity animation details. There are so many different prototyping tools out there at the moment, you’re sure to be able to find one that fits your needs. As a quick side note: If you’re worried that your coding skills might not be up to par to prototype in code, know that prototype code doesn’t have to be production quality code. Animated prototypes’ main concern is working out the animation details. Once you’ve arrived at a combination of animations that works, the animation specifics can be extracted or the prototype can be refactored for production. Motion comp or prototype? Both motion comps and prototypes can be extremely useful in the design process and you can use whichever one (or ones) that best fits your team’s style. The key thing that both offer is a way to make animation ideas visible and sharable. When you and your teammate are both looking at the same deliverable, you can be confident you’re talking about the same thing and discuss its pros and cons more easily than just describing the idea verbally. Motion comps tend to be more useful earlier in the design process when you want to focus on the motion without worrying about the underlying structure or code yet. Motion comps also be great when you want to try something completely new. Some folks prefer motion comps because the tools for making them feel more familiar to them which means they can work faster. Prototypes are most useful for animations that rely heavily on interaction. (Getting the timing right for interactions can be tough without the interaction part sometimes.) Prototypes can also be helpful to investigate and optimize performance if that’s a specific concern. Give them a try Whichever deliverables you choose to highlight your animation decisions, including them in your design reviews, critiques, or other design discussions will help you make better UI animation choices. More discussion around UI animation ideas during the design phase means greater buy-in, more room for iteration, and higher quality UI animations in your designs. Why not give them a try for your next project? 2017 Val Head valhead 2017-12-08T00:00:00+00:00 https://24ways.org/2017/stop-leaving-animation-to-the-last-minute/ design
301 Stretching Time Time is valuable. It’s a precious commodity that, if we’re not too careful, can slip effortlessly through our fingers. When we think about the resources at our disposal we’re often guilty of forgetting the most valuable resource we have to hand: time. We 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. It doesn’t matter if we’re rich or we’re 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. I believe we can ‘stretch’ time, ensuring we make the most of every second and maximising the opportunities that time affords us. Through a combination of ‘Structured Procrastination’ and ‘Focused Finishing’ 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’s required. A win win, I’m sure you’ll agree. Structured Procrastination I’m a terrible procrastinator. I used to think that was a curse – “Why didn’t I just get started earlier?” – over time, however, I’ve started to see procrastination as a valuable tool if it is used in a structured manner. Don Norman refers to procrastination as ‘late binding’ (a term I’ve happily hijacked). As he argues, in Why Procrastination Is Good, late binding (delay, or procrastination) offers many benefits: Delaying decisions until the time for action is beneficial… it provides the maximum amount of time to think, plan, and determine alternatives. We live in a world that is constantly changing and evolving, as such the best time to execute is often ‘just in time’. By delaying decisions until the last possible moment we can arrive at solutions that address the current reality more effectively, resulting in better outcomes. Procrastination isn’t 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 ‘prime the brain’. As 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. By 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’re working on and, perhaps, discover other elements that will serve you well in future tasks. When 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 – if not useful for this article – would serve me well in the future. Ron Burgundy summarises this neatly: Procrastinator? No. I just wait until the last second to do my work because I will be older, therefore wiser. An ‘older, therefore wiser’ mind is a good thing. We’re incredibly fortunate to live in a world where we have a wealth of information at our fingertips. Don’t 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. Deadlines 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. Like everyone I’ll 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. At this point we need to focus. Focused Finishing We live in an age of constant distraction. Smartphones are both a blessing and a curse, they keep us connected, but if we’re not careful the constant connection they provide can interrupt our flow. When a deadline is accelerating towards us it’s important to set aside the distractions and carve out a space where we can work in a clear and focused manner. When it’s time to finish, it’s important to avoid context switching and focus. All those micro-interactions throughout the day – triaging your emails, checking social media and browsing the web – can get in the way of you hitting your deadline. At this point, they’re distractions. Chunking tasks and managing when they’re scheduled can improve your productivity by a surprising order of magnitude. At this point it’s important to remove distractions which result in ‘attention residue’, where your mind is unable to focus on the current task, due to the mental residue of other, unrelated tasks. By focusing on a single task in a focused manner, it’s possible to minimise the negative impact of attention residue, allowing you to maximise your performance on the task at hand. Cal Newport explores this in his excellent book, Deep Work, which I would highly recommend reading. As he puts it: Efforts to deepen your focus will struggle if you don’t simultaneously wean your mind from a dependence on distraction. To help you focus on finishing it’s helpful to set up a work-focused environment that is purposefully free from distractions. There’s a time and a place for structured procrastination, but – equally – there’s a time and a place for focused finishing. The French term ‘mise en place’ is drawn from the world of fine cuisine – I discovered it when I was procrastinating – and it’s applicable in this context. The term translates as ‘putting in place’ or ‘everything in its place’ and it refers to the process of getting the workplace ready before cooking. Just like a professional chef organises their utensils and arranges their ingredients, so too can you. Thanks to the magic of multiple users on computers, it’s possible to create a separate user on your computer – without access to email and other social tools – so that you can switch to that account when you need to focus and hit the deadline. Another, less technical way of achieving the same result – depending, of course, upon your line of work – is to close your computer and find some non-digital, unconnected space to work in. The goal is to carve out time to focus so you can finish. As Newport states: If you don’t produce, you won’t thrive – no matter how skilled or talented you are. Procrastination is fine, but only if it’s accompanied by finishing. Create the space to finish and you’ll enjoy the best of both worlds. In closing… There 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. By combining the processes of ‘Structured Procrastination’ and ‘Focused Finishing’ 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. Make the most of your time, you only get so much. Use every second productively and you’ll be thankful that you did. Don’t waste your time, once it’s gone, it’s gone… and you can never get it back. 2016 Christopher Murphy christophermurphy 2016-12-21T00:00:00+00:00 https://24ways.org/2016/stretching-time/ process
216 Styling Components - Typed CSS With Stylable There’s been a lot of debate recently about how best to style components for web apps so that styles don’t accidentally ‘leak’ out of the component they’re meant for, or clash with other styles on the page. Elaborate 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. Others just give up on CSS and put all their styles in JavaScript. Now, I’m 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’t be as fast as using real CSS, and in any case, this requires waiting for JS to download, parse, execute then render the styles. There’s 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? A recent thread on Twitter asked “What’s your biggest gripe with CSS-in-JS?”, and the replies were illuminating: “Always having to remember to camelCase properties then spending 10min pulling hair out when you do forget”, “the cryptic domain-specific languages that each of the frameworks do just ever so slightly differently”, “When I test look and feel in browser, then I copy paste from inspector, only to have to re-write it as a JSON object”, “Lack of linting, autocomplete, and css plug-ins for colors/ incrementing/ etc”. If you’re a developer, and you’re 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. Some 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’t 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’ autocompletion, and which could be pre-processed at build time to valid, cross-browser, static CSS? After a few months and a few proofs of concept later (drumroll), yes – we could! We call it Stylable. Introducing Stylable Stylable 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’s quite a bit to it, and this is a short article, so let’s look at the basic concepts. Components all the way down Stylable is designed for component-based systems. Imagine you have a Gallery component. Within that, there is a Navigation component (for example, containing a ‘next’, ‘previous’, ‘show all thumbnails’, and ‘show all albums’ 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 — 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. Firstly, 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, <div className="jingle bells" /> might be re-written as <div class="header183--jingle header183--bells"></div>. So far, so BEM-like (albeit without the headache of remembering a convention). But what else can it do? Custom pseudo-elements An 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’s see the guts of a simple JSX button component in the file button.jsx: render () { return ( <button> <span className="icon" /> <span className="label">Submit</span> </button> ); } (Note:className is the JSX way of setting a class on an element; this example uses React, but Stylable itself is framework-agnostic.) I style it using a Stylable stylesheet (the .st.css suffix tells the preprocessor to process this file): /* button.st.css */ /* note that the root class is automatically placed on the root HTML element by Stylable React integration */ .root { background: #b0e0e6; } .icon { display: block; height: 2em; background-image: url('./assets/btnIcon.svg'); } .label { font-size: 1.2em; color: rgba(81, 12, 68, 1.0); } Note that Stylable allows all the CSS that you know and love to be included. As Drew Powers wrote in his review: with Stylable, you get CSS, and every part of CSS. This seems like a “duh” observation, but this is significant if you’ve ever battled with a CSS-in-JS framework over a lost or “hacky” implementation of a basic CSS feature. I can import my Button component into another component - this time, panel.jsx: /* panel.jsx */ import * as React from 'react'; import {properties, stylable} from 'wix-react-tools'; import {Button} from '../button'; import style from './panel.st.css'; export const Panel = stylable(style)(() => ( <div> <Button className="cancelBtn" /> </div> )); In panel.st.css: /* panel.st.css */ :import { -st-from: './button.st.css'; -st-default: Button; } /* cancelBtn is of type Button */ .cancelBtn { -st-extends: Button; background: cornflowerblue; } /* targets the label of <Button className="cancelBtn" /> */ .cancelBtn::label { color: honeydew; font-weight: bold; } Here, we’re reaching into the Button component from the Panel component. Buttons that are not inside a Panel won’t be affected. We do this by extending the CSS concept of pseudo-elements. As MDN says “A CSS pseudo-element is a keyword added to a selector that lets you style a specific part of the selected element(s)”. We don’t use a descendant selector because the label isn’t part of the Panel component, it’s part of the Button component. This syntax allows us three important features: Piercing the Shadow Boundary Because, 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’s not allowed in CSS, albeit with the note “A future version of this specification may allow multiple pseudo-elements per selector”. So I asked the CSS Working Group and was told “we intend to only allow specific combinations”, so we feel this extension to CSS is in the spirit of the language. While we’re 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. Structure-agnostic The second totez-groovy™ feature of Stylable’s pseudo-element syntax is that you don’t have to care about the internal structure of the component whose boundary you’re 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. Code completion When we started writing Stylable, our objective was to do for CSS what TypeScript does for JavaScript. Wikipedia says Challenges 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 … [with] static typing that enables static language analysis, which facilitates tooling and IDE support. Similarly, 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 ! An action replay of Visual Studio Code offering code completion etc, filmed in super StyloVision. Pseudo-classes for state Stylable 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. We do this by declaring the possible custom states on the component: /* Gallery.st.css */ .root { -st-states: toggled, loading; } .root:toggled { color: red; } .root:loading { color: green; } .root:loading:toggled { color: blue; } The -st-states “property” 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’s therefore valid CSS syntax and IDEs won’t flag it as an error, but is removed at build time. Remember, Stylable resolves to flat, valid, cross-browser CSS. As with plain CSS, it can’t 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 — by default, by setting a data-* attribute. And there’s more! Hopefully, I’ve 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’t 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. We made Stylable because we ♥ CSS. But there’s a practical reason, too. As James Kyle, a core team member of Yarn, Babel and TC39 (the JavaScript Standards Technical Committee), said of Styable “pretty sure all the CSS-in-JS libraries just died for me”, explaining CSS could be perfectly static if given the right tools, that’s exactly what stylable does. It gives you the tools you need in CSS so that you don’t need to do a bunch of dynamic shit in JS. Making it static is a huge performance win. Wix 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’s open-sourced so you, dear Reader, can try it out and use it too. There’s a Stylable boilerplate based on create-react-app to get you started (more integrations are in the pipeline). Happy Hols ‘n’ Hugz from the Stylable team: Bruce, Arnon, Tom, Ido. Read more Stylable documentation centre Stylable on Twitter A nice picture of a hedgehog 2017 Bruce Lawson brucelawson 2017-12-09T00:00:00+00:00 https://24ways.org/2017/styling-components-typed-css-with-stylable/ code
140 Styling hCards with CSS There are plenty of places online where you can learn about using the hCard microformat to mark up contact details at your site (there are some resources at the end of the article). But there’s not yet been a lot of focus on using microformats with CSS. So in this installment of 24 ways, we’re going to look at just that – how microformats help make CSS based styling simpler and more logical. Being rich, quite complex structures, hCards provide designers with a sophisticated scaffolding for styling them. A recent example of styling hCards I saw, playing on the business card metaphor, was by Andy Hume, at http://thedredge.org/2005/06/using-hcards-in-your-blog/. While his approach uses fixed width cards, let’s take a look at how we might style a variable width business card style for our hCards. Let’s take a common hCard, which includes address, telephone and email details <div class="vcard"> <p class="fn org">Web Directions North <a href="http://suda.co.uk/projects/X2V/get-vcard.php?uri=http://north.webdirections.org/contact/"> <img src="images/vcard-add.png" alt="download vcard icon"></a> </p> 1485 Laperrière Avenue Ottawa ON K1Z 7S8 Canada Phone/Fax: Work: 61 2 9365 5007 Email: info@webdirections.org We’ll be using a variation on the now well established “sliding doors” technique (if you create a CSS technique, remember it’s very important to give it a memorable name or acronym, and bonus points if you get your name in there!) by Douglas Bowman, enhanced by Scott Schiller (see http://www.schillmania.com/projects/dialog/,) which will give us a design which looks like this The technique, in a nutshell, uses background images on four elements, two at the top, and two at the bottom, to add each rounded corner. We are going to make this design “fluid” in the sense that it grows and shrinks in proportion with the size of the font that the text of the element is displayed with. This is sometimes referred to as an “em driven design” (we’ll see why in a moment). To see how this works in practice, here’s the same design with the text “zoomed” up in size and the same design again, when we zoom the text size down By the way, the hCard image comes from Chris Messina, and you can download it and other microformat icons from the microformats wiki. Now, with CSS3, this whole task would be considerably easier, because we can add multiple background images to an element, and border images for each edge of an element. Safari, version 1.3 up, actually supports multiple background images, but sadly, it’s not supported in Firefox 1.5, or even Firefox 2.0 (let’s not mention IE7 eh?). So it’s probably too little supported to use now. So instead we’ll use a technique that only involves CSS2, and works in pretty much any browser. Very often, developers add div or span elements as containers for these background images, and in fact, if you visit Scott Shiller’s site, that’s what he has done there. But if at all possible we shouldn’t be adding any HTML simply for presentational purposes, even if the presentation is done via CSS. What we can do is to use the HTML we have already, as much as is possible, to add the style we want. This can take some creative thinking, but once you get the hang of this approach it becomes a more natural way of using HTML compared with simply adding divs and spans at will as hooks for style. Of course, this technique isn’t always simple, and in fact sometimes simply not possible, requiring us to add just a little HTML to provide the “hooks” for CSS. Let’s go to work The first step is to add a background image to the whole vCard element. We make this wide enough (for example 1000 or more pixels) and tall enough that no matter how large the content of the vCard grows, it will never overflow this area. We can’t simply repeat the image, because the top left corner will show when the image repeats. We add this as the background image of the vCard element using CSS. While we are at it, let’s give the text a sans-serif font, some color so that it will be visible, and stop the image repeating. .vcard { background-image: url(images/vcardfill.png); background-repeat: no-repeat; color: #666; font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif; } Which in a browser, will look something like this. Next step we need to add the top right hand corner of the hCard. In keeping with our aim of not adding HTML simply for styling purposes, we want to use the existing structure of the page where possible. Here, we’ll use the paragraph of class fn and org, which is the first child element of the vcard element. <p class="fn org">Web Directions Conference Pty Ltd <img src="images/vcard-add.png" alt="download vcard icon"></p> Here’s our CSS for this element .fn { background-image: url(images/topright.png); background-repeat: no-repeat; background-position: top right; padding-top: 2em; font-weight: bold; font-size: 1.1em; } Again, we don’t want it to repeat, but this time, we’ve specified a background position for the image. This will make the background image start from the top, but its right edge will be located at the right edge of the element. I also made the font size a little bigger, and the weight bold, to differentiate it from the rest of the text in the hCard. Here’s the image we are adding as the background to this element. So, putting these two CSS statements together we get We specified a padding-top of 2em to give some space between the content of the fn element and the edge of the fn element. Otherwise the top of the hCard image would be hard against the border. To see this in action, just remove the padding-top: 2em; declaration and preview in a browser. So, with just two statements, we are well under way. We’ve not even had to add any HTML so far. Let’s turn to the bottom of the element, and add the bottom border (well, the background image which will serve as that border). Now, which element are we going to use to add this background image to? OK, here I have to admit to a little, teensie bit of cheating. If you look at the HTML of the hCard, I’ve grouped the email and telephone properties into a div, with a class of telecommunications. This grouping is not strictly requred for our hCard. <div class="telecommunications"> <p class="tel">Phone/Fax: <span class="tel"><span class="type">Work</span>: <span class="value">61 2 9365 5007</span></p> <p class="email">Email: <a class="value" href="mailto:info@webdirections.org">info@webdirections.org</a></p> </div> Now, I chose that class name because that is what the vCard specification calls this group of properties. And typically, I do tend to group together related elements using divs when I mark up content. I find it makes the page structure more logical and readable. But strictly speaking, this isn’t necessary, so you may consider it cheating. But my lesson in this would be, if you are going to add markup, try to make it as meaningful as possible. As you have probably guessed by now, we are going to add one part of the bottom border image to this element. We’re going to add this image as the background-image. Again, it will be a very wide image, like the top left one, so that no matter how wide the element might get, the background image will still be wide enough. Now, we’ll need to make this image sit in the bottom left of the element we attach it to, so we use a backgound position of left bottom (we put the horizontal position before the vertical). Here’s our CSS statement for this .telecommunications { background-image: url(images/bottom-left.png); background-repeat: no-repeat; background-position: left bottom; margin-bottom: 2em; } And that will look like this Not quite there, but well on the way. Time for the final piece in the puzzle. OK, I admit, I might have cheated just a little bit more in this step. But like the previous step, all valid, and (hopefully) quite justifiable markup. If we look at the HTML again, you’ll find that our email address is marked up like this <p class="email">Email: <a class="value" href="mailto:info@webdirections.org">info@webdirections.org</a></p> Typically, in hCard, the value part of this property isn’t required, and we could get away with <a class="email" href="mailto:info@webdirections.org">info@webdirections.org</a> The form I’ve used, with the span of class value is however, perfectly valid hCard markup (hard allows for multiple email addresses of different types, which is where this typically comes in handy). Why have I gone to all this trouble? Well, when it came to styling the hCard, I realized I needed a block element to attach the background image for the bottom right hand corner to. Typically the last block element in the containing element is the ideal choice (and sometimes it’s possible to take an inline element, for example the link here, and use CSS to make it a block element, and attach it to that, but that really doesn’t work with this design). So, if we are going to use the paragraph which contains the email link, we need a way to select it exclusively, which means that with CSS2 at least, we need a class or id as a hook for our CSS selector (in CSS3 we could use the last-child selector, which selects the last child element of a specified element, but again, as last child is not widely supported, we won’t rely on it here.) So, the least worst thing we could do is take an existing element, and add some reasonably meaningful markup to it. That’s why we gave the paragraph a class of email, and the email address a class of value. Which reminds me a little of a moment in Hamlet The lady doth protest too much, methinks OK, let’s get back to the CSS. We add the bottom right corner image, positioning it in the bottom right of the element, and making sure it doesn’t repeat. We also add some padding to the bottom, to balance out the padding we added to the top of the hCard. p.email { background-image: url(images/bottom-right.png); background-position: right bottom; background-repeat: no-repeat; padding-bottom: 2em; } Which all goes to make our hCard look like this It just remains for us to clean up a little. Let’s start from the top. We’ll float the download image to the right like this .vcard img { float: right; padding-right: 1em; margin-top: -1em } See how we didn’t have to add a class to style the image, we used the fact that the image is a descendent of the vcard element, and a descendent selector. In my experience, the very widely supported, powerful descendent selector is one of the most underused aspects of CSS. So if you don’t use it frequently, look into it in more detail. We added some space to the right of the image, and pulled it up a bit closer to the top of the hCard, like this We also want to add some whitespace between the edge of the hCard and the text. We would typically add padding to the left of the containing element, (in this case the vcard element) but this would break our bottom left hand corner, like this That’s because the div element we added this bottom left background image to would be moved in by the padding on its containing element. So instead, we add left margin to all the paragraphs in the hCard .vcard p { margin-left: 1em; } (there is the descendent selector again – it is the swiss army knife of CSS) Now, we’ve not yet made the width of the hCard a function of the size of the text inside it (or “em driven” as we described it earlier). We do this by giving the hCard a width that is specified in em units. Here we’ll set a width of say 28em, which makes the hCard always roughly as wide as 28 characters (strictly speaking 28 times the width of the letter capital M). So the statement for our containing vcard element becomes .vcard { background-image: url(images/vcardfill.png); background-repeat: no-repeat; color: #666; font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif; width: 28em; } and now our element will look like this We’ve used almost entirely the existing HTML from our original hCard (adding just a little, and trying as much as possible to keep that additional markup meaningful), and just 6 CSS statements. Holiday Bonus – a downloadable vCard Did you notice this part of the HTML <a href="http://suda.co.uk/projects/X2V/get-vcard.php?uri=http://north.webdirections.org/contact/"> <img src="images/vcard-add.png" alt="download vcard icon"></a> What’s with the odd looking url <a href="http://suda.co.uk/projects/X2V/get-vcard.php?uri=http://north.webdirections.org/contact/" If you click the link, X2V, a nifty web service from Brian Suda, grabs the page at the URL, and if it finds a hCard, converts it to a vCard, and depending on how your system is setup, automatically downloads it and adds it to your address book (Mac OS X) or prompts you whether you’d like to save the vCard and add it to whatever application is the default vCard handler on your system. What X2V does is take the actual HTML of your hCard, and with the magic of XSLT, converts it to a vCard. So, by simply marking up contact details using hCard, and adding a link like this, you automatically get downloadable vCard – and if you change your contact details, and update the hCard, there’s no vCard file to update as well. Technorati also have a similar service at http://technorati.com/contact so you might want to use that if you expect any kind of load, as they can probably afford the bandwidth more than Brian! If you want to play with the HTML and CSS for this design, the code and images can be downloaded. Hope you enjoyed this, and found it useful. If so, you might like to check out my microformats focussed blog, or get along to Web Directions North, where I’ll be speaking along with Dan Cederholmn and Tantek Çelik in a 2 hour session focussed solely on microformats. And keep an eye out for my microformats book, from which this article has been adapted, coming in the spring of 2007. A happy festive season, and all the best for 2007 John Some hCard links The hCard entry at microformats.org The hCard Creator The hCard cheatsheet The hCard FAQ Ideas for authoring hCards Microfomatique – a blog about microformats Web Directions North – featuring a full 2 hour focussed microformats session 2006 John Allsopp johnallsopp 2006-12-14T00:00:00+00:00 https://24ways.org/2006/styling-hcards-with-css/ design
284 Subliminal User Experience The term ‘user experience’ is often used vaguely to quantify common elements of the interaction design process: wireframing, sitemapping and so on. UX undoubtedly involves all of these principles to some degree, but there really is a lot more to it than that. Good UX is characterized by providing the user with constant feedback as they step through your interface. It means thinking about and providing fallbacks and error resolutions in even the rarest of scenarios. It’s about omitting clutter to make way for the necessary, and using the most fundamental of design tools to influence a user’s path. It means making no assumptions, designing right down to the most distinct details and going one step further every single time. In many cases, good UX is completely subliminal. There are simple tools and subtleties we can build into our products to enhance the overall experience but, in order to do so, we really have to step beyond where we usually draw the line on what to design. The purpose of this article is not to provide technical how-tos, as the functionality is, in most cases, quite simple and could be implemented in a myriad of ways. Rather, it will present a handful of ideas for enhancing the experience of an interface at a deeper level of design without relying on the container. We’ll cover three elements that should get you thinking in the right mindset: progress activity and post-active states pseudo-class preloading buttons and their (mis)behaviour Progress activity and the post-active state We’ve long established that we can’t control the devices our products are viewed on, which browser they’ll run in or what connection speed will be used to access them. We accept this all as factual, so why is it so often left to the browser to provide feedback to the user when an event is triggered or an error encountered? The browser isn’t part of the interface — it’s merely a container. A simple, visual recognition of your users’ activity may be all it takes to make or break the product. Let’s begin with a commonly overlooked case: progress activity. A user moves their cursor over a hyperlink or button, which is clearly defined as one by the visual language of your content. Upon doing so, they trigger the :hover state to confirm this element is indeed interactive. So far, so good. What happens next is where it starts to fall apart: the user hits this link, presumably triggering an :active state, which is then returned to the normal state upon release. And then what? From this point on, your user is in limbo. The link has fallen back to either its regular or :visited state. You’ve effectively abandoned them and are relying entirely on the browser they’re using to communicate that something is happening. This poses quite a few problems: The user may lose focus of what they were doing. There is little consistency between progress indication in browsers. The user may not even notice that their action has been acknowledged. How many times have one or more of these events happened to you due to a lack of communication from the interface? Think about the differences between Safari and Chrome in this area — two browsers that, when compared to each other, are relatively similar in nature, though this basic feature differs in execution. Like all aspects of designing the user experience, there is no one true way to fix this problem, but we can introduce details that many users will unconsciously appreciate. Consider the basic loading indicator. It’s nothing new — in fact, some would argue it’s quite a cliché. However, whether using a spinning wheel or a progress bar, a gif or JavaScript, or something more sophisticated, these simple tools create an illusion of movement, progress and activity. Depending on the implementation, progress indication graphics can significantly increase a user’s perception of the speed in which an event is taking place. Combine this with a cursor change and a lock over the element to prevent double-clicking or reloading, and your chances of keeping your user’s valuable attention have significantly increased. Demo: Progress activity and the post-active state This same logic applies to all aspects of defaulting in a browser, from micro-elements like this up to something as simple as a 404 page. The difference in a user’s reaction to hitting the default Apache 404 and a hand-crafted, branded page are phenomenal and there are no prizes for guessing which one they’re more likely to exit from. Pseudo-class preloading Another detail that it pays well to look after is the use and abuse of the :hover element and, more importantly, the content revealed by it. Chances are you’re using the :hover pseudo-class somewhere in almost every screen you create. If content is being revealed on :hover and that content takes some time to load, there will inevitably be a delay the first time it is initiated. It appears tacky and half-finished when a tooltip or drop-down loads instantly, only to have its background or supporting elements follow through a second or two later. So, let’s preload the elements we know we’ll need. A very simple application of this would be to load each file into the default state of a visible element and offset them by a large number. This ensures our elements have loaded and are ready if and when they need to be displayed. element { background: url(path/to/image.jpg) -9999em -9999em no-repeat; } element .tooltip { display: none; } element:hover .tooltip { display: block; background: url(path/to/image.jpg) 0 0; } Background images are just one example. Of course, the same logic can apply to any form of revealed content. Using a sprite graphic can also be a clever — albeit tedious — method for achieving the same goal, so if you’re using a sprite, preloading in this way may not be necessary The differences between preloading and not can only be visualized properly with an actual demonstration. Demo: Preloading revealed content Buttons and their (mis)behaviour Almost all of the time, a button serves just one purpose: to be clicked (or tapped). When a button’s pressed, therefore, if anything other than triggering the desired event occurs, a user naturally becomes frustrated. I often get funny looks when talking about this, but designing the details of a button is something I consider essential. It goes without saying that a button should always visually recognise :hover and :active states. We can take that one step further and disable some actions that get in the way of pressing the button. It’s rare that a user would ever want to select and use the text on a button, so let’s cleanly disable it: element { -moz-user-select: -moz-none; -webkit-user-select: none; user-select: none; } If the button is image-based or contains an image, we could also disable user dragging to make sure the image element stays locked to the button: element { -moz-user-drag: -moz-none; -webkit-user-drag: none; user-drag: none; } Demo: A more usable button Disabling global features like this should be done with utmost caution as it’s very easy to cross the line between enhancement and friction. Cases where this is acceptable are very rare, but it’s a good trick to keep in mind nevertheless. Both Apple’s iCloud and Metalab’s Flow applications use these tools appropriately and to great extent. You could argue that the visual feedback of having the text selected or image dragged when a user mis-hits the button is actually a positive effect, informing the user that their desired action did not work. However, covering for human error should be a designer’s job, not that of our users. We can (almost) ensure it does work for them by accommodating for errors like this in most cases. Final thoughts Designing to this level of detail can seem obsessive, but as a designer and user of many interfaces and applications, I believe it can be the difference between a good user experience and a great one. The samples you’ve just seen are only a fraction of the detail we can design for. Keep in mind that the demonstrations, code and methods above outline just one way to do this. You may not agree with all of these processes or have the time and desire to consider them, but one fact remains: it’s not the technology, or the way it’s done that’s important — it’s the logic and the concept of designing everything. 2011 Chris Sealey chrissealey 2011-12-03T00:00:00+00:00 https://24ways.org/2011/subliminal-user-experience/ ux
261 Surviving—and Thriving—as a Remote Worker Remote work is hot right now. Many people even say that remote work is the future. Why should a company limit itself to hiring from a specific geographic location when there’s an entire world of talent out there? I’ve been working remotely, full-time, for five and a half years. I’ve reached the point where I can’t even fathom working in an office. The idea of having to wake up at a specific time and commute into an office, work for eight hours, and then commute home, feels weirdly anachronistic. I’ve grown attached to my current level of freedom and flexibility. However, it took me a lot of trial and error to reach success as a remote worker — and sometimes even now, I slip up. Working remotely requires a great amount of discipline, independence, and communication. It can feel isolating, especially if you lean towards the more extroverted side of the social spectrum. Remote working isn’t for everyone, but most people, with enough effort, can make it work — or even thrive. Here’s what I’ve learned in over five years of working remotely. Experiment with your environment As a remote worker, you have almost unprecedented control of your environment. You can often control the specific desk and chair you use, how you accessorize your home office space — whether that’s a dedicated office, a corner of your bedroom, or your kitchen table. (Ideally, not your couch… but I’ve been there.) Hate fluorescent lights? Change your lightbulbs. Cover your work area in potted plants. Put up blackout curtains and work in the dark like a vampire. Whatever makes you feel most comfortable and productive, and doesn’t completely destroy your eyesight. Working remotely doesn’t always mean working from home. If you don’t have a specific reason you need to work from home (like specialized equipment), try working from other environments (which is especially helpful it you have roommates, or children). Cafes are the quintessential remote worker hotspot, but don’t just limit yourself to your favorite local haunt. More cities worldwide are embracing co-working spaces, where you can rent either a roaming spot or a dedicated desk. If you’re a social person, this is a great way to build community in your work environment. Most have phone rooms, so you can still take calls. Co-working spaces can be expensive, and not everyone has either the extra income, or work-provided stipend, to work from one. Local libraries are also a great work location. They’re quiet, usually have free wi-fi, and you have the added bonus of being able to check out books after work instead of, ahem, spending too much money on Kindle books. (I know most libraries let you check out ebooks, but reader, I am impulsive and impatient person. When I want a book now, I mean now.) Just be polite — make sure your headphones don’t leak, and don’t work from a library if you have a day full of calls. Remember, too, that you don’t have to stay in the same spot all day. It’s okay to go out for lunch and then resume work from a different location. If you find yourself getting restless, take a walk. Wash some dishes while you mull through a problem. Don’t force yourself to sit at your desk for eight hours if that doesn’t work for you. Set boundaries If you’re a workaholic, working remotely can be a challenge. It’s incredibly easy to just… work. All the time. My work computer is almost always with me. If I remember at 11pm that I wanted to do something, there’s nothing but my own willpower keeping me from opening up my laptop and working until 2am. Some people are naturally disciplined. Some have discipline instilled in them as children. And then some, like me, are undisciplined disasters that realize as adults that wow, I guess it’s time to figure this out, eh? Learning how to set boundaries is one of the most important lessons I’ve learned working remotely. (And honestly, it’s something I still struggle with). For a long time, I had a bad habit of waking up, checking my phone for new Slack messages, seeing something I need to react to, and then rolling over to my couch with my computer. Suddenly, it’s noon, I’m unwashed, unfed, starting to get a headache, and wondering why suddenly I hate all of my coworkers. Even when I finally tear myself from my computer to shower, get dressed, and eat, the damage is done. The rest of my day is pretty much shot. I recently had a conversation with a coworker, in which she remarked that she used to fill her empty time with work. Wake up? Scroll through Slack and email before getting out of bed. Waiting in line for lunch? Check work. Hanging out on her couch in the evening? You get the drift. She was only able to break the habit after taking a three month sabbatical, where she had no contact with work the entire time. I too had just returned from my own sabbatical. I took her advice, and no longer have work Slack on my phone, unless I need it for an event. After the event, I delete it. I also find it too easy to fill empty time with work. Now, I might wake up and procrastinate by scrolling through other apps, but I can’t get sucked into work before I’m even dressed. I’ve gotten pretty good at forbidding myself from working until I’m ready, but building any new habit requires intentionality. Something else I experimented with for a while was creating a separate account on my computer for social tasks, so if I wanted to hang out on my computer in the evening, I wouldn’t get distracted by work. It worked exceptionally well. The only problems I encountered were technical, like app licensing and some of my work proxy configurations. I’ve heard other coworkers have figured out ways to work through these technical issues, so I’m hoping to give it another try soon. You might noticed that a lot of these ideas are just hacks for making myself not work outside of my designated work times. It’s true! If you’re a more disciplined person, you might not need any of these coping mechanisms. If you’re struggling, finding ways to subvert your own bad habits can be the difference between thriving or burning out. Create intentional transition time I know it’s a stereotype that people who work from home stay in their pajamas all day, but… sometimes, it’s very easy to do. I’ve found that in order to reach peak focus, I need to create intentional transition time. The most obvious step is changing into different clothing than I woke up in. Ideally, this means getting dressed in real human clothing. I might decide that it’s cold and gross out and I want to work in joggers and a hoody all day, but first, I need to change out of my pajamas, put on a bra, and then succumb to the lure of comfort. I’ve found it helpful to take similar steps at the end of my day. If I’ve spent the day working from home, I try to end my day with something that occupies my body, while letting my mind unwind. Often, this is doing some light cleaning or dinner prep. If I try to go straight into another mentally heavy task without allowing myself this transition time, I find it hard to context switch. This is another reason working from outside your home is advantageous. Commutes, even if it’s a ten minute walk down the road, are great transition time. Lunch is a great transition time. You can decompress between tasks by going out for lunch, or cooking and eating lunch in your kitchen — not next to your computer. Embrace async If you’re used to working in an office, you’ve probably gotten pretty used to being able to pop over to a colleague’s desk if you need to ask a question. They’re pretty much forced to engage with you at that point. When you’re working remotely, your coworkers might not be in the same timezone as you. They might take an hour to finish up a task before responding to you, or you might not get an answer for your entire day because dangit Gary’s in Australia and it’s 3am there right now. For many remote workers, that’s part of the package. When you’re not co-located, you have to build up some patience and tolerance around waiting. You need to intentionally plan extra time into your schedule for waiting on answers. Asynchronous communication is great. Not everyone can be present for every meeting or office conversation — and the same goes for working remotely. However, when you’re remote, you can read through your intranet messages later or scroll back a couple hours in Slack. My company has a bunch of internal blogs (“p2s”) where we record major decisions and hold asynchronous conversations. I feel like even if I missed a meeting, or something big happened while I was asleep, I can catch up later. We have a phrase — “p2 or it didn’t happen.” Working remotely has made me a better communicator largely because I’ve gotten into the habit of making written updates. I’ve also trained myself to wait before responding, which allows me to distance myself from what could potentially be an emotional reaction. (On the internet, no one can see you making that face.) Having the added space that comes from not being in the same physical location with somebody else creates an opportunity to rein myself in and take the time to craft an appropriate response, without having the pressure of needing to reply right meow. Lean into it! (That said, if you’re stuck, sometimes the best course of action is to hop on a video call with someone and hash out the details. Use the tools most appropriate for the problem. They invented Zoom for a reason.) Seek out social opportunities Even introverts can feel lonely or isolated. When you work remotely, there isn’t a built-in community you’re surrounded by every day. You have to intentionally seek out social opportunities that an office would normally provide. I have a couple private Slack channels where I can joke around with work friends. Having that kind of safe space to socialize helps me feel less alone. (And, if the channels get too noisy, I can mute them for a couple hours.) Every now and then, I’ll also hop on a video call with some work friends and just hang out for a little while. It feels great to actually see someone laugh. If you work from a co-working space, that space likely has events. My co-working space hosts social hours, holiday parties, and sometimes even lunch-and-learns. These events are great opportunities for making new friends and forging professional connections outside of work. If you don’t have access to a co-working space, your town or city likely has meetups. Create a Meetup.com account and search for something that piques your interest. If you’ve been stuck inside your house for days, heads-down on a hard deadline, celebrate by getting out of the house. Get coffee or drinks with friends. See a show. Go to a religious service. Take a cooking class. Try yoga. Find excuses to be around someone other than your cats. When you can’t fall back on your work to provide community, you need to build your own. These are tips that I’ve found help me, but not everyone works the same way. Remember that it’s okay to experiment — just because you’ve worked one way, doesn’t mean that’s the best way for you. Check in with yourself every now and then. Are you happy with your work environment? Are you feeling lonely, down, or exhausted? Try switching up your routine for a couple weeks and jot down how you feel at the end of each day. Look for patterns. You deserve to have a comfortable and productive work environment! Hope to see you all online soon 🙌 2018 Mel Choyce melchoyce 2018-12-09T00:00:00+00:00 https://24ways.org/2018/thriving-as-a-remote-worker/ process
328 Swooshy Curly Quotes Without Images The problem Take a quote and render it within blockquote tags, applying big, funky and stylish curly quotes both at the beginning and the end without using any images – at all. The traditional way Feint background images under the text, or an image in the markup housed in a little float. Often designers only use the opening curly quote as it’s just too difficult to float a closing one. Why is the traditional way bad? Well, for a start there are no actual curly quotes in the text (unless you’re doing some nifty image replacement). Thus with CSS disabled you’ll only have default blockquote styling to fall back on. Secondly, images don’t resize, so scaling text will have no affect on your graphic curlies. The solution Use really big text. Then it can be resized by the browser, resized using CSS, and even be restyled with a new font style if you fancy it. It’ll also make sense when CSS is unavailable. The problem Creating “Drop Caps” with CSS has been around for a while (Big Dan Cederholm discusses a neat solution in that first book of his), but drop caps are normal characters – the A to Z or 1 to 10 – and these can all be pulled into a set space and do not serve up a ton of whitespace, unlike punctuation characters. Curly quotes aren’t like traditional characters. Like full stops, commas and hashes they float within the character space and leave lots of dead white space, making it bloody difficult to manipulate them with CSS. Styles generally fit around text, so cutting into that character is tricky indeed. Also, all that extra white space is going to push into the quote text and make it look pretty uneven. This grab highlights the actual character space: See how this is emphasized when we add a normal alphabetical character within the span. This is what we’re dealing with here: Then, there’s size. Call in a curly quote at less than 300% font-size and it ain’t gonna look very big. The white space it creates will be big enough, but the curlies will be way too small. We need more like 700% (as in this example) to make an impression, but that sure makes for a big character space. Prepare the curlies Firstly, remove the opening “ from the quote. Replace it with the opening curly quote character entity “. Then replace the closing “ with the entity reference for that, which is ”. Now at least the curlies will look nice and swooshy. Add the hooks Two reasons why we aren’t using :first-letter pseudo class to manipulate the curlies. Firstly, only CSS2-friendly browsers would get what we’re doing, and secondly we need to affect the last “letter” of our text also – the closing curly quote. So, add a span around the opening curly, and a second span around the closing curly, giving complete control of the characters: <blockquote><span class="bqstart">“</span>Speech marks. Curly quotes. That annoying thing cool people do with their fingers to emphasize a buzzword, shortly before you hit them.<span class="bqend">”</span></blockquote> So far nothing will look any different, aside form the curlies looking a bit nicer. I know we’ve just added extra markup, but the benefits as far as accessibility are concerned are good enough for me, and of course there are no images to download. The CSS OK, easy stuff first. Our first rule .bqstart floats the span left, changes the color, and whacks the font-size up to an exuberant 700%. Our second rule .bqend does the same tricks aside from floating the curly to the right. .bqstart { float: left; font-size: 700%; color: #FF0000; } .bqend { float: right; font-size: 700%; color: #FF0000; } That gives us this, which is rubbish. I’ve highlighted the actual span area with outlines: Note that the curlies don’t even fit inside the span! At this stage on IE 6 PC you won’t even see the quotes, as it only places focus on what it thinks is in the div. Also, the quote text is getting all spangled. Fiddle with margin and padding Think of that span outline box as a window, and that you need to position the curlies within that window in order to see them. By adding some small adjustments to the margin and padding it’s possible to position the curlies exactly where you want them, and remove the excess white space by defining a height: .bqstart { float: left; height: 45px; margin-top: -20px; padding-top: 45px; margin-bottom: -50px; font-size: 700%; color: #FF0000; } .bqend { float: right; height: 25px; margin-top: 0px; padding-top: 45px; font-size: 700%; color: #FF0000; } I wanted the blocks of my curlies to align with the quote text, whereas you may want them to dig in or stick out more. Be aware however that my positioning works for IE PC and Mac, Firefox and Safari. Too much tweaking seems to break the magic in various browsers at various times. Now things are fitting beautifully: I must admit that the heights, margins and spacing don’t make a lot of sense if you analyze them. This was a real trial and error job. Get it working on Safari, and IE would fail. Sort IE, and Firefox would go weird. Finished The final thing looks ace, can be resized, looks cool without styles, and can be edited with CSS at any time. Here’s a real example (note that I’m specifying Lucida Grande and then Verdana for my curlies): “Speech marks. Curly quotes. That annoying thing cool people do with their fingers to emphasize a buzzword, shortly before you hit them.” Browsers happy As I said, too much tweaking of margins and padding can break the effect in some browsers. Even now, Firefox insists on dropping the closing curly by approximately 6 or 7 pixels, and if I adjust the padding for that, it’ll crush it into the text on Safari or IE. Weird. Still, as I close now it seems solid through resizing tests on Safari, Firefox, Camino, Opera and IE PC and Mac. Lovely. It’s probably not perfect, but together we can beat the evil typographic limitations of the web and walk together towards a brighter, more aligned world. Merry Christmas. 2005 Simon Collison simoncollison 2005-12-21T00:00:00+00:00 https://24ways.org/2005/swooshy-curly-quotes-without-images/ business
321 Tables with Style It might not seem like it but styling tabular data can be a lot of fun. From a semantic point of view, there are plenty of elements to tie some style into. You have cells, rows, row groups and, of course, the table element itself. Adding CSS to a paragraph just isn’t as exciting. Where do I start? First, if you have some tabular data (you know, like a spreadsheet with rows and columns) that you’d like to spiffy up, pop it into a table — it’s rightful place! To add more semantics to your table — and coincidentally to add more hooks for CSS — break up your table into row groups. There are three types of row groups: the header (thead), the body (tbody) and the footer (tfoot). You can only have one header and one footer but you can have as many table bodies as is appropriate. Sample table example Inspiration Table Striping To improve scanning information within a table, a common technique is to style alternating rows. Also known as zebra tables. Whether you apply it using a class on every other row or turn to JavaScript to accomplish the task, a handy-dandy trick is to use a semi-transparent PNG as your background image. This is especially useful over patterned backgrounds. tbody tr.odd td { background:transparent url(background.png) repeat top left; } * html tbody tr.odd td { background:#C00; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader( src='background.png', sizingMethod='scale'); } We turn off the default background and apply our PNG hack to have this work in Internet Explorer. Styling Columns Did you know you could style a column? That’s right. You can add special column (col) or column group (colgroup) elements. With that you can add border or background styles to the column. <table> <col id="ingredients"> <col id="serve12"> <col id="serve24"> ... Check out the example. Fun with Backgrounds Pop in a tiled background to give your table some character! Internet Explorer’s PNG hack unfortunately only works well when applied to a cell. To figure out which background will appear over another, just remember the hierarchy: (bottom) Table → Column → Row Group → Row → Cell (top) The Future is Bright Once browser-makers start implementing CSS3, we’ll have more power at our disposal. Just with :first-child and :last-child, you can pull off a scalable version of our previous table with rounded corners and all — unfortunately, only Firefox manages to pull this one off successfully. And the selector the masses are clamouring for, nth-child, will make zebra tables easy as eggnog. 2005 Jonathan Snook jonathansnook 2005-12-19T00:00:00+00:00 https://24ways.org/2005/tables-with-style/ code
44 Taglines and Truisms To bring her good luck, “white rabbits” 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’t rely on it, especially when it comes to attracting new clients. The 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. Take a minute or two to look at your competitors’ websites. What’s the first thing that they say about themselves? Do they say that they “design delightful digital experiences,” “craft beautiful experiences” or “create remarkable digital experiences?” It’s 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. When 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. When 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:) The Ultimate Driving Machine Just Do It Don’t Leave Home Without It A clever tagline isn’t 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. I’m 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. A 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. It must also be meaningful to our brand and describe a truism, a truth that need not be a fact or statistic, but something that’s true about us, who we are, what we do and why that’s 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. I doubt that I need remind you who this tagline belongs to: There are some things money can’t buy. For everything else there’s MasterCard. That tagline was launched in 1997 by McCann-Erickson along with the “Priceless” campaign and it helped establish MasterCard as a friendlier credit card company, one with a sense of humour. MasterCard’s truism is that the things which really matter in life can’t be bought. They are worth more than anything that a monetary value can be applied to. In expressing that truism through the tagline, MasterCard’s advertising tells people to use not just any credit card, but their MasterCard, to pay for everything they buy. “Guinness is good for you” may have been a stretch, but “Good things come to those who wait” 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.) The fact that British Airways flies to more destinations than any other airline is their truism, and led their advertisers to the now famous tagline, “The world’s favourite airline.” At my company, Stuff & Nonsense, we’ve been thinking about taglines as we think about our position within an industry that seems full of companies who “design”, “craft”, and “create” “delightful”, “beautiful”, “remarkable digital experiences”. Much of what made us different has changed along with the type of work we’re interested in doing. Our work’s expanded beyond websites and now includes design for mobile and other media. It’s true we can’t know how or where it will be seen. The ways that we make it are flexible too as we’re careful not to become tied to particular tools or approaches. It’s also true that we’re a small team. One that’s 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’ve won business because of it and that it’s now a big part of our proposition. Our truism is that we’re flexible, “Fabulously flexible” as our tagline now expresses. And although we know that there may be other agencies who can be similarly flexible – after all, being flexible is not a unique selling proposition – only we do it so fabulously. As 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? Start 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’s meaningful, difficult to be argue with and, above all, uniquely yours. Answers The Ultimate Driving Machine (BMW) Just Do It (Nike) Don’t Leave Home Without It (American Express) 2014 Andy Clarke andyclarke 2014-12-23T00:00:00+00:00 https://24ways.org/2014/taglines-and-truisms/ business
300 Taking Device Orientation for a Spin When The Police sang “Don’t Stand So Close To Me” they weren’t 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’re there, we’re 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. But if you can’t beat them, join them. A brave new world A 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’t work in anything and went off disheartened into the corner for a bit of a sob. Turns 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—we’re still talking about browsers, after all. Now, of course they’re 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’re still trying to locate the documentation, right? Well, no! So 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’s find out. The Device Orientation API The phone-wavy API is more formally known as the DeviceOrientation Event Specification. It does a bunch of stuff that basically doesn’t 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. The 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. The API calls those pitch, roll and yaw values alpha, beta and gamma. Chocks away: window.addEventListener('deviceorientation', function(e) { console.log(e.alpha); console.log(e.beta); console.log(e.gamma); }); If 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. One important note Like may of these newfangled APIs, Device Orientation is only available over HTTPS. We’re not allowed to have too much fun without protection, so make sure that you’re working on a secure line. I’ve found a quick and easy way to share my local dev environment over TLS with my devices is to use an ngrok tunnel. ngrok http -host-header=rewrite mylocaldevsite.dev:80 ngrok will then set up a tunnel to your dev site with both HTTP and HTTPS URL options. You, of course, want the HTTPS option. Right, where were we? Make something to look at It’s all well and good having a bunch of numbers, but they’re 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’re not trying to be too clever here). Yeah, let’s just build one of those. Our 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 ‘window’ so that the part we want to show is visible. Here 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.) The details of the slider aren’t important (we’re 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 ‘alt-nazi’ or whatever). var position_image = function(percent) { var pos = (img_W / 100)*percent; img.style.transform = 'translate(-'+pos+'px)'; }; All this does is figure out what that percentage means in terms of the image width, and set the transform: translate(…); CSS property to move the image. (We use translate because it might be a bit faster to animate than left/right positioning.) Ok. 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’re done. (We’re so not done.) The maths bit If 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’ll note that the main value that is changing as we swing back and forth is the ‘alpha’ value. That’s the one we want to track. As our goal here is hey, these APIs are interesting and fun and not let’s build the world’s best panoramic image viewer, we’ll start by making a few assumptions and simplifications: When the image loads, we’ll centre the image and take the current nose-forward orientation reading as the middle. Moving left, we’ll track to the left of the image (lower percentage). Moving right, we’ll track to the right (higher percentage). If the user spins round, does cartwheels or loads the page then hops on a plane and switches earthly hemispheres, they’re on their own. Nose-forward When 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’t really matter to us, as we don’t know which direction the user might be facing in anyway — we just need to record that initial state and then use it to compare any new readings. var initial_position = null; window.addEventListener('deviceorientation', function(e) { if (initial_position === null) { initial_position = Math.floor(e.alpha); }; var current_position = initial_position - Math.floor(e.alpha); }); (I’m rounding down the values with Math.floor() to make debugging easier - we’ll take out the rounding later.) We get our initial position if it’s not yet been set, and then calculate the current position as a difference between the new value and the stored one. These values are weird One 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’d expect if you do a forward roll. What I’m 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’t see it. var rotation = current_position; if (current_position > 180) rotation = current_position-360; Which way up? Since we’re 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’s easy to account for when you know which way up the device is, but in true browser style, the API for that bit isn’t well supported. The best I can come up with is: var screen_portrait = false; if (window.innerWidth < window.innerHeight) { screen_portrait = true; } It works. Then we can use screen_portrait to branch our code: if (screen_portrait) { if (current_position > 180) rotation = current_position-360; } else { if (current_position < -180) rotation = 360+current_position; } Here’s the code in action so you can see the values for yourself. If you change screen orientation you’ll need to refresh the page (it’s a demo!). Limiting rotation Now, 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° to view a photo. Instead, we need to limit the range of movement to something like 60°-from-nose in either direction and normalise our values to pan the entire image across that 120° range. -60 would be full-left (0%) and 60 would be full-right (100%). If we set max_rotation = 60, that code ends up looking like this: if (rotation > max_rotation) rotation = max_rotation; if (rotation < (0-max_rotation)) rotation = 0-max_rotation; var percent = Math.floor(((rotation + max_rotation)/(max_rotation*2))*100); We should now be able to get a rotation from -60° to +60° expressed as a percentage. Try it for yourself. The big reveal All that’s left to do is pass that percentage to our image positioning function and would you believe it, it might actually work. position_image(percent); You can see the final result and take it for a spin. Literally. So 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. What we have made is progress. We’ve 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’t have this morning. Something we probably didn’t 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’ve learned that our browsers are just a little bit more capable than we thought. The 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. The 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’s create things. 2016 Drew McLellan drewmclellan 2016-12-24T00:00:00+00:00 https://24ways.org/2016/taking-device-orientation-for-a-spin/ code
267 Taming Complexity I’m going to step into my UX trousers for this one. I wouldn’t usually wear them in public, but it’s Christmas, so there’s nothing wrong with looking silly. Anyway, to business. Wherever I roam, I hear the familiar call for simplicity and the denouncement of complexity. I read often that the simpler something is, the more usable it will be. We understand that simple is hard to achieve, but we push for it nonetheless, convinced it will make what we build easier to use. Simple is better, right? Well, I’ll try to explore that. Much of what follows will not be revelatory to some but, like all good lessons, I think this serves as a welcome reminder that as we live in a complex world it’s OK to sometimes reflect that complexity in the products we build. Myths and legends Less is more, we’ve been told, ever since master of poetic verse Robert Browning used the phrase in 1855. Well, I’ve conducted some research, and it appears he knew nothing of web design. Neither did modernist architect Ludwig Mies van der Rohe, a later pedlar of this worthy yet contradictory notion. Broad is narrow. Tall is short. Eggs are chips. See: anyone can come up with this stuff. To paraphrase Einstein, simple doesn’t have to be simpler. In other words, simple doesn’t dictate that we remove the complexity. Complex doesn’t have to be confusing; it can be beautiful and elegant. On the web, complex can be necessary and powerful. A website that simplifies the lives of its users by offering them everything they need in one site or screen is powerful. For some, the greater the density of information, the more useful the site. In our decision-making process, principles such as Occam’s razor’s_razor (in a nutshell: simple is better than complex) are useful, but simple is for the user to determine through their initial impression and subsequent engagement. What appears simple to me or you might appear very complex to someone else, based on their own mental model or needs. We can aim to deliver simple, but they’ll be the judge. As a designer, developer, content alchemist, user experience discombobulator, or whatever you call yourself, you’re often wrestling with a wealth of material, a huge number of features, and numerous objectives. In many cases, much of that stuff is extraneous, and goes in the dustbin. However, it can be just as likely that there’s a truckload of suggested features and content because it all needs to be there. Don’t be afraid of that weight. In the right hands, less can indeed mean more, but it’s just as likely that less can very often lead to, well… less. Complexity is powerful Simple is the ability to offer a powerful experience without overwhelming the audience or inducing information anxiety. Giving them everything they need, without having them ferret off all over a site to get things done, is important. It’s useful to ask throughout a site’s lifespan, “does the user have everything they need?” It’s so easy to let our designer egos get in the way and chop stuff out, reduce down to only the things we want to see. That benefits us in the short term, but compromises the audience long-term. The trick is not to be afraid of complexity in itself, but to avoid creating the perception of complexity. Give a user a flight simulator and they’ll crash the plane or jump out. Give them everything they need and more, but make it feel simple, and you’re building a relationship, empowering people. This can be achieved carefully with what some call gradual engagement, and often the sensible thing might be to unleash complexity in carefully orchestrated phases, initially setting manageable levels of engagement and interaction, gradually increasing the inherent power of the product and fostering an empowered community. The design aesthetic Here’s a familiar scenario: the client or project lead gets overexcited and skips most of the important decision-making, instead barrelling straight into a bout of creative direction Tourette’s. Visually, the design needs to be minimal, white, crisp, full of white space, have big buttons, and quite likely be “clean”. Of course, we all like our websites to be clean as that’s more hygienic. But what do these words even mean, really? Early in a project they’re abstract distractions, unnecessary constraints. This premature narrowing forces us to think much more about throwing stuff out rather than acknowledging that what we’re building is complex, and many of the components perhaps necessary. Simple is not a formula. It cannot be achieved just by using a white background, by throwing things away, or by breathing a bellowsful of air in between every element and having it all float around in space. Simple is not a design treatment. Simple is hard. Simple requires deep investigation, a thorough understanding of every aspect of a project, in line with the needs and expectations of the audience. Recognizing this helps us empathize a little more with those most vocal of UX practitioners. They usually appreciate that our successes depend on a thorough understanding of the user’s mental models and expected outcomes. I personally still consider UX people to be web designers like the rest of us (mainly to wind them up), but they’re web designers that design every decision, and by putting the user experience at the heart of their process, they have a greater chance of finding simplicity in complexity. The visual design aesthetic — the façade — is only a part of that. Divide and conquer I’m currently working on an app that’s complex in architecture, and complex in ambition. We’ll be releasing in carefully orchestrated private phases, gradually introducing more complexity in line with the unavoidably complex nature of the objective, but my job is to design the whole, the complete system as it will be when it’s out of beta and beyond. I’ve noticed that I’m not throwing much out; most of it needs to be there. Therefore, my responsibility is to consider interesting and appropriate methods of navigation and bring everything together logically. I’m using things like smart defaults, graphical timelines and colour keys to make sense of the complexity, techniques that are sympathetic to the content. They act as familiar points of navigation and reference, yet are malleable enough to change subtly to remain relevant to the information they connect. It’s really OK to have a lot of stuff, so long as we make each component work smartly. It’s a divide and conquer approach. By finding simplicity and logic in each content bucket, I’ve made more sense of the whole, allowing me to create key layouts where most of the simplified buckets are collated and sometimes combined, providing everything the user needs and expects in the appropriate places. I’m also making sure I don’t reduce the app’s power. I need to reflect the scale of opportunity, and provide access to or knowledge of the more advanced tools and features for everyone: a window into what they can do and how they can help. I know it’s the minority who will be actively building the content, but the power is in providing those opportunities for all. Much of this will be familiar to the responsible practitioners who build websites for government, local authorities, utility companies, newspapers, magazines, banking, and we-sell-everything-ever-made online shops. Across the web, there are sites and tools that thrive on complexity. Alas, the majority of such sites have done little to make navigation intuitive, or empower audiences. Where we can make a difference is by striving to make our UIs feel simple, look wonderful, not intimidating — even if they’re mind-meltingly complex behind that façade. Embrace, empathize and tame So, there are loads of ways to exploit complexity, and make it seem simple. I’ve hinted at some methods above, and we’ve already looked at gradual engagement as a way to make sense of complexity, so that’s a big thumbs-up for a release cycle that increases audience power. Prior to each and every release, it’s also useful to rest on the finished thing for a while and use it yourself, even if you’re itching to release. ‘Ready’ often isn’t, and ‘finished’ never is, and the more time you spend browsing around the sites you build, the more you learn what to question, where to add, or subtract. It’s definitely worth building in some contingency time for sitting on your work, so to speak. One thing I always do is squint at my layouts. By squinting, I get a sort of abstract idea of the overall composition, and general feel for the thing. It makes my face look stupid, but helps me see how various buckets fit together, and how simple or complex the site feels overall. I mentioned the need to put our design egos to one side and not throw out anything useful, and I think that’s vital. I’m a big believer in economy, reduction, and removing the extraneous, but I’m usually referring to decoration, bells and whistles, and fluff. I wouldn’t ever advocate the complete removal of powerful content from a project roadmap. Above all, don’t fear complexity. Embrace and tame it. Work hard to empathize with audience needs, and you can create elegant, playful, risky, surprising, emotive, delightful, and ultimately simple things. 2011 Simon Collison simoncollison 2011-12-21T00:00:00+00:00 https://24ways.org/2011/taming-complexity/ ux
132 Tasty Text Trimmer In most cases, when designing a user interface it’s best to make a decision about how data is best displayed and stick with it. Failing to make a decision ultimately leads to too many user options, which in turn can be taxing on the poor old user. Under some circumstances, however, it’s good to give the user freedom in customising their workspace. One good example of this is the ‘Article Length’ tool in Apple’s Safari RSS reader. Sliding a slider left of right dynamically changes the length of each article shown. It’s that kind of awesomey magic stuff that’s enough to keep you from sleeping. Let’s build one. The Setup Let’s take a page that has lots of long text items, a bit like a news page or like Safari’s RSS items view. If we were to attach a class name to each element we wanted to resize, that would give us something to hook onto from the JavaScript. Example 1: The basic page. As you can see, I’ve wrapped my items in a DIV and added a class name of chunk to them. It’s these chunks that we’ll be finding with the JavaScript. Speaking of which … Our Core Functions There are two main tasks that need performing in our script. The first is to find the chunks we’re going to be resizing and store their original contents away somewhere safe. We’ll need this so that if we trim the text down we’ll know what it was if the user decides they want it back again. We’ll call this loadChunks. var loadChunks = function(){ var everything = document.getElementsByTagName('*'); var i, l; chunks = []; for (i=0, l=everything.length; i<l; i++){ if (everything[i].className.indexOf(chunkClass) > -1){ chunks.push({ ref: everything[i], original: everything[i].innerHTML }); } } }; The variable chunks is stored outside of this function so that we can access it from our next core function, which is doTrim. var doTrim = function(interval) { if (!chunks) loadChunks(); var i, l; for (i=0, l=chunks.length; i<l; i++){ var a = chunks[i].original.split(' '); a = a.slice(0, interval); chunks[i].ref.innerHTML = a.join(' '); } }; The first thing that needs to be done is to call loadChunks if the chunks variable isn’t set. This should only happen the first time doTrim is called, as from that point the chunks will be loaded. Then all we do is loop through the chunks and trim them. The trimming itself (lines 6-8) is very simple. We split the text into an array of words (line 6), then select only a portion from the beginning of the array up until the number we want (line 7). Finally the words are glued back together (line 8). In essense, that’s it, but it leaves us needing to know how to get the number into this function in the first place, and how that number is generated by the user. Let’s look at the latter case first. The YUI Slider Widget There are lots of JavaScript libraries available at the moment. A fair few of those are really good. I use the Yahoo! User Interface Library professionally, but have only recently played with their pre-build slider widget. Turns out, it’s pretty good and perfect for this task. Once you have the library files linked in (check the docs linked above) it’s fairly straightforward to create yourself a slider. slider = YAHOO.widget.Slider.getHorizSlider("sliderbg", "sliderthumb", 0, 100, 5); slider.setValue(50); slider.subscribe("change", doTrim); All that’s needed then is some CSS to make the slider look like a slider, and of course a few bits of HTML. We’ll see those later. See It Working! Rather than spell out all the nuts and bolts of implementing this fairly simple script, let’s just look at in it action and then pick on some interesting bits I’ve added. Example 2: Try the Tasty Text Trimmer. At the top of the JavaScript file I’ve added a small number of settings. var chunkClass = 'chunk'; var minValue = 10; var maxValue = 100; var multiplier = 5; Obvious candidates for configuration are the class name used to find the chunks, and also the some minimum and maximum values. The minValue is the fewest number of words we wish to display when the slider is all the way down. The maxValue is the length of the slider, in this case 100. Moving the slider makes a call to our doTrim function with the current value of the slider. For a slider 100 pixels long, this is going to be in the range of 0-100. That might be okay for some things, but for longer items of text you’ll want to allow for displaying more than 100 words. I’ve accounted for this by adding in a multiplier – in my code I’m multiplying the value by 5, so a slider value of 50 shows 250 words. You’ll probably want to tailor the multiplier to the type of content you’re using. Keeping it Accessible This effect isn’t something we can really achieve without JavaScript, but even so we must make sure that this functionality has no adverse impact on the page when JavaScript isn’t available. This is achieved by adding the slider markup to the page from within the insertSliderHTML function. var insertSliderHTML = function(){ var s = '<a id="slider-less" href="#less"><img src="icon_min.gif" width="10" height="10" alt="Less text" class="first" /></a>'; s +=' <div id="sliderbg"><div id="sliderthumb"><img src="sliderthumbimg.gif" /></div></div>'; s +=' <a id="slider-more" href="#more"><img src="icon_max.gif" width="10" height="10" alt="More text" /></a>'; document.getElementById('slider').innerHTML = s; } The other important factor to consider is that a slider can be tricky to use unless you have good eyesight and pretty well controlled motor skills. Therefore we should provide a method of changing the value by the keyboard. I’ve done this by making the icons at either end of the slider links so they can be tabbed to. Clicking on either icon fires the appropriate JavaScript function to show more or less of the text. In Conclusion The upshot of all this is that without JavaScript the page just shows all the text as it normally would. With JavaScript we have a slider for trimming the text excepts that can be controlled with the mouse or with a keyboard. If you’re like me and have just scrolled to the bottom to find the working demo, here it is again: Try the Tasty Text Trimmer Trimmer for Christmas? Don’t say I never give you anything! 2006 Drew McLellan drewmclellan 2006-12-01T00:00:00+00:00 https://24ways.org/2006/tasty-text-trimmer/ code
215 Teach the CLI to Talk Back The CLI is a daunting tool. It’s quick, powerful, but it’s also incredibly easy to screw things up in – 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’t have to be this way. If you’ve ever interacted with Slack’s Slackbot to set a reminder or ask a question, you’re 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.) Same 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. I’m not aiming to build an AI here – my aspirations are a little more down to earth. What I’d 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. Interactive command lines in the wild If you’ve used dev tools in the command line, you’ve probably already used an interactive prompt – something that asks you questions and responds based on your answers. Here are some examples: Yeoman If you have Yeoman globally installed, running yo will start a command prompt. The prompt asks you what you’d 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’s a nice way to start someone off with using the tool. npm If you’re a Node.js developer, you’re 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. The alternative would be to expect the user to craft their own package.json, which is more error-prone since it’s in JSON format, so something as trivial as an extraneous comma can throw an error. Snyk Snyk 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 – such as patching the issue, applying a fix by upgrading the problematic dependency, or ignoring the issue (you are then prompted for a reason). These 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. I 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. Writing your own Something I do a lot is add bookmarks to styleguides.io – 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’ve been putting together a tool to help me add bookmarks. It’s called bookmarkbot – it’s a personal assistant squirrel called Mark who will collect and bury your bookmarks for safekeeping.* *Fortunately, this metaphor also gives me a charming excuse for any situation where bookmarks sometimes get lost – it’s not my poorly-written code, honest, it’s just being realistic because sometimes squirrels forget where they buried things! When you run bookmarkbot, it will ask you for some information, and save that information as a Markdown file in YAML format. For this demo, I’m 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. Prerequisites Node.js npm RubyGems (Only if you want to go as far as serving a static site for your bookmarks, and you want to use Jekyll for it) Disclaimer Bear in mind that this is a really simplified walkthrough. It doesn’t have any error states, and it doesn’t 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. Let’s go! Create a new folder wherever you keep your projects, and give it an awesome name (I’ve called mine bookmarks and put it in the Sites directory because I’m unimaginative). Now cd to that directory. cd Sites/bookmarks Let’s use that example I gave earlier, the trusty npm init. npm init Pop in the information you’d 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’s install some of the dependencies we’ll need. npm install --save inquirer npm install --save slugify Next, add the following snippet to your package.json to tell it to run this file when you run npm start. "scripts": { … "start": "node index.js" } That index.js file doesn’t exist yet, so let’s create it in the root of our folder, and add the following: // Packages we need var fs = require('fs'); // Creates our file (part of Node.js so doesn't need installing) var inquirer = require('inquirer'); // The engine for our questions prompt var slugify = require('slugify'); // Will turn a string into a usable filename // The questions var questions = [ { type: 'input', name: 'name', message: 'What is your name?', }, ]; // The questions prompt function askQuestions() { // Ask questions inquirer.prompt(questions).then(answers => { // Things we'll need to generate the output var name = answers.name; // Finished asking questions, show the output console.log('Hello ' + name + '!'); }); } // Kick off the questions prompt askQuestions(); This is just some barebones where we’re including the inquirer package we installed earlier. I’ve stored the questions in a variable, and the askQuestions function will prompt the user for their name, and then print “Hello <your name>” in the console. Enough setup, let’s see some magic. Save the file, go back to the command line and run npm start. Extending what we’ve learnt At the moment, we’re just saving a name to a file, which isn’t really achieving our goal of saving bookmarks. We don’t want our tool to forget our information every time we talk to it – we need to save it somewhere. So I’m going to add a little function to write the output to a file. Saving to a file Create a folder in your project’s directory called _bookmarks. This is where the bookmarks will be saved. I’ve replaced my questions array, and instead of asking for a name, I’ve extended out the questions, asking to be provided with a link and title (as a regular input type), a list of tags (using inquirer’s checkbox type), and finally a description, again, using the input type. So this is how my code looks now: // Packages we need var fs = require('fs'); // Creates our file var inquirer = require('inquirer'); // The engine for our questions prompt var slugify = require('slugify'); // Will turn a string into a usable filename // The questions var questions = [ { type: 'input', name: 'link', message: 'What is the url?', }, { type: 'input', name: 'title', message: 'What is the title?', }, { type: 'checkbox', name: 'tags', message: 'Would you like me to add any tags?', choices: [ { name: 'frontend' }, { name: 'backend' }, { name: 'security' }, { name: 'design' }, { name: 'process' }, { name: 'business' }, ], }, { type: 'input', name: 'description', message: 'How about a description?', }, ]; // The questions prompt function askQuestions() { // Say hello console.log('🐿 Oh, hello! Found something you want me to bookmark?\n'); // Ask questions inquirer.prompt(questions).then((answers) => { // Things we'll need to generate the output var title = answers.title; var link = answers.link; var tags = answers.tags + ''; var description = answers.description; var output = '---\n' + 'title: "' + title + '"\n' + 'link: "' + link + '"\n' + 'tags: [' + tags + ']\n' + '---\n' + description + '\n'; // Finished asking questions, show the output console.log('\n🐿 All done! Here is what I\'ve written down:\n'); console.log(output); // Things we'll need to generate the filename var slug = slugify(title); var filename = '_bookmarks/' + slug + '.md'; // Write the file fs.writeFile(filename, output, function () { console.log('\n🐿 Great! I have saved your bookmark to ' + filename); }); }); } // Kick off the questions prompt askQuestions(); The 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. Getting confirmation Before the user makes critical changes, it’s good to verify those changes first. We’re going to add a confirmation step to our tool, before writing the file. More seasoned CLI users may favour speed over a “hey, can you wait a sec and just check this is all ok” step, but I always think it’s worth adding one so you can occasionally save someone’s butt. So, underneath our questions array, let’s add a confirmation array. // Packages we need … // The questions … // Confirmation questions var confirm = [ { type: 'confirm', name: 'confirm', message: 'Does this look good?', }, ]; // The questions prompt … As we’re adding the confirm step before the file gets written, we’ll need to add the following inside the askQuestions function: // The questions prompt function askQuestions() { // Say hello … // Ask questions inquirer.prompt(questions).then((answers) => { … // Things we'll need to generate the output … // Finished asking questions, show the output … // Confirm output is correct inquirer.prompt(confirm).then(answers => { // Things we'll need to generate the filename var slug = slugify(title); var filename = '_bookmarks/' + slug + '.md'; if (answers.confirm) { // Save output into file fs.writeFile(filename, output, function () { console.log('\n🐿 Great! I have saved your bookmark to ' + filename); }); } else { // Ask the questions again console.log('\n🐿 Oops, let\'s try again!\n'); askQuestions(); } }); }); } // Kick off the questions prompt askQuestions(); Now run npm start and give it a go! Typing y will write the file, and n will take you back to the start. Ideally, I’d store the answers already given as defaults so the user doesn’t have to start from scratch, but I want to keep this demo simple. Serving the files Now 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’ve got a few options here and I don’t want to force you down any particular path, as there are plenty out there – it’s just a case of using the one you’re most comfortable with. I personally favour Jekyll because of its tight integration with GitHub Pages – I don’t want to mess around with hosting and deployment, so it’s really handy to have my bookmarks publish themselves on my site as soon as I commit and push them using Git. I’ll give you a very brief run-through of how I’m doing this with bookmarkbot, but I recommend you read my Get Started With GitHub Pages (Plus Bonus Jekyll) guide if you’re unfamiliar with them, because I’ll be glossing over some bits that are already covered in there. Setting up a build tool If you haven’t already, install Jekyll and Bundler globally through RubyGems. Jekyll is our static-site generator, and Bundler is what we use to install Ruby dependencies. gem install jekyll bundler In my project folder, I’m going to run the following which will install the Jekyll files we’ll need to build our listing page. I’m using --force, otherwise it will complain that the directory isn’t empty. jekyll new . --force If you check your project folder, you’ll see a bunch of new files. Now run the following to start the server: bundle exec jekyll serve This will build a new directory called _site. This is where your static HTML files have been generated. Don’t touch anything in this folder because it will get overwritten the next time you build. Now that serve is running, go to http://127.0.0.1:4000/ and you’ll 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’ve got a few saved). So let’s get that set up next. Open up the _config.yml file that Jekyll added earlier. In here, we’re going to tell it about our bookmarks. Replace everything in your _config.yml file with the following: title: My Bookmarks description: These are some of my favourite articles about the web. markdown: kramdown baseurl: /bookmarks # This needs to be the same name as whatever you call your repo on GitHub. collections: - bookmarks This 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. <!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>{{site.title}}</title> <meta name="description" content="{{site.description}}"> </head> <body> <h1>{{site.title}}</h1> <p>{{site.description}}</p> <ul> {% for bookmark in site.bookmarks %} <li> <a href="{{bookmark.link}}"> <h2>{{bookmark.title}}</h2> </a> {{bookmark.content}} {% if bookmark.tags %} <ul> {% for tags in bookmark.tags %}<li>{{tags}}</li>{% endfor %} </ul> {% endif %} </li> {% endfor %} </ul> </body> </html> Restart 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). It’s a decent start – there’s a lot more we can do in this area but now we’ve got a nice list of all our bookmarks, let’s get it online! If 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 “settings”. Scroll down to the section labelled “GitHub Pages”, and from here you can enable it. Select your master branch, and it will provide you with a url to view your published pages. What next? Now that you’ve 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’ll probably want to do is add some CSS, then when you’ve added a bunch of bookmarks, you’ll 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’re feeling extra-fancy, you could just ask for a url and pull in metadata from the site itself). Maybe you’ve got an idea that doesn’t involve bookmarks at all. You could use what you’ve learnt to build a place where you can share quotes, a list of your favourite restaurants, or even Christmas gift ideas. Here’s one I made earlier My demo, bookmarkbot, is on GitHub, and I’ve 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! 2017 Anna Debenham annadebenham 2017-12-11T00:00:00+00:00 https://24ways.org/2017/teach-the-cli-to-talk-back/ code
257 The (Switch)-Case for State Machines in User Interfaces You’re tasked with creating a login form. Email, password, submit button, done. “This will be easy,” you think to yourself. Login form by Selecto You’ve made similar forms many times in the past; it’s essentially muscle memory at this point. You’re working closely with a designer, who gives you a beautiful, detailed mockup of a login form. Sure, you’ll have to translate the pixels to meaningful, responsive CSS values, but that’s the least of your problems. As you’re writing up the HTML structure and CSS layout and styles for this form, you realize that you don’t know what the successful “logged in” page looks like. You remind the designer, who readily gives it to you. But then you start thinking more and more about how the login form is supposed to work. What if login fails? Where do those errors show up? Should we show errors differently if the user forgot to enter their email, or password, or both? Or should the submit button be disabled? Should we validate the email field? When should we show validation errors – as they’re typing their email, or when they move to the password field, or when they click submit? (Note: many, many login forms are guilty of this.) When should the errors disappear? What do we show during the login process? Some loading spinner? What if loading takes too long, or a server error occurs? Many more questions come up, and you (and your designer) are understandably frustrated. The lack of upfront specification opens the door to scope creep, which readily finds itself at home in all the unexplored edge cases. Modeling Behavior Describing all the possible user flows and business logic of an application can become tricky. Ironically, user stories might not tell the whole story – they often leave out potential edge-cases or small yet important bits of information. However, one important (and very old) mathematical model of computation can be used for describing the behavior and all possible states of a user interface: the finite state machine. The general idea, as it applies to user interfaces, is that all of our applications can be described (at some level of abstraction) as being in one, and only one, of a finite number of states at any given time. For example, we can describe our login form above in these states: start - not submitted yet loading - submitted and logging in success - successfully logged in error - login failed Additionally, we can describe an application as accepting a finite number of events – that is, all the possible events that can be “sent” to the application, either from the user or some other external entity: SUBMIT - pressing the submit button RESOLVE - the server responds, indicating that login is successful REJECT - the server responds, indicating that login failed Then, we can combine these states and events to describe the transitions between them. That is, when the application is in one state, an an event occurs, we can specify what the next state should be: From the start state, when the SUBMIT event occurs, the app should be in the loading state. From the loading state, when the RESOLVE event occurs, login succeeded and the app should be in the success state. If login fails from the loading state (i.e., when the REJECT event occurs), the app should be in the error state. From the error state, the user should be able to retry login: when the SUBMIT event occurs here, the app should go to the loading state. Otherwise, if any other event occurs, don’t do anything and stay in the same state. That’s a pretty thorough description, similar to a user story! It’s also a bit more symbolic than a user story (e.g., “when the SUBMIT event occurs” instead of “when the user presses the submit button”), and that’s for a reason. By representing states, events, and transitions symbolically, we can visualize what this state machine looks like: Every state is represented by a box, and every event is connected to a transition arrow that connects two states. This makes it intuitive to follow the flow and understand what the next state should be given the current state and an event. From Visuals to Code Drawing a state machine doesn’t require any special software; in fact, using paper and pencil (in case anything changes!) does the job quite nicely. However, one common problem is handoff: it doesn’t matter how detailed a user story or how well-designed a visualization is, it eventually has to be coded in order for it to become part of a real application. With the state machine model described above, the same visual description can be mapped directly to code. Traditionally, and as the title suggests, this is done using switch/case statements: function loginMachine(state, event) { switch (state) { case 'start': if (event === 'SUBMIT') { return 'loading'; } break; case 'loading': if (event === 'RESOLVE') { return 'success'; } else if (event === 'REJECT') { return 'error'; } break; case 'success': // Accept no further events break; case 'error': if (event === 'SUBMIT') { return 'loading'; } break; default: // This should never occur return undefined; } } console.log(loginMachine('start', 'SUBMIT')); // => 'loading' This is fine (I suppose) but personally, I find it much easier to use objects: const loginMachine = { initial: "start", states: { start: { on: { SUBMIT: 'loading' } }, loading: { on: { REJECT: 'error', RESOLVE: 'success' } }, error: { on: { SUBMIT: 'loading' } }, success: {} } }; function transition(state, event) { return machine .states[state] // Look up the state .on[event] // Look up the next state based on the event || state; // If not found, return the current state } console.log(transition('start', 'SUBMIT')); As you might have noticed, the loginMachine is a plain JS object, and can be written in JSON. This is important because it allows the machine to be visualized by a 3rd-party tool, as demonstrated here: A Common Language Between Designers and Developers Although finite state machines are a fundamental part of computer science, they have an amazing potential to bridge the application specification gap between designers and developers, as well as project managers, stakeholders, and more. By designing a state machine visually and with code, designers and developers alike can: identify all possible states, and potentially missing states describe exactly what should happen when an event occurs on a given state, and prevent that event from having unintended side-effects in other states (ever click a submit button more than once?) eliminate impossible states and identify states that are “unreachable” (have no entry transition) or “sunken” (have no exit transition) add features with full confidence of knowing what other states it might affect simplify redundant states or complex user flows create test paths for almost every possible user flow, and easily identify edge cases collaborate better by understanding the entire application model equally. Not a New Idea I’m not the first to suggest that state machines can help bridge the gap between design and development. Vince MingPu Shao wrote an article about designing UI states and communicating with developers effectively with finite state machines User flow diagrams, which visually describe the paths that a user can take through an app to achieve certain goals, are essentially state machines. Numerous tools, from Sketch plugins to standalone apps, exist for creating them. In 1999, Ian Horrocks wrote a book titled “Constructing the User Interface with Statecharts”, which takes state machines to the next level and describes the inherent difficulties (and solutions) with creating complex UIs. The ideas in the book are still relevant today. More than a decade earlier, David Harel published “Statecharts: A Visual Formalism for Complex Systems”, in which the statechart - an extended hierarchical state machine model - is born. State machines and statecharts have been used for complex systems and user interfaces, both physical and digital, for decades, and are especially prevalent in other industries, such as game development and embedded electronic systems. Even NASA uses statecharts for the Curiosity Rover and more, citing many benefits: Visualized modeling Precise diagrams Automatic code generation Comprehensive test coverage Accommodation of late-breaking requirements changes Moving Forward It’s time that we improve how we communicate between designers and developers, much less improve the way we develop UIs to deliver the best, bug-free, optimal user experience. There is so much more to state machines and statecharts than just being a different way of designing and coding. For more resources: The World of Statecharts is a comprehensive guide by Erik Mogensen in using statecharts in your applications The Statechart Community on Spectrum is always full of interesting ideas and questions related to state machines, statecharts, and software modeling I gave a talk at React Rally over a year ago about how state machines (finite automata) can improve the way we develop applications. The latest one is from Reactive Conf, where I demonstrate how statecharts can be used to automatically generate test cases. I have also been working on XState, which is a library for “state machines and statecharts for the modern web”. You can create and visualize statecharts in JavaScript, and use them in any framework (and soon enough, multiple different languages). I’m excited about the future of developing web and mobile applications with statecharts, especially with regard to faster design/development cycles, auto-generated testing, better error prevention, comprehensive analytics, and even the use of model-based reinforcement learning and artificial intelligence to greatly improve the user experience. 2018 David Khourshid davidkhourshid 2018-12-12T00:00:00+00:00 https://24ways.org/2018/state-machines-in-user-interfaces/ code
65 The Accessibility Mindset 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. Indeed, it is an additional skill set to acquire, quite like learning new JavaScript frameworks, CSS layout techniques or new HTML elements. But it isn’t particularly harder to learn than those other skills. A World Health Organization (WHO) report on disabilities states that, [i]ncluding children, over a billion people (or about 15% of the world’s population) were estimated to be living with disability. Being 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. Accessibility 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’ needs when they are built in an accessible fashion. Beyond the bare minimum In the time of table layouts, web developers could create code that passed validation rules but didn’t 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’t do is measure how well you met them. W3C 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. The 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: Open video The 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: Open video The 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: Open video You can also set the label to display:block; to further increase the clickable area: Open video And while we’re at it, users might expect the whole box to be clickable anyway. Let’s apply the CSS that was on a wrapping div element to the label directly: Open video The 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. <form action="#"> <label for="uniquecheckboxid"> <input type="checkbox" name="checkbox" id="uniquecheckboxid" /> Checkbox 4 </label> </form> Button Example The 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 “button” without any indication of what this button is for. Open video A screen reader announcing a button. Contains audio. The code snippet shows why the button is not properly announced: <button> <span class="icon icon-pencil"></span> </button> An 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: Open video A screen reader announcing a button with a title. However, 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’t 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: The mobile GitHub view with and without external fonts. Even 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’t load. <button> <img src="icon-pencil.svg" alt="Edit"> </button> Providing 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. <button> <span class="icon icon-pencil"></span> Edit </button> This also reads just fine in screen readers: Open video A screen reader announcing the revised button. Clever usability enhancements don’t stop at a technical implementation level. Take the BBC iPlayer pages as an example: when a user navigates the “captioned videos” or “audio description” 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’t 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. More information W3C 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 “How People with Disabilities Use the Web”, there are “Tips for Getting Started” 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. Conclusion You 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’t notice when those fundamental aspects of good website design and development are done right. But they’ll always know when they are implemented poorly. If you take all this into consideration, you can create accessibility solutions based on the available data and bring accessibility to people who didn’t know they’d need it: Open video In this video from the latest Apple keynote, the Apple TV is operated by voice input through a remote. When the user asks “What did she say?” 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. 2015 Eric Eggert ericeggert 2015-12-17T00:00:00+00:00 https://24ways.org/2015/the-accessibility-mindset/ code
260 The Art of Mathematics: A Mandala Maker Tutorial In front-end development, there’s often a great deal of focus on tools that aim to make our work more efficient. But what if you’re new to web development? When you’re just starting out, the amount of new material can be overwhelming, particularly if you don’t have a solid background in Computer Science. But the truth is, once you’ve learned a little bit of JavaScript, you can already make some pretty impressive things. A couple of years back, when I was learning to code, I started working on a side project. I wanted to make something colorful and fun to share with my friends. This is what my app looks like these days: Mandala Maker user interface The coolest part about it is the fact that it’s a tool: anyone can use it to create something original and brand new. In this tutorial, we’ll build a smaller version of this app – a symmetrical drawing tool in ES5, JavaScript and HTML5. The tutorial app will have eight reflections, a color picker and a Clear button. Once we’re done, you’re on your own and can tweak it as you please. Be creative! Preparations: a blank canvas The first thing you’ll need for this project is a designated drawing space. We’ll use the HTML5 canvas element and give it a width and a height of 600px (you can set the dimensions to anything else if you like). Files Create 3 files: index.html, styles.css, main.js. Don’t forget to include your JS and CSS files in your HTML. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="style.css"> <script src="main.js"></script> </head> <body onload="init()"> <canvas width="600" height="600"> <p>Your browser doesn't support canvas.</p> </canvas> </body> </html> I’ll ask you to update your HTML file at a later point, but the CSS file we’ll start with will stay the same throughout the project. This is the full CSS we are going to use: body { background-color: #ccc; text-align: center; } canvas { touch-action: none; background-color: #fff; } button { font-size: 110%; } Next steps We are done with our preparations and ready to move on to the actual tutorial, which is made up of 4 parts: Building a simple drawing app with one line and one color Adding a Clear button and a color picker Adding more functionality: 2 line drawing (add the first reflection) Adding more functionality: 8 line drawing (add 6 more reflections!) Interactive demos This tutorial will be accompanied by four CodePens, one at the end of each section. In my own app I originally used mouse events, and only added touch events when I realized mobile device support was (A) possible, and (B) going to make my app way more accessible. For the sake of code simplicity, I decided that in this tutorial app I will only use one event type, so I picked a third option: pointer events. These are supported by some desktop browsers and some mobile browsers. An up-to-date version of Chrome is probably your best bet. Part 1: A simple drawing app Let’s get started with our main.js file. Our basic drawing app will be made up of 6 functions: init, drawLine, stopDrawing, recordPointerLocation, handlePointerMove, handlePointerDown. It also has nine variables: var canvas, context, w, h, prevX = 0, currX = 0, prevY = 0, currY = 0, draw = false; The variables canvas and context let us manipulate the canvas. w is the canvas width and h is the canvas height. The four coordinates are used for tracking the current and previous location of the pointer. A short line is drawn between (prevX, prevY) and (currX, currY) repeatedly many times while we move the pointer upon the canvas. For your drawing to appear, three conditions must be met: the pointer (be it a finger, a trackpad or a mouse) must be down, it must be moving and the movement has to be on the canvas. If these three conditions are met, the boolean draw is set to true. 1. init Responsible for canvas set up, this listens to pointer events and the location of their coordinates and sets everything in motion by calling other functions, which in turn handle touch and movement events. function init() { canvas = document.querySelector("canvas"); context = canvas.getContext("2d"); w = canvas.width; h = canvas.height; canvas.onpointermove = handlePointerMove; canvas.onpointerdown = handlePointerDown; canvas.onpointerup = stopDrawing; canvas.onpointerout = stopDrawing; } 2. drawLine This is called to action by handlePointerMove() and draws the pointer path. It only runs if draw = true. It uses canvas methods you can read about in the canvas API documentation. You can also learn to use the canvas element in this tutorial. lineWidth and linecap set the properties of our paint brush, or digital pen, but pay attention to beginPath and closePath. Between those two is where the magic happens: moveTo and lineTo take canvas coordinates as arguments and draw from (a,b) to (c,d), which is to say from (prevX,prevY) to (currX,currY). function drawLine() { var a = prevX, b = prevY, c = currX, d = currY; context.lineWidth = 4; context.lineCap = "round"; context.beginPath(); context.moveTo(a, b); context.lineTo(c, d); context.stroke(); context.closePath(); } 3. stopDrawing This is used by init when the pointer is not down (onpointerup) or is out of bounds (onpointerout). function stopDrawing() { draw = false; } 4. recordPointerLocation This tracks the pointer’s location and stores its coordinates. Also, you need to know that in computer graphics the origin of the coordinate space (0,0) is at the top left corner, and all elements are positioned relative to it. When we use canvas we are dealing with two coordinate spaces: the browser window and the canvas itself. This function converts between the two: it subtracts the canvas offsetLeft and offsetTop so we can later treat the canvas as the only coordinate space. If you are confused, read more about it. function recordPointerLocation(e) { prevX = currX; prevY = currY; currX = e.clientX - canvas.offsetLeft; currY = e.clientY - canvas.offsetTop; } 5. handlePointerMove This is set by init to run when the pointer moves. It checks if draw = true. If so, it calls recordPointerLocation to get the path and drawLine to draw it. function handlePointerMove(e) { if (draw) { recordPointerLocation(e); drawLine(); } } 6. handlePointerDown This is set by init to run when the pointer is down (finger is on touchscreen or mouse it clicked). If it is, calls recordPointerLocation to get the path and sets draw to true. That’s because we only want movement events from handlePointerMove to cause drawing if the pointer is down. function handlePointerDown(e) { recordPointerLocation(e); draw = true; } Finally, we have a working drawing app. But that’s just the beginning! See the Pen Mandala Maker Tutorial: Part 1 by Hagar Shilo (@hagarsh) on CodePen. Part 2: Add a Clear button and a color picker Now we’ll update our HTML file, adding a menu div with an input of the type and class color and a button of the class clear. <body onload="init()"> <canvas width="600" height="600"> <p>Your browser doesn't support canvas.</p> </canvas> <div class="menu"> <input type="color" class="color" /> <button type="button" class="clear">Clear</button> </div> </body> Color picker This is our new color picker function. It targets the input element by its class and gets its value. function getColor() { return document.querySelector(".color").value; } Up until now, the app used a default color (black) for the paint brush/digital pen. If we want to change the color we need to use the canvas property strokeStyle. We’ll update drawLine by adding strokeStyle to it and setting it to the input value by calling getColor. function drawLine() { //...code... context.strokeStyle = getColor(); context.lineWidth = 4; context.lineCap = "round"; //...code... } Clear button This is our new Clear function. It responds to a button click and displays a dialog asking the user if she really wants to delete the drawing. function clearCanvas() { if (confirm("Want to clear?")) { context.clearRect(0, 0, w, h); } } The method clearRect takes four arguments. The first two (0,0) mark the origin, which is actually the top left corner of the canvas. The other two (w,h) mark the full width and height of the canvas. This means the entire canvas will be erased, from the top left corner to the bottom right corner. If we were to give clearRect a slightly different set of arguments, say (0,0,w/2,h), the result would be different. In this case, only the left side of the canvas would clear up. Let’s add this event handler to init: function init() { //...code... canvas.onpointermove = handleMouseMove; canvas.onpointerdown = handleMouseDown; canvas.onpointerup = stopDrawing; canvas.onpointerout = stopDrawing; document.querySelector(".clear").onclick = clearCanvas; } See the Pen Mandala Maker Tutorial: Part 2 by Hagar Shilo (@hagarsh) on CodePen. Part 3: Draw with 2 lines It’s time to make a line appear where no pointer has gone before. A ghost line! For that we are going to need four new coordinates: a', b', c' and d' (marked in the code as a_, b_, c_ and d_). In order for us to be able to add the first reflection, first we must decide if it’s going to go over the y-axis or the x-axis. Since this is an arbitrary decision, it doesn’t matter which one we choose. Let’s go with the x-axis. Here is a sketch to help you grasp the mathematics of reflecting a point across the x-axis. The coordinate space in my sketch is different from my explanation earlier about the way the coordinate space works in computer graphics (more about that in a bit!). Now, look at A. It shows a point drawn where the pointer hits, and B shows the additional point we want to appear: a reflection of the point across the x-axis. This is our goal. A sketch illustrating the mathematics of reflecting a point. What happens to the x coordinates? The variables a/a' and c/c' correspond to prevX and currX respectively, so we can call them “the x coordinates”. We are reflecting across x, so their values remain the same, and therefore a' = a and c' = c. What happens to the y coordinates? What about b' and d'? Those are the ones that have to change, but in what way? Thanks to the slightly misleading sketch I showed you just now (of A and B), you probably think that the y coordinates b' and d' should get the negative values of b and d respectively, but nope. This is computer graphics, remember? The origin is at the top left corner and not at the canvas center, and therefore we get the following values: b = h - b, d' = h - d, where h is the canvas height. This is the new code for the app’s variables and the two lines: the one that fills the pointer’s path and the one mirroring it across the x-axis. function drawLine() { var a = prevX, a_ = a, b = prevY, b_ = h-b, c = currX, c_ = c, d = currY, d_ = h-d; //... code ... // Draw line #1, at the pointer's location context.moveTo(a, b); context.lineTo(c, d); // Draw line #2, mirroring the line #1 context.moveTo(a_, b_); context.lineTo(c_, d_); //... code ... } In case this was too abstract for you, let’s look at some actual numbers to see how this works. Let’s say we have a tiny canvas of w = h = 10. Now let a = 3, b = 2, c = 4 and d = 3. So b' = 10 - 2 = 8 and d' = 10 - 3 = 7. We use the top and the left as references. For the y coordinates this means we count from the top, and 8 from the top is also 2 from the bottom. Similarly, 7 from the top is 3 from the bottom of the canvas. That’s it, really. This is how the single point, and a line (not necessarily a straight one, by the way) is made up of many, many small segments that are similar to point in behavior. If you are still confused, I don’t blame you. Here is the result. Draw something and see what happens. See the Pen Mandala Maker Tutorial: Part 3 by Hagar Shilo (@hagarsh) on CodePen. Part 4: Draw with 8 lines I have made yet another confusing sketch, with points C and D, so you understand what we’re trying to do. Later on we’ll look at points E, F, G and H as well. The circled point is the one we’re adding at each particular step. The circled point at C has the coordinates (-3,2) and the circled point at D has the coordinates (-3,-2). Once again, keep in mind that the origin in the sketches is not the same as the origin of the canvas. A sketch illustrating points C and D. This is the part where the math gets a bit mathier, as our drawLine function evolves further. We’ll keep using the four new coordinates: a', b', c' and d', and reassign their values for each new location/line. Let’s add two more lines in two new locations on the canvas. Their locations relative to the first two lines are exactly what you see in the sketch above, though the calculation required is different (because of the origin points being different). function drawLine() { //... code ... // Reassign values a_ = w-a; b_ = b; c_ = w-c; d_ = d; // Draw the 3rd line context.moveTo(a_, b_); context.lineTo(c_, d_); // Reassign values a_ = w-a; b_ = h-b; c_ = w-c; d_ = h-d; // Draw the 4th line context.moveTo(a_, b_); context.lineTo(c_, d_); //... code ... What is happening? You might be wondering why we use w and h as separate variables, even though we know they have the same value. Why complicate the code this way for no apparent reason? That’s because we want the symmetry to hold for a rectangular canvas as well, and this way it will. Also, you may have noticed that the values of a' and c' are not reassigned when the fourth line is created. Why write their value assignments twice? It’s for readability, documentation and communication. Maintaining the quadruple structure in the code is meant to help you remember that all the while we are dealing with two y coordinates (current and previous) and two x coordinates (current and previous). What happens to the x coordinates? As you recall, our x coordinates are a (prevX) and c (currX). For the third line we are adding, a' = w - a and c' = w - c, which means… For the fourth line, the same thing happens to our x coordinates a and c. What happens to the y coordinates? As you recall, our y coordinates are b (prevY) and d (currY). For the third line we are adding, b' = b and d' = d, which means the y coordinates are the ones not changing this time, making this is a reflection across the y-axis. For the fourth line, b' = h - b and d' = h - d, which we’ve seen before: that’s a reflection across the x-axis. We have four more lines, or locations, to define. Note: the part of the code that’s responsible for drawing a micro-line between the newly calculated coordinates is always the same: context.moveTo(a_, b_); context.lineTo(c_, d_); We can leave it out of the next code snippets and just focus on the calculations, i.e, the reassignments. Once again, we need some concrete examples to see where we’re going, so here’s another sketch! The circled point E has the coordinates (2,3) and the circled point F has the coordinates (2,-3). The ability to draw at A but also make the drawing appear at E and F (in addition to B, C and D that we already dealt with) is the functionality we are about to add to out code. A sketch illustrating points E and F. This is the code for E and F: // Reassign for 5 a_ = w/2+h/2-b; b_ = w/2+h/2-a; c_ = w/2+h/2-d; d_ = w/2+h/2-c; // Reassign for 6 a_ = w/2+h/2-b; b_ = h/2-w/2+a; c_ = w/2+h/2-d; d_ = h/2-w/2+c; Their x coordinates are identical and their y coordinates are reversed to one another. This one will be out final sketch. The circled point G has the coordinates (-2,3) and the circled point H has the coordinates (-2,-3). A sketch illustrating points G and H. This is the code: // Reassign for 7 a_ = w/2-h/2+b; b_ = w/2+h/2-a; c_ = w/2-h/2+d; d_ = w/2+h/2-c; // Reassign for 8 a_ = w/2-h/2+b; b_ = h/2-w/2+a; c_ = w/2-h/2+d; d_ = h/2-w/2+c; //...code... } Once again, the x coordinates of these two points are the same, while the y coordinates are different. And once again I won’t go into the full details, since this has been a long enough journey as it is, and I think we’ve covered all the important principles. But feel free to play around with the code and change it. I really recommend commenting out the code for some of the points to see what your drawing looks like without them. I hope you had fun learning! This is our final app: See the Pen Mandala Maker Tutorial: Part 4 by Hagar Shilo (@hagarsh) on CodePen. 2018 Hagar Shilo hagarshilo 2018-12-02T00:00:00+00:00 https://24ways.org/2018/the-art-of-mathematics/ code
230 The Articulate Web Designer of Tomorrow You could say that we design to communicate, and that we seek emotive responses. It sounds straightforward, and it can be, but leaving it to chance isn’t wise. Many wander into web design without formal training, and whilst that certainly isn’t essential, we owe it to ourselves to draw on wider influences, learn from the past, and think smarter. What knowledge can we ourselves explore in order to become better designers? In addition, how can we take this knowledge, investigate it through our unique discipline, and in turn speak more eloquently about what we do on the web? Below, I outline a number of things that I personally believe all designers should be using and exploring collectively. Taking stock Where we’re at is good. Finding clarity through web standards, we’ve ended up quite modernist in our approach, pursuing function, elegance and reduction. However, we’re not great at articulating our own design processes and principles to outsiders. Equally, we rely heavily on our instincts when deciding if something is or isn’t good. That’s fine, but we can better understand why things are the way they are by looking a little deeper, thereby helping us articulate what goes on in our design brains to our peers, our clients and to normal humans. As designers we use ideas, concepts, text and images. We apply our ideas and experience, imposing order and structure to content, hoping to ease the communication of an idea to the largest possible audience or to a specific audience. We consciously manipulate most of what is available to us, but not all. There is something else we can use. I often think that brilliant work demands a keen understanding of the magical visual language that informs design. Embracing an established visual language This is a language whose alphabet is shapes, structures, colours, lines and rhythms. When effective, it is somewhat invisible, subliminally enforcing messages and evoking meaning, using methods solidly rooted in a grammar perceptible in virtually all extraordinary creative work. The syntax for art, architecture, film, and furniture, industrial and graphic design (think Bauhaus and the Swiss style perhaps), this language urges us to become fluent if we aim for a more powerful dialogue with our audience. Figure 1: Structures (clockwise from top-left): Informal; Formal; Active; Visible. The greatest creative minds our world has produced could understand some or all of this language. Line and point, form and shape. Abstract objects. Formal and informal structures. Visual distribution. Balance, composition and the multitudinous approaches to symmetry. Patterns and texture. Movement and paths. Repetition, rhythm and frequency. Colour theory. Whitespace and the pause. The list goes on. The genius we perceive in our creative heroes is often a composite of experience, trial and error, conviction, intuition – even accident – but rarely does great work arise without an initial understanding of the nuts and bolts that help communicate an idea or emotion. Our world of interactivity As web designers, our connection with this language is most evident in graphic design. With more technological ease and power comes the responsibility to understand, wisely use, and be able to justify many of our decisions. We have moved beyond the scope of print into a world of interactivity, but we shouldn’t let go of any established principles without good reason. Figure 2: Understanding movement of objects in any direction along a defined path. For example, immersion in this visual language can improve our implementation of CSS3 and JavaScript behaviour. With CSS3, we’ve seen a resurgence in CSS experimentation, some of which has been wonderful, but much of it has appeared clumsy. In the race to make something spin, twist, flip or fly from one corner to another, the designer sometimes fails to think about the true movement they seek to emulate. What forces are supposedly affecting this movement? What is the expected path of this transition and is it being respected? Stopping to think about what is really supposed to be happening on the page compels us to use complex animations, diagrams and rotations more carefully. It helps us to better understand paths and movement. Figure 3: Repetition can occur through variations in colour, shape, direction, and so on. It can only be of greater benefit to be mindful of symmetries, depth, affordance, juxtaposition, balance, economy and reduction. A deeper understanding of basic structures can help us to say more with sketches, wireframes, layouts and composition. We’ve all experimented with grids and rhythm but, to truly benefit from these long-established principles, we are duty-bound to understand their possibilities more than we will by simply leveraging a free framework or borrowing some CSS. Design is not a science, but… Threading through all of this is what we have learned from science, and what it teaches us of the human brain. This visual language matters because technology changes but, for the most part, people don’t. For centuries, we humans have received and interpreted information in much the same way. Understanding more of how we perceive meaning can help designers make smarter decisions, and call on visual language to underpin these decisions. It is our responsibility as designers to be aware of mental models, mapping, semiotics, sensory experience and human emotion. Design itself is not a science, but the appropriate use of visual language and scientific understanding exposes the line between effective and awkward, between communicative and mute. By strengthening our mental and analytical approach to what is often done arbitrarily or “because it feels right”, we simply become better designers. A visual language for the web So, I’ve outlined numerous starting points and areas worthy of deeper investigation, and hopefully you’re eager to do some research. However, I’ve mostly discussed established ideas and principles that we as web designers can learn from. It’s my belief that our community has a shared responsibility to expand this visual language as it applies to the ebb and flow of the web. Indulge me as I conclude with a related tangent. In defining a visual language specifically for the web, we must continue to mature. The old powerfully influences the new, but we must intelligently expand the visual language of masterful work and articulate what is uniquely ours. For example, phrases like Ethan Marcotte’s Responsive Web Design aren’t merely elegant, they describe a new way of thinking and working, of communicating about designs and interaction patterns. These phrases broaden our vocabulary and are immediately adopted by designers worldwide, in both conversation and execution. Our legacy Our new definitions should flex and not be tied to specific devices or methods which fade away or morph with time. Our legacy is perhaps more about robust and flexible patterns and systems than it is about specific devices or programming languages. Figure 4: As web designers, we should think about systems, not pages. The established principles we adopt and whatever new ways of thinking we define should slip neatly into a wider philosophy about our approach to web design. We’re called, as a community, to define what is distinctive about the visual language of the web, create this vocabulary, this dialect that resonates with us and moves us forward as we tackle each day’s work. Let’s give it some thought. Further reading This is my immediate “go-to” list of books that I bullishly believe all web designers should own, but there is so much more out there to read. Sadly, many great texts relating to this stuff are often out of print. Feel free to share your recommendations. Don Norman, The Design of Everyday Things Christian Leborg, Visual Grammar Scott McCloud, Understanding Comics David Crow, Visible Signs William Lidwell and Katrina Holden, Universal Principles of Design 2010 Simon Collison simoncollison 2010-12-16T00:00:00+00:00 https://24ways.org/2010/the-articulate-web-designer-of-tomorrow/ process
333 The Attribute Selector for Fun and (no ad) Profit If I had a favourite CSS selector, it would undoubtedly be the attribute selector (Ed: You really need to get out more). For those of you not familiar with the attribute selector, it allows you to style an element based on the existence, value or partial value of a specific attribute. At it’s very basic level you could use this selector to style an element with particular attribute, such as a title attribute. <abbr title="Cascading Style Sheets">CSS</abbr> In this example I’m going to make all <abbr> elements with a title attribute grey. I am also going to give them a dotted bottom border that changes to a solid border on hover. Finally, for that extra bit of feedback, I will change the cursor to a question mark on hover as well. abbr[title] { color: #666; border-bottom: 1px dotted #666; } abbr[title]:hover { border-bottom-style: solid; cursor: help; } This provides a nice way to show your site users that <abbr> elements with title tags are special, as they contain extra, hidden information. Most modern browsers such as Firefox, Safari and Opera support the attribute selector. Unfortunately Internet Explorer 6 and below does not support the attribute selector, but that shouldn’t stop you from adding nice usability embellishments to more modern browsers. Internet Explorer 7 looks set to implement this CSS2.1 selector, so expect to see it become more common over the next few years. Styling an element based on the existence of an attribute is all well and good, but it is still pretty limited. Where attribute selectors come into their own is their ability to target the value of an attribute. You can use this for a variety of interesting effects such as styling VoteLinks. VoteWhats? If you haven’t heard of VoteLinks, it is a microformat that allows people to show their approval or disapproval of a links destination by adding a pre-defined keyword to the rev attribute. For instance, if you had a particularly bad meal at a restaurant, you could signify your dissaproval by adding a rev attribute with a value of vote-against. <a href="http://www.mommacherri.co.uk/" rev="vote-against">Momma Cherri's</a> You could then highlight these links by adding an image to the right of these links. a[rev="vote-against"]{ padding-right: 20px; background: url(images/vote-against.png) no-repeat right top; } This is a useful technique, but it will only highlight VoteLinks on sites you control. This is where user stylesheets come into effect. If you create a user stylesheet containing this rule, every site you visit that uses VoteLinks will receive your new style. Cool huh? However my absolute favourite use for attribute selectors is as a lightweight form of ad blocking. Most online adverts conform to industry-defined sizes. So if you wanted to block all banner-ad sized images, you could simply add this line of code to your user stylesheet. img[width="468"][height="60"], img[width="468px"][height="60px"] { display: none !important; } To hide any banner-ad sized element, such as flash movies, applets or iFrames, simply apply the above rule to every element using the universal selector. *[width="468"][height="60"], *[width="468px"][height="60px"] { display: none !important; } Just bare in mind when using this technique that you may accidentally hide something that isn’t actually an advert; it just happens to be the same size. The Interactive Advertising Bureau lists a number of common ad sizes. Using these dimensions, you can create stylesheet that blocks all the popular ad formats. Apply this as a user stylesheet and you never need to suffer another advert again. Here’s wishing you a Merry, ad-free Christmas. 2005 Andy Budd andybudd 2005-12-11T00:00:00+00:00 https://24ways.org/2005/the-attribute-selector-for-fun-and-no-ad-profit/ code
14 The Command Position Principle Living where I do, in a small village in rural North Wales, getting anywhere means driving along narrow country roads. Most of these are just about passable when two cars meet. If you’re driving too close to the centre of the road, when two drivers meet you stop, glare at each other and no one goes anywhere. Drive too close to your nearside and in summer you’ll probably scratch your paintwork on the hedgerows, or in winter you’ll sink your wheels into mud. Driving these lanes requires a balance between caring for your own vehicle and consideration for someone else’s, but all too often, I’ve seen drivers pushed towards the hedgerows and mud when someone who’s inconsiderate drives too wide because they don’t want to risk scratching their own paintwork or getting their wheels dirty. If you learn to ride a motorcycle, you’ll be taught about the command position: Approximate central position, or any position from which the rider can exert control over invitation space either side. The command position helps motorcyclists stay safe, because when they ride in the centre of their lane it prevents other people, usually car drivers, from driving alongside, either forcing them into the curb or potentially dangerously close to oncoming traffic. Taking the command position isn’t about motorcyclists being aggressive, it’s about them being confident. It’s them knowing their rightful place on the road and communicating that through how they ride. I’ve recently been trying to take that command position when driving my car on our lanes. When I see someone coming in the opposite direction, instead of instinctively moving closer to my nearside — and in so doing subconsciously invite them into my space on the road — I hold both my nerve and a central position in my lane. Since I done this I’ve noticed that other drivers more often than not stay in their lane or pull closer to their nearside so we occupy equal space on the road. Although we both still need to watch our wing mirrors, neither of us gets our paint scratched or our wheels muddy. We can apply this principle to business too, in particular to negotiations and the way we sell. Here’s how we might do that. Commanding negotiations When a customer’s been sold to well — more on that in just a moment — and they’ve made the decision to buy, the thing that usually stands in the way of us doing business is a negotiation over price. Some people treat negotiations as the equivalent of driving wide. They act offensively, because their aim is to force the other person into getting less, usually in return for giving more. In encounters like this, it’s easy for us to act defensively. We might lack confidence in the price we ask for, or the value of the product or service we offer. We might compromise too early because of that. When that happens, there’s a pretty good chance that we’ll drive away with less than we deserve unless we use the command position principle to help us. Before we start any negotiation it’s important to know that both sides ultimately want to reach an agreement. This isn’t always obvious. If one side isn’t already committed, at least in principle, then it’s not a negotiation at that point, it’s something else. For example, a prospective customer may be looking to learn our lowest price so that they can compare it to our competitors. When that’s the case, we’ve probably failed to qualify that prospect properly as, after all, who wants to be chosen simply because they’re the cheapest? In this situation, negotiating is a waste of time since we don’t yet know that it will result in us making a deal. We should enter into a negotiation only when we know where we stand. So ask confidently: “Are you looking to [make a decision]?” When that’s been confirmed, it’s down to everyone to compromise until a deal’s been reached. That’s because good negotiations aren’t about one side beating the other, they’re about achieving a good deal for both. Using the command position principle helps us to maintain control over our negotiating space and affords us the opportunity to give ground only if we need to and only when we’re ready. It can also ensure that the person we’re negotiating with gives up some of their space. Commanding sales It’s not always necessary to negotiate when we’re doing a business deal, but we should always be prepared to sell. One of the most important parts of our sales process should be controlling when and how we tell someone our price. Unless it’s impossible to avoid, don’t work out a price for someone on the spot. When we do that we lose control over the time and place for presenting our price alongside the value factors that will contribute to the prospective customer accepting that price. For the same reason, never give a ballpark or, worse, a guesstimate figure. If the question of price comes up before we’re fully prepared, we should say politely that we need more time to work out a meaningful cost. When we are ready, we shouldn’t email a price for our prospective customer to read unaccompanied. Instead, create an opportunity to talk a prospect through our figures, demonstrate how we arrived at them and, most importantly, explain the value of what we’re selling to their business. Agree a time and place to do this and, if possible, do it all face-to-face. We shouldn’t hesitate when we give someone a price. When we sound even the slightest bit unsure or apologetic, we give the impression that we’ll be flexible in our position before negotiations have even begun. Think about the command position principle, know the price and present it confidently. That way we send a clear signal that we know our business and how we deal with people. The command position principle isn’t about being cocky, it’s about showing other people respect, asking for it in return and showing it to ourselves. Earlier, I mentioned selling well, because we sometimes hear people say that they dislike being sold to. In my experience, it’s not that people dislike the sales process, it’s that we dislike it done badly. Taking part in a good sales process, either by selling or being sold to, can be a pleasurable experience. Try to be confident — after all, we understand how our skills will benefit a customer better than anyone else. Our confidence will inspire confidence in others. Self-confidence isn’t the same as arrogance, just as the command position isn’t the same as riding without consideration for others. The command position principle preserves others’ space as well as our own. By the same token, we should be considerate of others’ time and not waste it and our own by attempting to force them into buying something that’s inappropriate. To prevent this from happening, evaluate them well to ensure that they’re the right customer for us. If they’re not, let them go on their way. They’ll thank us for it and may well become customers the next time we meet. The business of closing a deal can be made an enjoyable experience for everyone if we take control by guiding someone through the sales process by asking the right questions to uncover their concerns, then allaying them by being knowledgeable and confident. This is riding in the command position. Just like demonstrating we know our rightful position on the road, knowing our rightful place in a business relationship and communicating that through how we deal with people will help everyone achieve an equitable balance. When that happens in business, as well as on the road, no one gets their paintwork scratched or their wheels muddy. 2013 Andy Clarke andyclarke 2013-12-23T00:00:00+00:00 https://24ways.org/2013/the-command-position-principle/ business
172 The Construction of Instruction If the world were made to my specifications, all your clients would be happy to pay for a web writer to craft every sentence into something as elegant as it was functional, and the client would have planned the content so that you had it just when you asked, but we both know that won’t happen every time. Sometimes you just know they are going to write the About page, two company blog pages and a Facebook fan page before resigning their position as chief content writer and you are going to end up filling in all the details that will otherwise just be Lorem Ipsum. Welcome to the big world of microcopy: A man walks into a bar. The bartender nods a greeting and watches as the man scans the bottles behind the bar. “Er, you have a lot of gin here. Is there one you would recommend?” “Yes sir.” Long pause. “… Never mind, I’ll have the one in the green bottle.” “Certainly, sir. But you can’t buy it from this part of the bar. You need to go through the double doors there.” “But they look like they lead into the kitchen.” “Really, sir? Well, no, that’s where we allow customers to purchase gin.” The man walks through the doors. On the other side he is greeted by the same bartender. “Y-you!” he stammers but the reticent bartender is now all but silent. Unnerved, the man points to a green bottle, “Er, I’d like to buy a shot of that please. With ice and tonic water.” The bartender mixes the drink and puts it on the bar just out of the reach of the man and looks up. “Um, do you take cards?” the man asks, ready to present his credit card. The bartender goes to take the card to put it through the machine. “Wait! How much was it – with sales tax and everything? Do you take a gratuity?” The bartender simply shrugs. The man eyes him for a moment and decides to try his luck at the bar next door. In the Choose Your Own Adventure version of this story there are plenty of ways to stop the man giving up. You could let him buy the gin right where he was; you could make the price more obvious; you could signpost the place to buy gin. The mistakes made by the bar and bartender are painfully obvious. And yet, there are websites losing users everyday due to the same lack of clear instruction. A smidgen of well written copy goes a long way to reassure the nervous prospect. Just imagine if our man walked into the bar and the bartender explained that although the bar was here, sales were conducted in the next room because people were not then able to overhear the man’s card details. Instead, he is left to fend for himself. Online, we kick customers through the anonymous double doors with a merry ‘Paypal will handle your transaction!’. Recently I worked on a site where the default error message, to account for anything happening that the developers hadn’t accounted for, was ‘SOMETHING HAS GONE WRONG!’. It might have been technically accurate but this is not how to inspire confidence in your customers that they can make a successful purchase through you. As everyone knows they can shop just fine, thank you very much, it is your site they will blame. Card declined? It’s the site. Didn’t know my email address has changed? It’s the site. Can’t log in? It’s the site. Yes, yes. I know. None of these things are related to your site, or you the developer, but drop outs will be high and you’ll get imploring emails from your client asking you to wade knee deep into the site analytics to find a solution by testing 41 shades of blue because if it worked for Google…? Before you try a visual fix involving the Dulux paint chart breeding with a Pantone swatch, take an objective look at the information you are giving customers. How much are you assuming they know? How much are you relying on age-old labels and prompts without clarification? Here’s a fun example for non-North Americans: ask your Granny to write out her billing address. If she looks at you blankly, tell her it is the address where the bank sends her statements. Imagine how many fewer instances of the wrong address there would be if we routinely added that information when people purchased from the UK? Instead, we rely on a language convention that hasn’t much common usage without explanation because, well, because we always have since the banks told us how we could take payments online. So. Your client is busying themselves with writing the ultimate Facebook fan page about themselves and here you are left with creating a cohesive signup process or basket or purchase instructions. Here are five simple rules for bending puny humans to your will creating instructive instructions and constructive error messages that ultimately mean less hassle for you. Plan what you want to say and plan it out as early as possible This goes for all content. Walk a virtual mile in the shoes of your users. What specific help can you offer customers to actively encourage continuation and ensure a minimal amount of dropouts? Make space for that information. One of the most common web content mistakes is jamming too much into a space that has been defined by physical boundaries rather than planned out. If you manage it, the best you can hope for is that no-one notices it was a last-minute job. Mostly it reads like a bad game of Tetris with content sticking out all over the place. Use your words Microcopy often says a lot in a few words but without those words you could leave room for doubt. When doubt creeps in a customer wants reassurance just like Alice: This time (Alice) found a little bottle… with the words ‘DRINK ME’ beautifully printed on it in large letters. It was all very well to say ‘Drink me,’ but the wise little Alice was not going to do that in a hurry. ‘No, I’ll look first,’ she said, ‘and see whether it’s marked “poison” or not’ Alice in Wonderland, Lewis Carroll. Value clarity over brevity. Or a little more prosaically, “If in doubt, spell it out.” Thanks, Jeremy! Be prepared to help ‘Login failed: email/password combination is incorrect.’ Oh. ‘Login failed: email/password combination is incorrect. Are you typing in all capitals? Caps Lock may be on. Have you changed your email address recently and not updated your account with us? Try your old email address first. Can’t remember your password? We can help you reset it.’ Ah! Be direct and be informative There is rarely a site that doesn’t suffer from some degree of jargon. Squash it early by setting a few guidelines about what language and tone of voice you will use to converse with your users. Be consistent. Equally, try to be as specific as possible when giving error messages or instructions and allay fears upfront. Card payments are handled by paypal but you do not need a paypal account to pay. We will not display your email address but we might need it to contact you. Sign up for our free trial (no credit card required). Combine copy and visual cues, learn from others and test new combinations While visual design and copy can work independently, they work best together. New phrases and designs are being tested all the time so take a peek at abtests.com for more ideas, then test some new ideas and add your own results. Have a look at the microcopy pool on Flickr for some wonderful examples of little words and pictures working together. And yes, you absolutely should join the group and post more examples. A man walks into a bar. The bartender greets him in a friendly manner and asks him what he would like to drink. “Gin and Tonic, please.” “Yes sir, we have our house gin on offer but we also have a particularly good import here too.” “The import, please.” “How would you like it? With a slice of lemon? Over ice?” “Both” “That’s £3.80. We accept cash, cards or you could open a tab.” “Card please.” “Certainly sir. Move just over here so that you can’t be observed. Now, please enter your pin number.” “Thank you.” “And here is your drink. Do let me know if there is a problem with it. I shall just be here at the bar. Enjoy.” Cheers! 2009 Relly Annett-Baker rellyannettbaker 2009-12-08T00:00:00+00:00 https://24ways.org/2009/the-construction-of-instruction/ content
117 The First Tool You Reach For Microsoft recently announced that Internet Explorer 8 will be released in the first half of 2009. Compared to the standards support of other major browsers, IE8 will not be especially great, but it will finally catch up with the state of the art in one specific area: support for CSS tables. This milestone has the potential to trigger an important change in the way you approach web design. To show you just how big a difference CSS tables can make, think about how you might code a fluid, three-column layout from scratch. Just to make your life more difficult, give it one fixed-width column, with a background colour that differs from the rest of the page. Ready? Go! Okay, since you’re the sort of discerning web designer who reads 24ways, I’m going to assume you at least considered doing this without using HTML tables for the layout. If you’re especially hardcore, I imagine you began thinking of CSS floats, negative margins, and faux columns. If you did, colour me impressed! Now admit it: you probably also gave an inward sigh about the time it would take to figure out the math on the negative margin overlaps, check for dropped floats in Internet Explorer and generally wrestle each of the major browsers into giving you what you want. If after all that you simply gave up and used HTML tables, I can’t say I blame you. There are plenty of professional web designers out there who still choose to use HTML tables as their main layout tool. Sure, they may know that users with screen readers get confused by inappropriate use of tables, but they have a job to do, and they want tools that will make that job easy, not difficult. Now let me show you how to do it with CSS tables. First, we have a div element for each of our columns, and we wrap them all in another two divs: <div class="container"> <div> <div id="menu"> ⋮ </div> <div id="content"> ⋮ </div> <div id="sidebar"> ⋮ </div> </div> </div> Don’t sweat the “div clutter” in this code. Unlike tables, divs have no semantic meaning, and can therefore be used liberally (within reason) to provide hooks for the styles you want to apply to your page. Using CSS, we can set the outer div to display as a table with collapsed borders (i.e. adjacent cells share a border) and a fixed layout (i.e. cell widths unaffected by their contents): .container { display: table; border-collapse: collapse; table-layout: fixed; } With another two rules, we set the middle div to display as a table row, and each of the inner divs to display as table cells: .container > div { display: table-row; } .container > div > div { display: table-cell; } Finally, we can set the widths of the cells (and of the table itself) directly: .container { width: 100%; } #menu { width: 200px; } #content { width: auto; } #sidebar { width: 25%; } And, just like that, we have a rock solid three-column layout, ready to be styled to your own taste, like in this example: This example will render perfectly in reasonably up-to-date versions of Firefox, Safari and Opera, as well as the current beta release of Internet Explorer 8. CSS tables aren’t only useful for multi-column page layout; they can come in handy in most any situation that calls for elements to be displayed side-by-side on the page. Consider this simple login form layout: The incantation required to achieve this layout using CSS floats may be old hat to you by now, but try to teach it to a beginner, and watch his eyes widen in horror at the hoops you have to jump through (not to mention the assumptions you have to build into your design about the length of the form labels). Here’s how to do it with CSS tables: <form action="/login" method="post"> <div> <div> <label for="username">Username:</label> <span class="input"><input type="text" name="username" id="username"/></span> </div> <div> <label for="userpass">Password:</label> <span class="input"><input type="password" name="userpass" id="userpass"/></span> </div> <div class="submit"> <label for="login"></label> <span class="input"><input type="submit" name="login" id="login" value="Login"/></span> </div> </div> </form> This time, we’re using a mixture of divs and spans as semantically transparent styling hooks. Let’s look at the CSS code. First, we set up the outer div to display as a table, the inner divs to display as table rows, and the labels and spans as table cells (with right-aligned text): form > div { display: table; } form > div > div { display: table-row; } form label, form span { display: table-cell; text-align: right; } We want the first column of the table to be wide enough to accommodate our labels, but no wider. With CSS float techniques, we had to guess at what that width was likely to be, and adjust it whenever we changed our form labels. With CSS tables, we can simply set the width of the first column to something very small (1em), and then use the white-space property to force the column to the required width: form label { white-space: nowrap; width: 1em; } To polish off the layout, we’ll make our text and password fields occupy the full width of the table cells that contain them: input[type=text], input[type=password] { width: 100%; } The rest is margins, padding and borders to get the desired look. Check out the finished example. As the first tool you reach for when approaching any layout task, CSS tables make a lot more sense to your average designer than the cryptic incantations called for by CSS floats. When IE8 is released and all major browsers support CSS tables, we can begin to gradually deploy CSS table-based layouts on sites that are more and more mainstream. In our new book, Everything You Know About CSS Is Wrong!, Rachel Andrew and I explore in much greater detail how CSS tables work as a page layout tool in the real world. CSS tables have their quirks just like floats do, but they don’t tend to affect common layout tasks, and the workarounds tend to be less fiddly too. Check it out, and get ready for the next big step forward in web design with CSS. 2008 Kevin Yank kevinyank 2008-12-13T00:00:00+00:00 https://24ways.org/2008/the-first-tool-you-reach-for/ code
228 The Great Unveiling The moment of unveiling our designs should be among our proudest, but it never seems to work out that way. Instead of a chance to show how we can bring our clients’ visions to life, critique can be a tense, worrying ordeal. And yes, the stakes are high: a superb design is only superb if it goes live. Mismanage the feedback process and your research, creativity and hard work can be wasted, and your client may wonder whether you’ve been worth the investment. The great unveiling is a pivotal part of the design process, but it needn’t be a negative one. Just as usability testing teaches us whether our designs meet user needs, presenting our work to clients tells us whether we’ve met important business goals. So how can we turn the tide to make presenting designs a constructive experience, and to give good designs a chance to shine through? Timing is everything First, consider when you should seek others’ opinions. Your personal style will influence whether you show early sketches or wait to demonstrate something more complete. Some designers thrive at low fidelity, sketching out ideas that, despite their rudimentary nature, easily spark debate. Other designers take time to create more fully-realised versions. Some even argue that the great unveiling should be eliminated altogether by working directly alongside the client throughout, collaborating on the design to reach its full potential. Whatever your individual preference, you’ll rarely have the chance to do it entirely your own way. Contracts, clients, and deadlines will affect how early and often you share your work. However, try to avoid the trap of presenting too late and at too high fidelity. My experience has taught me that skilled designers tend to present their work earlier and allow longer for iteration than novices do. More aware of the potential flaws in their solutions, these designers cling less tightly to their initial efforts. Working roughly and seeking early feedback gives you the flexibility to respond more fully to nuances you may have missed until now. Planning design reviews Present design ideas face-to-face, or at least via video conference. Asynchronous methods like e-mail and Basecamp are slow, easily ignored, and deny you the opportunity to guide your colleagues through your work. In person, you profit from both the well-known benefits of non-verbal communication, and the chance to immediately respond to questions and elaborate on rationale. Be sure to watch the numbers at your design review sessions, however. Any more than a handful of attendees and the meeting could quickly spiral into fruitless debate. Ask your project sponsor to appoint a representative to speak on behalf of each business function, rather than inviting too many cooks. Where possible, show your work in its native format. Photocopy hand-drawn sketches to reinforce their disposability (the defining quality of a sketch) and encourage others to scribble their own thoughts on top. Show digital deliverables – wireframes, design concepts, rich interactions – on screen. The experience of a design is very different on screen than on paper. A monitor has appropriate dimensions and viewport size, presenting an accurate picture of the design’s visual hierarchy, and putting interactive elements in the right context. On paper, a link is merely underlined text. On screen, it is another step along the user’s journey. Don’t waste time presenting multiple concepts. Not only is it costly to work up multiple concepts to the level required for fair appraisal, but the practice demonstrates a sorry abdication of responsibility. Designers should be custodians of design. Asking for feedback on multiple designs turns the critique process into a beauty pageant, relinquishing a designer’s authority. Instead of rational choices that meet genuine user and business needs, you may be stuck with a Frankensteinian monstrosity, assembled from incompatible parts: “This header plus the whizzy bit from Version C”. This isn’t to say that you shouldn’t explore lots of ideas yourself. Divergent thinking early in the design process is the only way to break free of the clichéd patterns and fads that so often litter mediocre sites. But you must act as a design curator, choosing the best of your work and explaining its rationale clearly and succinctly. Attitude, then, is central to successful critique. It can be difficult to tread the fine line between the harmful extremes of doormat passivity and prima donna arrogance. Remember that you are the professional, but be mindful that even experts make mistakes, particularly when – as with all design projects – they don’t possess all the relevant information in advance. Present your case with open-minded confidence, while accepting that positive critique will make your design (and ultimately your skills) stronger. The courage of your convictions Ultimately, your success in the feedback process, and indeed in the entire design process, hinges upon the rationale you provide for your work. Ideally, you should be able to refer to your research – personas, usability test findings, analytics – to support your decisions. To keep this evidence in mind, print it out to share at the design review, or include it in your presentation. Explain the rationale behind the most important decisions before showing the design, so that you can be sure of the full attention of your audience. Once you’ve covered these points, display your design and walk through the specific features of the page. A little honesty goes a long way here: state your case as strongly as your rationale demands. Sure of your reasoning? Be strong. Speculating an approach based on a hunch? Say so, and encourage your colleagues to explore the idea with you and see where it leads. Of course, none of these approaches should be sacrosanct. A proficient designer must be able to bend his or her way of working to suit the situation at hand. So sometimes you’ll want to ignore these rules of thumb and explore your own hunches as required. More power to you. As long as you think as clearly about the feedback process as you have about the design itself, you’ll be able to enjoy the great unveiling as a moment to be savoured, not feared. 2010 Cennydd Bowles cennyddbowles 2010-12-12T00:00:00+00:00 https://24ways.org/2010/the-great-unveiling/ business
116 The IE6 Equation It is the destiny of one browser to serve as the nemesis of web developers everywhere. At the birth of the Web Standards movement, that role was played by Netscape Navigator 4; an outdated browser that refused to die. Its tenacious existence hampered the adoption of modern standards. Today that role is played by Internet Explorer 6. There’s a sensation that I’m sure you’re familiar with. It’s a horrible mixture of dread and nervousness. It’s the feeling you get when—after working on a design for a while in a standards-compliant browser like Firefox, Safari or Opera—you decide that you can no longer put off the inevitable moment when you must check the site in IE6. Fingers are crossed, prayers are muttered, but alas, to no avail. The nemesis browser invariably screws something up. What do you do next? If the differences in IE6 are minor, you could just leave it be. After all, websites don’t need to look exactly the same in all browsers. But if there are major layout issues and a significant portion of your audience is still using IE6, you’ll probably need to roll up your sleeves and start fixing the problems. A common approach is to quarantine IE6-specific CSS in a separate stylesheet. This stylesheet can then be referenced from the HTML document using conditional comments like this: <!--[if lt IE 7]> <link rel="stylesheet" href="ie6.css" type="text/css" media="screen" /> <![endif]--> That stylesheet will only be served up to Internet Explorer where the version number is less than 7. You can put anything inside a conditional comment. You could put a script element in there. So as well as serving up browser-specific CSS, it’s possible to serve up browser-specific JavaScript. A few years back, before Microsoft released Internet Explorer 7, JavaScript genius Dean Edwards wrote a script called IE7. This amazing piece of code uses JavaScript to make Internet Explorer 5 and 6 behave like a standards-compliant browser. Dean used JavaScript to bootstrap IE’s CSS support. Because the script is specifically targeted at Internet Explorer, there’s no point in serving it up to other browsers. Conditional comments to the rescue: <!--[if lt IE 7]> <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE7.js" type="text/javascript"></script> <![endif]--> Standards-compliant browsers won’t fetch the script. Users of IE6, on the hand, will pay a kind of bad browser tax by having to download the JavaScript file. So when should you develop an IE6-specific stylesheet and when should you just use Dean’s JavaScript code? This is the question that myself and my co-worker Natalie Downe set out to answer one morning at Clearleft. We realised that in order to answer that question you need to first answer two other questions, how much time does it take to develop for IE6? and how much of your audience is using IE6? Let’s say that t represents the total development time. Let t6 represent the portion of that time you spend developing for IE6. If your total audience is a, then a6 is the portion of your audience using IE6. With some algebraic help from our mathematically minded co-worker Cennydd Bowles, Natalie and I came up with the following equation to calculate the percentage likelihood that you should be using Dean’s IE7 script: p = 50 [ log ( at6 / ta6 ) + 1 ] Try plugging in your own numbers. If you spend a lot of time developing for IE6 and only a small portion of your audience is using that browser, you’ll get a very high number out of the equation; you should probably use the IE7 script. But if you only spend a little time developing for IE6 and a significant portion of you audience are still using that browser, you’ll get a very small value for p; you might as well write an IE6-specific stylesheet. Of course this equation is somewhat disingenuous. While it’s entirely possible to research the percentage of your audience still using IE6, it’s not so easy to figure out how much of your development time will be spent developing for that one browser. You can’t really know until you’ve already done the development, by which time the equation is irrelevant. Instead of using the equation, you could try imposing a limit on how long you will spend developing for IE6. Get your site working in standards-compliant browsers first, then give yourself a time limit to get it working in IE6. If you can’t solve all the issues in that time limit, switch over to using Dean’s script. You could even make the time limit directly proportional to the percentage of your audience using IE6. If 20% of your audience is still using IE6 and you’ve just spent five days getting the site working in standards-compliant browsers, give yourself one day to get it working in IE6. But if 50% of your audience is still using IE6, be prepared to spend 2.5 days wrestling with your nemesis. All of these different methods for dealing with IE6 demonstrate that there’s no one single answer that works for everyone. They also highlight a problem with the current debate around dealing with IE6. There’s no shortage of blog posts, articles and even entire websites discussing when to drop support for IE6. But very few of them take the time to define what they mean by “support.” This isn’t a binary issue. There is no Boolean answer. Instead, there’s a sliding scale of support: Block IE6 users from your site. Develop with web standards and don’t spend any development time testing in IE6. Use the Dean Edwards IE7 script to bootstrap CSS support in IE6. Write an IE6 stylesheet to address layout issues. Make your site look exactly the same in IE6 as in any other browser. Each end of that scale is extreme. I don’t think that anybody should be actively blocking any browser but neither do I think that users of an outdated browser should get exactly the same experience as users of a more modern browser. The real meanings of “supporting” or “not supporting” IE6 lie somewhere in-between those extremes. Just as I think that semantics are important in markup, they are equally important in our discussion of web development. So let’s try to come up with some better terms than using the catch-all verb “support.” If you say in your client contract that you “support” IE6, define exactly what that means. If you find yourself in a discussion about “dropping support” for IE6, take the time to explain what you think that entails. The web developers at Yahoo! are on the right track with their concept of graded browser support. I’m interested in hearing more ideas of how to frame this discussion. If we can all agree to use clear and precise language, we stand a better chance of defeating our nemesis. 2008 Jeremy Keith jeremykeith 2008-12-08T00:00:00+00:00 https://24ways.org/2008/the-ie6-equation/ code
25 The Introvert Owner’s Manual Nobody realizes that some people expend tremendous energy merely to be normal. Albert Camus “Whatever you plan, just make sure there are lots of people there,” said my husband in the run-up to his birthday last year. A few months later, before my own birthday, I uttered, “Whatever you plan, just make sure it is only me and you.” I am an introvert. It is very likely some of you are too, or that you live, work or fraternise with one. Despite there being quite a few of us out there – some say as many as one third of the population, others as little as ten per cent – I think our professional and social lives are biased towards a definition of normality that is more accepting of the extrovert. I hope that by reading this article you will gain some insight to what goes on inside the head of the introvert(s) that you know and understand how to relate to them in a way that respects their disposition. Before we go any further, I should define what exactly being an introvert means, and, equally important, what it does not. Only once this is established will you be able to handle your introvert correctly. What defines an introvert The simplest and most accurate way of describing an introvert is that she uses up energy in social situations and needs to be in solitude to recharge. To explain what I mean, let us take the example of the The Sims: when you create a Sim, you can choose (among other characteristics) whether it will be outgoing or not. If the Sim is outgoing, when you play the game you need to make sure it interacts as much as possible with other Sims or its mood indicator (the plumbob) will become red and that is a bad thing. Conversely, if your Sim is not outgoing, when you put it in too many social situations its plumbob will become red too. So your (real life) introvert might think you are great (you might even be her best friend, her spouse or her child), but if her plumbob is red, or nearly, she might just need a little time and space to recharge before she is ready to interact. This is not the same thing as being shy or in a bad mood all the time. We are not necessarily awkward in social situations, but, if we have not had the time to recharge, being social might be almost impossible. This explains why your introvert will likely ask who will be at the gathering you have planned, for how long she will have to stay there, and what she will be doing before and after the event. It is the equivalent of you wanting to know if there will be power sockets in the restaurant to charge your iPhone – asking this does not mean you don’t want to attend. The explanation above might be a simplistic way of looking at things, but I would say it is one that introverts can relate to; call it a minimalist approach to socialisation. Caring for your introvert Articles and conversations about introversion usually focus on how to fix the condition and how to make introverts more outgoing: a clear example of our society’s bias towards the normality of extroversion. Avoid this. You will not be able to convert your introvert into an extrovert. Believe it or not, there is nothing wrong with her. In her 2012 TED talk, “The power of introverts”, Susan Cain pointed to the fact that places like school and work are designed for extroverts: students and workers are required to constantly work in groups and speaking up is highly valued. Both types are evaluated against the same criteria and more often than not people are expected to excel at being outspoken to be considered well rounded. Obviously, this is not the right way to appraise your introvert. Comparing your introvert with an extrovert using the same parameters and simply asking her to behave more like an extrovert is a mistake and something that will only perpetuate an introvert’s idea that the problem lies with her. Speaking up Your introvert is likely to have strong opinions and ideas, and to have been listening to other people speak at meetings and workshops. Help her voice those thoughts by creating an environment where everyone stops and listens when someone speaks instead of one which fosters interruptions. Show her that it is acceptable for someone to take time to think before they speak: silences are OK. Allow her the freedom to be herself instead of pressuring her to change an innate quality. It is not uncommon to find an introvert who likes to express ideas in writing. The world of web professionals excels in the spread of knowledge that is shared and sought through the written word. Give your introvert the necessary time and tools to write about the job, if she is that way inclined; this might be a good alternative to asking her to speak out. Group work I remember the sinking feeling whenever I heard my teachers say the dreaded words: “And now you’re going to break out into groups of…” Being an introvert does not mean you do not like people (or like to be around or work with others). It is just that activities such as group work will invariably drain your introvert’s energy rapidly. Your introvert’s batteries will need to be fully charged for her to be at her best and afterwards she will most likely need to recharge. Quiet time These days, one of the things that I value most at work is the ability to have moments to create and to think in solitude. When I am able to have those moments at the right time I will in turn be happy to participate in group conversations and tasks. Allow your introvert to have those moments: this does not mean she will have to work from home one day a week (but maybe it will); it might simply mean allowing her to take her laptop and her notebook and work from the empty side of the office, or from the coffee shop downstairs for an hour or two. In all likelihood she will come back fully recharged and ready to engage in more social activities – her plumbob will again be bright green. Leadership Do not think that your introvert cannot lead. Cain notes that introverted leaders are more likely to let their proactive employees run with their ideas instead of taking the ideas as their own. I would say that is a positive attribute in a leader. Maybe next time a project starts, talk to your introvert about the possibility of her being in a leadership position or of having more responsibility: you might be surprised at her ability to plan and foresee potential obstacles in the project. Final thoughts You would not tell someone with dyslexia to get better at spelling without giving her the right tools and enough time to do so. Equally, do not ask your introvert to be more outgoing, or to turn her frown upside down, without giving her the space to do so. I believe that everyone is an introvert at some point. Everyone needs a moment of solitude now and then, and the work we do requires frequent periods of deep focus and concentration. Striving to create workplaces, classrooms, homes that allow introverts to shine and be comfortable in their skin has the potential to also make those places more balanced for everyone else. Resources and further reading The power of introverts 10 myths about introverts Susan Cain’s 2014 TED Talk | Announcing the Quiet Revolution Help Shy Kids — Don’t Punish Them The Introvert Advantage 6 Things You Thought Wrong About Introverts Extraversion and introversion 2014 Inayaili de León Persson inayailideleon 2014-12-13T00:00:00+00:00 https://24ways.org/2014/the-introvert-owners-manual/ process
144 The Mobile Web, Simplified A note from the editors: although eye-opening in 2006, this article is no longer relevant to today’s mobile web. Considering a foray into mobile web development? Following are four things you need to know before making the leap. 1. 4 billion mobile subscribers expected by 2010 Fancy that. Coupled with the UN prediction of 6.8 billion humans by 2010, 4 billion mobile subscribers (source) is an astounding 59% of the planet. Just how many of those subscribers will have data plans and web-enabled phones is still in question, but inevitably this all means one thing for you and me: A ton of potential eyes to view our web content on a mobile device. 2. Context is king Your content is of little value to users if it ignores the context in which it is viewed. Consider how you access data on your mobile device. You might be holding a bottle of water or gripping a handle on the subway/tube. You’re probably seeking specific data such as directions or show times, rather than the plethora of data at your disposal via a desktop PC. The mobile web, a phrase often used to indicate “accessing the web on a mobile device”, is very much a context-, content-, and component-specific environment. Expressed in terms of your potential target audience, access to web content on a mobile device is largely influenced by surrounding circumstances and conditions, information relevant to being mobile, and the feature set of the device being used. Ask yourself, What is relevant to my users and the tasks, problems, and needs they may encounter while being mobile? Answer that question and you’ll be off to a great start. 3. WAP 2.0 is an XHTML environment In a nutshell, here are a few fundamental tenets of mobile internet technology: Wireless Application Protocol (WAP) is the protocol for enabling mobile access to internet content. Wireless Markup Language (WML) was the language of choice for WAP 1.0. Nearly all devices sold today are WAP 2.0 devices. With the introduction of WAP 2.0, XHTML Mobile Profile (XHTML-MP) became the preferred markup language. XHTML-MP will be familiar to anyone experienced with XHTML Transitional or Strict. Summary? The mobile web is rapidly becoming an XHTML environment, and thus you and I can apply our existing “desktop web” skills to understand how to develop content for it. With WML on the decline, the learning curve is much smaller today than it was several years ago. I’m generalizing things gratuitously, but the point remains: Get off yo’ lazy butt and begin to take mobile seriously. I’ll even pass you a few tips for getting started. First, the DOCTYPE for XHTML-MP is as follows: <!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile10.dtd"> As for MIME type, Open Mobile Alliance (OMA) specifies using the MIME type application/vnd.wap.xhtml+xml, but ultimately you need to ensure the server delivering your mobile content is configured properly for the MIME type you choose to use, as there are other options (see Setting up WAP Servers). Once you’ve made it to the body, the XHTML-MP markup is not unlike what you’re already used to. A few resources worth skimming: Developers Home XHTML-MP Tutorial – An impressively replete resource for all things XHTML-MP XHTML-MP Tags List – A complete list of XHTML-MP elements and accompanying attributes And last but certainly not least, CSS. There exists WAP CSS, which is essentially a subset of CSS2 with WAP-specific extensions. For all intents and purposes, much of the CSS you’re already comfortable using will be transferrable to mobile. As for including CSS in your pages, your options are the same as for desktop sites: external, embedded, and inline. Some experts will argue embedded or inline over external in favor of reducing the number of HTTP connections per page request, yet many popular mobilized sites and apps employ external linking without issue. Stocking stuffers: Flickr Mobile, Fandango Mobile, and Popurls Mobile. A few sites with whom you can do the View Source song and dance for further study. 4. “Cell phone” is so DynaTAC If you’re a U.S. resident, listen up: You must rid your vocabulary of the term “cell phone”. We’re one of the few economies on the planet to refer to a mobile phone accordingly. If you care to find yourself in any of the worthwhile mobile development circles, begin using terms more widely accepted: “mobile” or “mobile phone” or “handset” or “handy”. If you’re not sure which, go for “mobile”. Such as, “Yo dog, check out my new mobile.” More importantly, however, is overcoming the mentality that access to the mobile web can be done only with a phone. Instead, “device” encourages us to think phone, handheld computer, watch, Nintendo DS, car, you name it. Simple enough? 2006 Cameron Moll cameronmoll 2006-12-19T00:00:00+00:00 https://24ways.org/2006/the-mobile-web-simplified/ ux
145 The Neverending (Background Image) Story Everyone likes candy for Christmas, and there’s none better than eye candy. Well, that, and just more of the stuff. Today we’re going to combine both of those good points and look at how to create a beautiful background image that goes on and on… forever! Of course, each background image is different, so instead of agonising over each and every pixel, I’m going to concentrate on five key steps that you can apply to any of your own repeating background images. In this example, we’ll look at the Miami Beach background image used on the new FOWA site, which I’m afraid is about as un-festive as you can get. 1. Choose your image wisely I find there are three main criteria when judging photos you’re considering for repetition manipulation (or ‘repetulation’, as I like to say)… simplicity (beware of complex patterns) angle and perspective (watch out for shadows and obvious vanishing points) consistent elements (for easy cloning) You might want to check out this annotated version of the image, where I’ve highlighted elements of the photo that led me to choose it as the right one. The original image purchased from iStockPhoto. The Photoshopped version used on the FOWA site. 2. The power of horizontal lines With the image chosen and your cursor poised for some Photoshop magic, the most useful thing you can do is drag out the edge pixels from one side of the image to create a kind of rough colour ‘template’ on which to work over. It doesn’t matter which side you choose, although you might find it beneficial to use the one with the simplest spread of colour and complex elements. Click and hold on the marquee tool in the toolbar and select the ‘single column marquee tool’, which will span the full height of your document but will only be one pixel wide. Make the selection right at the edge of your document, press ctrl-c / cmd-c to copy the selection you made, create a new layer, and hit ctrl-v / cmd-v to paste the selection onto your new layer. using free transform (ctrl-t / cmd-t), drag out your selection so that it becomes as wide as your entire canvas. A one-pixel-wide selection stretched out to the entire width of the canvas. 3. Cloning It goes without saying that the trusty clone tool is one of the most important in the process of creating a seamlessly repeating background image, but I think it’s important to be fairly loose with it. Always clone on to a new layer so that you’ve got the freedom to move it around, but above all else, use the eraser tool to tweak your cloned areas: let that handle the precision stuff and you won’t have to worry about getting your clones right first time. In the example below, you can see how I overcame the problem of the far-left tree shadow being chopped off by cloning the shadow from the tree on its right. The edge of the shadow is cut off and needs to be ‘made’ from a pre-existing element. The successful clone completes the missing shadow. The two elements are obviously very similar but it doesn’t look like a clone because the majority of the shape is ‘genuine’ and only a small part is a duplicate. Also, after cloning I transformed the duplicate, erased parts of it, used gradients, and — ooh, did someone mention gradients? 4. Never underestimate a gradient For this image, I used gradients in a similar way to a brush: covering large parts of the canvas with a colour that faded out to a desired point, before erasing certain parts for accuracy. Several of the gradients and brushes that make up the ‘customised’ part of the image, visible when the main photograph layer is hidden. The full composite. Gradients are also a bit of an easy fix: you can use a gradient on one side of the image, flip it horizontally, and then use it again on the opposite side to make a more seamless join. Speaking of which… 5. Sewing the seams No matter what kind of magic Photoshop dust you sprinkle over your image, there will still always be the area where the two edges meet: that scary ‘loop’ point. Fret ye not, however, for there’s help at hand in the form of a nice little cheat. Even though the loop point might still be apparent, we can help hide it by doing something to throw viewers off the scent. The seam is usually easy to spot because it’s a blank area with not much detail or colour variation, so in order to disguise it, go against the rule: put something across it! This isn’t quite as challenging as it may sound, because if we intentionally make our own ‘object’ to span the join, we can accurately measure the exact halfway point where we need to split it across the two sides of the image. This is exactly what I did with the FOWA background image: I made some clouds! A sky with no clouds in an unhappy one. A simple soft white brush creates a cloud-like formation in the sky. After taking the cloud’s opacity down to 20%, I used free transform to highlight the boundaries of the layer. I then moved it over to the right, so that the middle of the layer perfectly aligned with the right side of the canvas. Finally, I duplicated the layer and did the same in reverse: dragging the layer over to the left and making sure that the middle of the duplicate layer perfectly aligned with the left side of the canvas. And there you have it! Boom! Ta-da! Et Voila! To see the repeating background image in action, visit futureofwebapps.com on a large widescreen monitor or see a simulation of the effect. Thanks for reading, folks. Have a great Christmas! 2007 Elliot Jay Stocks elliotjaystocks 2007-12-03T00:00:00+00:00 https://24ways.org/2007/the-neverending-background-image-story/ code
22 The Responsive Hover Paradigm CSS transitions and animations provide web designers with a whole slew of tools to spruce up our designs. Move over ActionScript tweens! The techniques we can now implement with CSS are reminiscent of Flash-based adventures from the pages of web history. Pairing CSS enhancements with our :hover pseudo-class allows us to add interesting events to our websites. We have a ton of power at our fingertips. However, with this power, we each have to ask ourselves: just because I can do something, should I? Why bother? We hear a lot of mantras in the web community. Some proclaim the importance of content; some encourage methods like mobile first to support content; and others warn of the overhead and speed impact of decorative flourishes and visual images. I agree, one hundred percent. At the same time, I believe that content can reign king and still provide a beautiful design with compelling interactions and acceptable performance impacts. Maybe, just maybe, we can even have a little bit of fun when crafting these systems! Yes, a site with pure HTML content and no CSS will load very fast on your mobile phone, but it leaves a lot to be desired. If you went to your local library and every book looked the same, how would you know which one to borrow? Imagine if every book was printed on the same paper stock with the same cover page in the same type size set at a legible point value… how would you know if you were going to purchase a cookbook about wild game or a young adult story about teens fighting to the death? For certain audiences, seeing a site with hip, lively hovers sure beats a stale website concept. I’ve worked on many higher education sites, and setting the interactive options is often a very important factor in engaging potential students, alumni, and donors. The same can go for e-commerce sites: enticing your audience with surprise and delight factors can be the difference between a successful and a lost sale. Knowing your content and audience can help you decide if an intriguing experience is appropriate for your site; if it is, then hover responses can be a real asset. Why hover? We have all these capabilities with CSS properties to create the aforementioned fun interactions, and it would be quite easy to fall back into some old patterns and animation abuse. The world of Flash intros and skip links could be recreated with CSS keyframes. However, I don’t think any of us want to go the route of forcing users into unwanted exchanges and road blocking content. What’s great about utilizing hover to pair with CSS powered actions is that it’s user initiated. It’s a well-established expectation that when a user mouses over an object, something changes. If we can identify that something as a link, then we will expect something to change as we move our mouse over it. By waiting to trigger a CSS-based response until a user chooses to engage with a target makes for a more polished experience (as opposed to barraging our screens with animations all willy-nilly). This makes it the perfect opportunity to add some unique spunk. What about mobile, touch, and responsive? So, you’re on board with this so far, but what about mobile and touch devices? Sure, some devices like the Samsung Galaxy S4 have some hovering capabilities, but certainly most do not. Beyond mobile devices, we also have to worry about desktops with touch capabilities. It’s super difficult to detect if a user is currently using touch or hover. One option we have is to design strictly for touch only and send hover enhancements to the graveyard. However, being that I’m all “fuck yeah hovers!,” I like to explore all options. So, let’s examine four different types of hover patterns and see how they can translate to our touch devices. 1. The essential text hover Changing text color on hover is something we’ve done for a while and it has helped aid in identifying links. To maintain the best accessibility we can achieve, it helps to have a different visual indicator on the default :link state, such as an underline. By making sure all text links have an underline, we won’t have to rely on visual changes during hover to make sure touch device users know that it is a link. For hover-enabled devices, we can add a basic color transition. Doing so creates a nice fade, which makes the change on hover less jarring. Kinda like smooth jazz. The code* to achieve this is quite simple: a { color: #6dd4b1; transition: color 0.25s linear; } a:hover, a:focus { color: #357099; } Browser prefixes are omitted You can see in the final result that, for both touch and hover, everyone wins: See the Pen Most Basic Link Transition by Jenn Lukas (@Jenn) on CodePen 2. Visual background wizardry and animated hovers We can take this a step further by again making changes to our aesthetic on hover, but not making any content changes. Altering image hovers for fun and personality can separate your site from others; that personality is important and can enhance our content. Let’s look at a few sites that do this really well. Scroll down to the judges section of CSS Off and check out the illustrations of the judges. On hover, the illustration fades into a photo of the judge. This provides a realistic alternative to the drawing. Users without the hover can click into the detail page, where they can see the full color picture and learn more about the judges; the information is still available through a different pathway. Going back to the higher education field, let’s visit Delaware Valley College. The school had recently gone through a rebranding that included loop icons as a symbol to connect ideas. These icons are brought into the website on hover of the slideshow arrows (WebKit browsers). The hover reveals a loop animation, tying in overall themes and adding some extra pizzazz that makes me think, “This is a hip place that feels current.” For visitors who can’t access the hover effect, the default arrow state clearly represents a clickable link, and there is swipe functionality on mobile devices to boot. DIY.org’s Frontend Dev page has a bunch of enjoyable hover actions happening, featuring scaling transforms and looping animations. Nothing new is revealed on hover, so touch devices won’t miss anything, but it intrigues the user who is visiting a site about front-end dev doing cool front-end things. It backs up its claim of front-end knowledge by adding this enhancement. The old Cowork Chicago (now redirecting) had a great example, captured here: Coop: Chicago Coworking from Jenn Lukas on Vimeo. The code for the Join areas is quite simple: .join-buttons .daily, .join-buttons .monthly { height: 260px; z-index: 0; margin-top: 30px; transition: height .2s linear,margin .2s linear; } .join-buttons .daily:hover, .join-buttons .monthly:hover { height: 280px; margin-top: 20px; } li.button:hover { z-index: 20; } The slight rotation on the photos, and the change of color and size of the rate options on hover, add to the fun factor. The site attempts to advertise the co-working space by letting bits of their charisma show through with these transitions. They don’t hit the user over the head with animations, but provide a nice addition to make sure visitors know it’s a welcoming place to work. Some text is added on the hover, but the text isn’t essential to determine where the link goes. 3. Image block hovers There have been more designs popping up with large image blocks acting as extensive hit area links to subsequent pages. On hover of these links, text is revealed, letting the user know where the link destination goes. See the Pen Transitioning Max Height by Jenn Lukas (@Jenn) on CodePen This type of link is tough for users on touch as the image might not provide enough context to reveal its target. If you weren’t aware of what my illustrated avatar from 2007 looked like (or even if you did), then how would you know that this is a link to my Twitter page? Instead, if we provide enough context — such as the @jennlukas handle — you could assume the destination. Users who receive the hover can also see the Twitter bio. It won’t break the experience for users that can’t hover, but it will provide a nice interaction and some more information for those that can. See the Pen Transitioning Max Height by Jenn Lukas (@Jenn) on CodePen The Esquire site follows this same pattern, in which the title of the story is shown and the subheading is revealed on hover. Dining at Altitude took the opposite approach, where all text is shown by default and, on hover, you can see more of the image that the text sits atop. This is a nice technique to follow. For touch users, following the link will allow them to see more of the image detail that was revealed on hover. 4. Drop-down navigation menu hovers Main navigation options that rely on hover have come up as a problem for touch. One way to address this is to be sure your top level items are all functional links to somewhere, and not blank anchors to trigger a submenu drop-down. This ensures that, even without the hover-triggered menu, users can still navigate to those top-level pages. From there, they should be able to access the tertiary pages shown in the drop-down. Following this arrangement, drop-down menus act as a quick shortcut and aren’t necessary to the navigational structure. If the top navigation items are your most visited pages, this execution won’t hinder your visitors. If the information within the menu is vital, such as a lone account menu, another option is to show drop-down menus on click instead of hover. This pattern will allow both mouse and touch users to access the drop-downs. Why can’t we just detect hover? This is a really tricky thing to do. Internet Explorer 10 on Windows 8 uses the aria-haspopup attribute to simulate hover on touch devices, but usually our audience stretches beyond that group. There’s been discussion around using Modernizr, but false positives have come with that. A W3C draft for Media Queries Level 4 includes a hover feature, but it’s not supported yet. Since some devices can hover and touch, should you rely on hover effects for those? Arguments have come up that users can be browsing your site with a mouse and then decide to switch to touch, or vice versa. That might be a large concern for you, or it might be an edge case that isn’t vital to your site’s success. For one site, I used mousemove and touchstart JavaScript events in order to detect if a visitor starts to browse the site with a mouse. The design initiates for touch users, showing all text on load, but as soon as a mouse movement occurs, the text becomes hidden and is then revealed on hover. See the Pen Detect Touch devices with mousemove and touchstart by Jenn Lukas (@Jenn) on CodePen One downside to this approach is that the text is viewable until a mouse enters the document, but if the elements are further down the page it might not be noticed. A second downside is if a user on a touch- and hover-enabled device starts browsing with the mouse and then switches back to touch, the hover-centric styles will remain until a new page load. These were acceptable scenarios in the project I worked on, but might not be for every project. Can we give our visitors a choice? I’ve been thinking about how we can combat the concern of not knowing if our customers are using touch or a mouse, not to mention keyboard or Wacom tablets or Minority Report screens. We can cover keyboards with our friend :focus, but that still doesn’t solve our other dilemmas. Remember when we couldn’t rely on browsers to zoom text and we had to use those small A, medium A, big A [AAA] buttons? On selection of one of those options, a different style sheet would load with small, medium, or large text sizes to satisfy our user’s request. We could even set cookies to remember their font choices. What if we offered a similar solution, a hover/touch switcher, for our new predicament? See the Pen cwuJf by Jenn Lukas (@Jenn) on CodePen We could add this switcher to our design. Maybe add it to the header on smaller screens and the footer on larger screens to play the odds. Then be sure to deliver the appropriate touch- or hover-optimized adventure for our guests. How about adding View options in the areas where we’re hiding content until hover? Looking at Delta Cycle, there’s logic in place to switch layouts on some mobile devices. On desktops we can see the layout shows the product and price by default, and the name of the item and an Add to cart button on hover. If you want to keep this hover, but also worry that touch users can’t access it — or even if you are concerned that people might want to view it with more details up front — we could add another view switcher. See the Pen List/Grid Views for Hover or Touch by Jenn Lukas (@Jenn) on CodePen Similar to the list versus grid view we often see in operating systems, a choice here could cover all of our bases. Conclusion There is no one-size-fits-all solution when it comes to hover patterns. Design for your content. If you are providing important information about driving directions or healthcare, you might want to err on the side of designing for touch only. If you are behind an educational site and trying to entice more traffic and sign-ups, or a more immersive e-commerce site selling pies, then hover activity can help support your content and engage your visitors without being a detriment. While content can be our top priority, let’s not forget that our designs and interactions, hovers included, can have a great positive impact on how visitors experience our site. Hover wisely, friends. 2013 Jenn Lukas jennlukas 2013-12-12T00:00:00+00:00 https://24ways.org/2013/the-responsive-hover-paradigm/  
251 The System, the Search, and the Food Bank Imagine a warehouse, half the length of a football field, with a looped conveyer belt down the center. On the belt are plastic bins filled with assortments of shelf-stable food—one may have two bags of potato chips, seventeen pudding cups, and a box of tissues; the next, a dozen cans of beets. The conveyer belt is ringed with large, empty cardboard boxes, each labeled with categories like “Bottled Water” or “Cereal” or “Candy.” Such was the scene at my local food bank a few Saturdays ago, when some friends and I volunteered for a shift sorting donated food items. Our job was to fill the labeled cardboard boxes with the correct items nabbed from the swiftly moving, randomly stocked plastic bins. I could scarcely believe my good fortune of assignments. You want me to sort things? Into categories? For several hours? And you say there’s an element of time pressure? Listen, is there some sort of permanent position I could be conscripted into. Look, I can’t quite explain it: I just know that I love sorting, organizing, and classifying things—groceries at a food bank, but also my bookshelves, my kitchen cabinets, my craft supplies, my dishwasher arrangement, yes I am a delight to live with, why do you ask? The opportunity to create meaning from nothing is at the core of my excitement, which is why I’ve tried to build a career out of organizing digital content, and why I brought a frankly frightening level of enthusiasm to the food bank. “I can’t believe they’re letting me do this,” I whispered in awe to my conveyer belt neighbor as I snapped up a bag of popcorn for the Snacks box with the kind of ferocity usually associated with birds of prey. The jumble of donated items coming into the center need to be sorted in order for the food bank to be able to quantify, package, and distribute the food to those who need it (I sense a metaphor coming on). It’s not just a nice-to-have that we spent our morning separating cookies from carrots—it’s a crucial step in the process. Organization makes the difference between chaos and sense, between randomness and usefulness, whether we’re talking about donated groceries or—there it is—web content. This happens through the magic of criteria matching. In order for us to sort the food bank donations correctly, we needed to know not only the categories we were sorting into, but also the criteria for each category. Does canned ravioli count as Canned Soup? Does enchilada sauce count as Tomatoes? Do protein bars count as Snacks? (Answers: yes, yes, and only if they are under 10 grams of protein or will expire within three months.) Is X a Y? was the question at the heart of our food sorting—but it’s also at the heart of any information-seeking behavior. When we are organizing, or looking for, any kind of information, we are asking ourselves: What is the criteria that defines Y? Does X meet that criteria? We don’t usually articulate it so concretely because it’s a background process, only leaping to consciousness when we encounter a stumbling block. If cans of broth flew by on the conveyer belt, it didn’t require much thought to place them in the Canned Soup box. Boxed broth, on the other hand, wasn’t allowed, causing a small cognitive hiccup—this X is NOT a Y—that sometimes meant having to re-sort our boxes. On the web, we’re interested—I would hope—in reducing cognitive hiccups for our users. We are interested in making our apps easy to use, our websites easy to navigate, our information easy to access. After all, most of the time, the process of using the internet is one of uniting a question with an answer—Is this article from a trustworthy source? Is this clothing the style I want? Is this company paying their workers a living wage? Is this website one that can answer my question? Is X a Y? We have a responsibility, therefore, to make information easy for our users to find, understand, and act on. This means—well, this means a lot of things, and I’ve got limited space here, so let’s focus on these three lessons from the food bank: Use plain, familiar language. This advice seems to be given constantly, but that’s because it’s solid and it’s not followed enough. Your menu labels, page names, and headings need to reflect the word choice of your users. Think how much harder it would have been to sort food if the boxes were labeled according to nutritional content, grocery store aisle number, or Latin name. How much would it slow sorting down if the Tomatoes box were labeled Nightshades? It sounds silly, but it’s not that different from sites that use industry jargon, company lingo, acronyms (oh, yes, I’ve seen it), or other internally focused language when trying to provide wayfinding for users. Choose words that your audience knows—not only will they be more likely to spot what they’re looking for on your site or app, but you’ll turn up more often in search results. Create consistency in all things. Missteps in consistency look like my earlier chicken broth example—changing up how something looks, sounds, or functions creates a moment of cognitive dissonance, and those moments add up. The names of products, the names of brands, the names of files and forms and pages, the names of processes and procedures and concepts—these all need to be consistently spelled, punctuated, linked, and referenced, no matter what section or level the user is in. If submenus are visible in one section, they should be visible in all. If calls-to-action are a graphic button in one section, they are the same graphic button in all. Every affordance, every module, every design choice sets up user expectations; consistency keeps those expectations afloat, making for a smoother experience overall. Make the system transparent. By this, I do not mean that every piece of content should be elevated at all times. The horror. But I do mean that we should make an effort to communicate the boundaries of the digital space from any given corner within. Navigation structures operate just as much as a table of contents as they do a method of moving from one place to another. Page hierarchies help explain content relationships, communicating conceptual relevancy and relative importance. Submenus illustrate which related concepts may be found within a given site section. Take care to show information that conveys the depth and breadth of the system, rather than obscuring it. This idea of transparency was perhaps the biggest challenge we experienced in food sorting. Imagine us volunteers as users, each looking for a specific piece of information in the larger system. Like any new visitor to a website, we came into the system not knowing the full picture. We didn’t know every category label around the conveyer belt, nor what criteria each category warranted. The system wasn’t transparent for us, so we had to make it transparent as we went. We had to stop what we were doing and ask questions. We’d ask staff members. We’d ask more seasoned volunteers. We’d ask each other. We’d make guesses, and guess wrongly, and mess up the boxes, and correct our mistakes, and learn. The more we learned, the easier the sorting became. That is, we were able to sort more quickly, more efficiently, more accurately. The better we understood the system, the better we were at interacting with it. The same is true of our users: the better they understand digital spaces, the more effective they are at using them. But visitors to our apps and websites do not have the luxury of learning the whole system. The fumbling trial-and-error method that I used at the food bank can, on a website, drive users away—or, worse, misinform or hurt them. This is why we must make choices that prioritize transparency, consistency, and familiarity. Our users want to know if X is a Y—well-sorted content can give them the answer. 2018 Lisa Maria Martin lisamariamartin 2018-12-16T00:00:00+00:00 https://24ways.org/2018/the-system-the-search-and-the-food-bank/ content
186 The Web Is Your CMS It is amazing what you can do these days with the services offered on the web. Flickr stores terabytes of photos for us and converts them automatically to all kind of sizes, finds people in them and even allows us to edit them online. YouTube does almost the same complete job with videos, LinkedIn allows us to maintain our CV, Delicious our bookmarks and so on. We don’t have to do these tasks ourselves any more, as all of these systems also come with ways to use the data in the form of Application Programming Interfaces, or APIs for short. APIs give us raw data when we send requests telling the system what we want to get back. The problem is that every API has a different idea of what is a simple way of accessing this data and in which format to give it back. Making it easier to access APIs What we need is a way to abstract the pains of different data formats and authentication formats away from the developer — and this is the purpose of the Yahoo Query Language, or YQL for short. Libraries like jQuery and YUI make it easy and reliable to use JavaScript in browsers (yes, even IE6) and YQL allows us to access web services and even the data embedded in web documents in a simple fashion – SQL style. Select * from the web and filter it the way I want YQL is a web service that takes a few inputs itself: A query that tells it what to get, update or access An output format – XML, JSON, JSON-P or JSON-P-X A callback function (if you defined JSON-P or JSON-P-X) You can try it out yourself – check out this link to get back Flickr photos for the search term ‘santa’*%20from%20flickr.photos.search%20where%20text%3D%22santa%22&format=xml in XML format. The YQL query for this is select * from flickr.photos.search where text="santa" The easiest way to take your first steps with YQL is to look at the console. There you get sample queries, access to all the data sources available to you and you can easily put together complex queries. In this article, however, let’s use PHP to put together a web page that pulls in Flickr photos, blog posts, Videos from YouTube and latest bookmarks from Delicious. Check out the demo and get the source code on GitHub. <?php /* YouTube RSS */ $query = 'select description from rss(5) where url="http://gdata.youtube.com/feeds/base/users/chrisheilmann/uploads?alt=rss&v=2&orderby=published&client=ytapi-youtube-profile";'; /* Flickr search by user id */ $query .= 'select farm,id,owner,secret,server,title from flickr.photos.search where user_id="11414938@N00";'; /* Delicious RSS */ $query .= 'select title,link from rss where url="http://feeds.delicious.com/v2/rss/codepo8?count=10";'; /* Blog RSS */ $query .= 'select title,link from rss where url="http://feeds.feedburner.com/wait-till-i/gwZf"'; /* The YQL web service root with JSON as the output */ $root = 'http://query.yahooapis.com/v1/public/yql?format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys'; /* Assemble the query */ $query = "select * from query.multi where queries='".$query."'"; $url = $root . '&q=' . urlencode($query); /* Do the curl call (access the data just like a browser would) */ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $output = curl_exec($ch); curl_close($ch); $data = json_decode($output); $results = $data->query->results->results; /* YouTube output */ $youtube = '<ul id="youtube">'; foreach($results[0]->item as $r){ $cleanHTML = undoYouTubeMarkupCrimes($r->description); $youtube .= '<li>'.$cleanHTML.'</li>'; } $youtube .= '</ul>'; /* Flickr output */ $flickr = '<ul id="flickr">'; foreach($results[1]->photo as $r){ $flickr .= '<li>'. '<a href="http://www.flickr.com/photos/codepo8/'.$r->id.'/">'. '<img src="http://farm' .$r->farm . '.static.flickr.com/'. $r->server . '/' . $r->id . '_' . $r->secret . '_s.jpg" alt="'.$r->title.'"></a></li>'; } $flickr .= '</ul>'; /* Delicious output */ $delicious = '<ul id="delicious">'; foreach($results[2]->item as $r){ $delicious .= '<li><a href="'.$r->link.'">'.$r->title.'</a></li>'; } $delicious .= '</ul>'; /* Blog output */ $blog = '<ul id="blog">'; foreach($results[3]->item as $r){ $blog .= '<li><a href="'.$r->link.'">'.$r->title.'</a></li>'; } $blog .= '</ul>'; function undoYouTubeMarkupCrimes($str){ $cleaner = preg_replace('/555px/','100%',$str); $cleaner = preg_replace('/width="[^"]+"/','',$cleaner); $cleaner = preg_replace('/<tbody>/','<colgroup><col width="20%"><col width="50%"><col width="30%"></colgroup><tbody>',$cleaner); return $cleaner; } ?> What we are doing here is create a few different YQL statements and queue them together with the query.multi table. Each of these can be run inside YQL itself. Check out the YouTube, Flickr, Delicious and Blog example in the console if you don’t believe me. The benefit of using this table is that we don’t make individual requests for each query but we get all the data in one single request – which means a much better performing solution as the YQL server farm is faster on the web than our servers. We point the query to the YQL web service end point and get the resulting data using cURL. All that we need to do then is to convert the returned data to HTML lists that can be printed out inside an HTML template. Mixing, matching and using HTML as a data source This was a simple example of what YQL can do for you. Where it gets really powerful however is by mixing and matching different APIs. YQL is also a good tool to get information from HTML documents. By using the html table you can load the content of an HTML document (which gets fixed automatically by HTMLTidy) and use XPATH to filter down results to what you need. Take the following example which takes headlines from the news.bbc.co.uk homepage and runs the results through Yahoo’s Term Extractor API to give you a list of currently hot topics. select * from search.termextract where context in ( select content from html where url="http://news.bbc.co.uk" and xpath="//table[@width=800]//a" ) Try it out in the console or see the results here. In English, this means: Go to http://news.bbc.co.uk and get me the HTML Run it through HTML Tidy to clean it up. Get me only the links inside the table with an attribute of width and the value 800 Get only the content of the link and for each of the links Take the content and send it as context to the Yahoo Term Extractor API If we choose JSON-P as the output format we can use the outcome directly in JavaScript (see this demo or see its source): <ul id="hottopics"></ul> <script type="text/javascript"> function hottopics(o){ var res = o.query.results.Result, all = res.length, topics = {}, out = [], html = '', i=0; /* create hash from topics to prevent repetition */ for(i=0;i<all;i++){ topics[res[i]] = res[i]; }; for(i in topics){ out.push(i); }; html = '<li>' + out.join('</li><li>') + '</li>'; document.getElementById('hottopics').innerHTML = html; }; </script> <script type="text/javascript" src="http://query.yahooapis.com/v1/public/yql?q=select%20content%20from%20search.termextract%20where %20context%20in%20(select%20content%20from%20html%20where%20url%3D%22http%3A%2F%2Fnews.bbc.co.uk%22%20and%20xpath%3D%22%2F%2Ftable%5B%40width%3D800%5D%2F%2Fa%22)&format=json&callback=hottopics"></script> Using JSON, we can also use PHP which means the demo works for everybody – not only those with JavaScript enabled (see this demo or see its source): <ul id="hottopics"><li> <?php $url = 'http://query.yahooapis.com/v1/public/yql?q=select%20content'. '%20from%20search.termextract%20where%20context%20in'. '%20(select%20content%20from%20html%20where%20url%3D%22'. 'http%3A%2F%2Fnews.bbc.co.uk%22%20and%20xpath%3D%22%2F%2F'. 'table%5B%40width%3D800%5D%2F%2Fa%22)&format=json'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $output = curl_exec($ch); curl_close($ch); $data = json_decode($output); $topics = array_unique($data->query->results->Result); echo join('</li><li>',$topics); ?> </li></ul> Summary This article could only scratch the surface of YQL. You have not only read access to the web but you can also write to web services. For example you can update Twitter, post to your WordPress blog or shorten a URL with bit.ly. Using Open Tables you can add any web service to the YQL interface and you can even run server-side JavaScript which is for example useful to return Flickr photos as HTML or get the HTML content from a document that needs POST data. The web of data is already here, and using YQL you don’t have to be a web services expert to use it and be part of it. 2009 Christian Heilmann chrisheilmann 2009-12-17T00:00:00+00:00 https://24ways.org/2009/the-web-is-your-cms/ code
273 There’s No Formula for Great Designs Before he combined them with fluid images and CSS3 media queries to coin responsive design, Ethan Marcotte described fluid grids — one of the most enjoyable parts of responsive design. Enjoyable that is, if you like working with math(s). But fluid grids aren’t perfect and, unless we’re careful when applying them, they can sometimes result in a design that feels disconnected. Recapping fluid grids If you haven’t read Ethan’s Fluid Grids, now would be a good time to do that. It centres around a simple formula for converting pixel widths to percentages: (target ÷ context) × 100 = result How does that work in practice? Well, take that Fireworks or Photoshop comp you’re working on (I call them static design visuals, or just visuals.) Of course, everything on that visual — column divisions, inline images, navigation elements, everything — is measured in pixels. Now: Pick something in the visual and measure its width. That’s our target. Take that target measurement and divide it by the width of its parent (context). Multiply what you’ve got by 100 (shift two decimal places). What you’re left with is a percentage width to drop into your style sheets. For example, divide this 300px wide sidebar division by its 948px parent and then multiply by 100: your original 300px is neatly converted to 31.646%. .content-sub { width : 31.646%; /* 300px ÷ 948px = .31646 */ } That formula makes it surprisingly simple for even die-hard fixed width aficionados to convert their visuals to percentage-based, fluid layouts. It’s a handy formula for those who still design using static visuals, and downright essential for those situations where one person in an organization designs in Fireworks or Photoshop and another develops with CSS. Why? Well, although I think that designing in a browser makes the best sense — particularly when designing for multiple devices — I’ll wager most designers still make visuals in Fireworks or Photoshop and use them for demonstrations and get feedback and sign-off. That’s OK. If you haven’t made the transition to content-out designing in a browser yet, the fluid grids formula helps you carry on pushing pixels a while longer. You can carry on moving pixel width measurements from your visuals to your style sheets, too, in the same way you always have. You can be precise to the pixel and even apply a grid image as a CSS background to help you keep everything lined up perfectly. Once you’re done, and the fixed width layout in the browser matches your visual, loop back through your style sheets and convert those pixels to percentages using the fluid grids formula. With very little extra work, you’ll have a fluid implementation of your fixed width layout. The fluid grids formula is simple and incredibly effective, but not long after I started working responsively I realized that the formula shouldn’t (always) be a one-fix, set-and-forget calculation. I noticed that unless we compensate for problems it sometimes creates, the result can be a disconnected design. Staying connected Good design relies on connectedness, a feeling of natural balance between elements and the grid they’re placed on. Give an element greater prominence or position in a visual hierarchy and you can fundamentally alter the balance and sometimes the meaning of a design. Different from a browser’s page zooming feature — where images, text and overall layout change size by the same ratio — fluid grids flex a layout in response to a window or device width. Columns expand and contract, and within them fluid media (images and videos) can also change size. This can be one of the most impressive demonstrations of responsive design. But not every element within a fluid grid can change size along with the window or device width. For example, type size and leading won’t change along with a column’s width. When columns and elements within them change width, all too easily a visual hierarchy can be broken and along with it the relationship between element sizes and the outer window or viewport. This can happen quickly if you make just one set of fluid grid calculations and use those percentages across every screen width, from smartphones through tablets and up to large desktops. The answer? Make several sets of fluid grids calculations, each one at a significant window or device width breakpoint. Then apply those new percentages, when needed, to help keep elements in proportion and maintain balance and connectedness. Here’s how I work. Avoiding disconnection I’ve never been entirely happy with grid frameworks such as the 960 Grid System, so I start almost every project by creating a custom grid to inform my layout decisions. Here’s a plain version of a grid from a recent project that I’ll use as an illustration. This project’s grid comprises 84px columns and 24px gutters. This creates an odd number of columns at common tablet and desktop widths, and allows for 300px fixed width assets — useful when I need to fit advertising into a desktop layout’s sidebar. Showing common advertising sizes (Larger image) For this project I chose three 320 and Up breakpoints above 320px and, after placing as many columns as would fit those breakpoint widths, I derived three content widths: Breakpoint Columns Content width 768px 7 732px 992px 9 948px 1,382px 13 1,380px Here’s my grid again, this time with pixel measurements and breakpoints overlaid. Showing pixel measurements and breakpoints (Larger image) Now cast your mind back to the fluid grids calculation I made earlier. I divided a 300px element by 948px and arrived at 31.646%. For some elements it’s possible to use that percentage across all screen widths, but others will feel too small in relation to a narrower 768px and too large inside 1,380px. To help maintain connectedness, I make a set of fluid grids calculations based on each of the content widths I established earlier. Now I can shift an element’s percentage width up or down when I switch to a new breakpoint and content width. For example: 300px is 40.984% of 732px 300px is 31.646% of 948px 300px is 21.739% of 1,380px I’ll add all those fluid grid percentages to my grid image and save it for quick reference. Showing percentages at all breakpoints (Larger image) Then I can apply those different percentage widths to elements at each breakpoint using CSS3 media queries. For example, that sidebar division again: /* 732px, 7-column width */ @media only screen and (min-width: 768px) { .content-sub { width : 40.983%; /* 300px ÷ 732px = .40983 */ } } /* 948px, 9-column width */ @media only screen and (min-width: 992px) { .content-sub { width : 31.645%; /* 300px ÷ 948px = .31645 */ } } /* 1380px, 13-column width */ @media only screen and (min-width: 1382px) { .content-sub { width : 21.739%; /* 300px ÷ 1380px = .21739 */ } } The number of changes you make to a layout at different breakpoints will, of course, depend on the specifics of the design you’re working on. Yes, this is additional work, but the result will be a layout that feels better balanced and within which elements remain in harmony with each other while they respond to new screen or device widths. Putting the design in responsive web design Until now, many of the conversations around responsive web design have been about aspects of technical implementation, rather than design. I believe we’re only beginning to understand what’s involved in designing responsively. In future, we’ll likely be making design decisions not just about proportions but also about responsive typography. We’ll also need to learn how to adapt our designs to device characteristics such as touch targets and more. Sometimes we’ll make decisions to improve function, other times because they make a design ‘feel’ right. You’ll know when you’ve made a right decision. You’ll feel it. After all, there really is no formula for making great designs. 2011 Andy Clarke andyclarke 2011-12-23T00:00:00+00:00 https://24ways.org/2011/theres-no-formula-for-great-designs/ ux
88 Think First, Code Later This is a story that’s best told from the end, and it’s probably one you’re all familiar with. You, or someone just like you, have been building a website, probably as part of a skilled and capable team. You’re a front-end developer, focusing on JavaScript – it’s either your sole responsibility or shared around. It’s quite a big job, been going on for months, and at last it feels like you’re reaching the end of it. But, in a brief moment of downtime, you step back and take a look at the code as a whole. You notice that the folder called “jQuery plugins” suddenly looks rather full, and maybe there’s evidence of several methods of doing the same thing; there are loads of little niggly fixes in the bug tracker; and every place you use Ajax the structure of the data is slightly different. You sigh, and your shoulders droop slightly, and you think “Yeah, we’ll do that more cleanly next time.” The thing is, you probably already know how to rewrite the start of this story to make the ending work better. This situation is not really anyone’s fault – it’s just an accumulation of all the things you decided along the way, all the things you agreed you’d fix later that have disappeared into the black hole of technical debt, and accomodating all the “can we just…?” requests from around the team and the client. So, the solution to this is easy, right? More interminable planning meetings, more tightly controlled and documented specifications, less freedom to innovate, to try out new ideas and enjoy what you’re doing. Wait, that sounds even less fun than the old way. Minimum viable planning Actually, planning and specifications are exactly what you need, but the way you go about them can make a real difference, both to the quality of your code, and the quality of your life as a developer. It can be as simple as being a little more thoughtful before starting on any new piece of functionality. Involve your whole team if possible, or at least those working on what you’re doing. Canvass opinions and work out what the solution to the problem might look like first, rather than coding speculatively to find out. There are easy ways you can get into this habit of putting the thought and design up front, and it doesn’t have to mean spending more time on the project as a whole. It also doesn’t have to result in reams of functional specifications. Instead, let the code itself form the specification. As JavaScript applications become more complex, unit testing is becoming ever more important. So embrace it, whether you prefer QUnit, or Mocha, or any of the other JavaScript testing frameworks out there. The TDD (or test-driven development) pattern is all about writing the tests first and then writing functional code to pass those tests; or, if you prefer, code that meets the specification given by the tests. Sounds like a hassle at first, but once you get into the rhythm of it you should find that the time spent writing tests up front is no greater, and often significantly less, than the time you would have spent fixing bugs afterwards. If what you’re working on requires an API between client and server (usually Ajax but this can apply to any method of sending or receiving data) then spend a bit of time with the back-end developer to design the data contracts, before either of you cut any code. Work out what the API endpoints are going to be, and what the data structure you’ll get back from a certain endpoint looks like. A mock JSON object documented on a wiki is enough and it can be atomic. Don’t worry about planning the entire project at once, just plan enough to get on with your current tasks. Definition in this way doesn’t have to make your API immutable – change is still fine – but if you know roughly where you’re heading, then not only can your team’s efforts become more parallel, but you’re far more likely to have an easier time making it all work. And again, you have a specification – the shape of the data – to write your JavaScript against. Putting everything together, you end up with a logical flow of development, from the specification agreed with the client (your backlog), to the specification agreed with your team (the API contract design), to the specification agreed with your code (your unit tests). Hopefully, there will be ample clues in all of this to inform your front-end library choices, because by then you should have a better picture of what you’re going to need. What the framework? As a JavaScript developer predominantly, these are the choices I’m particularly interested in – how and why you use JavaScript libraries and frameworks, both what you expect from them and what you actually get. If we look back at how web development, and specifically JavaScript development has progressed – from the earliest days of using lines and lines of Dreamweaver code-barf to make an image rollover effect, to today’s large frameworks that handle working with the DOM, Ajax communication and visual effects all in one hit – the purpose of it is clear: to smooth over the inconsistent bumps between browsers and give a solid, reliable, predictable base on which to put our desired functionality. Understanding what we expect the language as a specification to do, and matching that to what we observe browsers actually doing, and then smoothing out the differences, is a big job. Since the language and the implementations are also changing as we go along, it also feels like a never-ending job. So make full use of this valuable effort. Use jQuery or YUI or anything else you’re comfortable with, but it still pays to think early on about what you need your library to do and what the best choice is to meet that need. I’ve come in to projects as a fixer and found, to take a recent example, that jQuery UI was being used just to provide a date picker and a modal effect. That’s a lot of code weight to provide two fairly simple pieces of functionality that could easily be covered by smaller plugins. Which isn’t to say that jQuery UI itself is a bad choice, but I could see that it had been included late on just to do those things, whereas a more considered approach would have been to put the library in early and use it more universally. There are other choices, too. If you automatically throw in jQuery (or whatever your favourite main library is) to a small site with limited functionality, you might only touch a tiny fraction of its scope. In my own development I started looking at what I actually needed from a JavaScript library. For a simple project like What the Framework?, all jQuery needed to do was listen for .ready() and then perform some light DOM selection before handing over to a client-side MVC framework. So perhaps there was another way to go about this while still avoiding the cross-browser headaches. Deleting jQuery But the jQuery pattern is compelling and familiar. And once you’re comfortable with something, it’s a bit of an effort to force yourself out of that comfort zone and learn. But looking back at my whole career, I realised that I’ve relearned pretty much everything I do, probably several times, since I started out. So it’s worth keeping in mind that learning and trying new things is how development has advanced to where it is now, and how it will keep advancing in the future. In the end this lead me to Ender, which is billed as an NPM-style package manager for the browser, letting you search for and manage small, loosely coupled modules and their dependencies, and compile them to one file with a common API. For What the Framework I ended up with a set of DOM tools, Underscore and Knockout, all minified into 25kb of JavaScript. This compares really well with 32kb minified for jQuery on its own, and Ender’s use of the dollar variable and the jQuery-like syntax in many modules makes switching over a low-friction experience. On more complex projects, where you’re really going to use all the features of something like jQuery, but want to minimise the loading of other dependencies when you don’t need them, I’ve recently started looking at Jam. This uses the RequireJS pattern to compile commonly used code into a library file and then manage dependencies and bring in others on a per-page basis depending on how you need it. Again, it all comes down to thinking about what you need and using it only when you need it. And the configurability of tools like Ender or Jam allow you to be responsive to changing requirements as your project grows. There is no right answer That’s not to say this way of working automatically makes things easier. It doesn’t. On a large, long-running project or one where future functionality is unknown, it’s still hard to predict and plan for everything – at least until crystal balls as a service come about. But by including strong engineering practices in your front-end, and trying to minimise technical debt, you’re at least giving yourself a decent safety net to guard against the “can we just…?” tendencies that are a fact of life. So, really, this is not an advocation of using a particular technology or framework, because I can’t tell you what works for you or your team. But what I can tell you is that working this way round has done wonders for my productivity and enthusiasm, both for code quality and for trying out new libraries. Give it a go, you might like it! 2012 Stephen Fulljames stephenfulljames 2012-12-07T00:00:00+00:00 https://24ways.org/2012/think-first-code-later/ process
160 Tracking Christmas Cheer with Google Charts A note from the editors: Since this article was written Google has retired the Charts API. Let’s get something out in the open: I love statistics. As an informatician I can’t get enough graphs, charts, and numbers. So you can imagine when Google released their Charts API I thought Christmas had come early. I immediately began to draw up graphs for the holiday season using the new API; and using my new found chart-making skills I’ll show you what you can and can’t do with Google Charts. Mummy, it’s my first chart The Google Charts API allows you to send data to Google; in return they give you back a nicely-rendered graph. All the hard work is done on Google’s servers — you need only reference an image in your HTML. You pass along the data — the numbers for the charts, axis labels, and so on — in the query string of the image’s URL. If you want to add charts to your blog or web site, there’s probably no quicker way to get started. Here’s a simple example: if we add the following line to an HTML page: <img src="http://chart.apis.google.com/chart?cht=lc&chs=200x125&chd=s:ZreelPuevfgznf2008" /> Then we’ll see the line graph in Figure 1 appear in our page. That graph is hosted on Google’s own server1: http://chart.apis.google.com/. Figure 1: A simple example of a line graph created with Google Charts. If you look at the URL used in the example you’ll notice we’re passing some parameters along in the query string (the bit after the question mark). The query string looks like this: cht=lc&chs=200x125&chd=s:ZreelPuevfgznf2008 It’s contains everything Google Charts needs to draw the graph. There are three parameters in the query string: cht; this specifies the type of chart Google Charts will generate (in this case, lc is a line chart). chs, the value of which is 200x125; this defines the chart’s size (200 pixels wide by 125 pixels high). chd, the value of which is s:ZreelPuevfgznf2008; this is the actual chart data, which we’ll discuss in more detail later. These three parameters are the minimum you need to send to Google Charts in order to create a chart. There are lots more parameters you can send too (giving you more choice over how a chart is displayed), but you have to include at least these three before a chart can be created. Using these three parameters you can create pie charts, scatter plots, Venn diagrams, bar charts (and more) up to 1,000 pixels wide or 1,000 pixels high (but no more than 300,000 pixels in total). Christmas pie After I discovered the option to create a pie chart I instantly thought of graphing all the types of food and beverages that I’ll consume at this year’s Christmas feast. I can represent each item as a percentage of all the food on a pie chart (just thinking about that makes me hungry). By changing the value of the cht parameter in the image’s query string I can change the chart type from a line chart to a pie chart. Google Charts offers two different types of pie chart: a fancy three-dimensional version and a two-dimensional overhead version. I want to stick with the latter, so I need to change cht=lc to cht=p (the p telling Google Charts to create a pie chart; if you want the three-dimensional version, use cht=p3). As a pie chart is circular I also need to adjust the size of the chart to make it square. Finally, it would be nice to add a title to the graph. I can do this by adding the optional parameter, chtt, to the end of the image URL. I end up with the chart you see in Figure 2. Figure 2: Pie chart with a title. To add this chart to your own page, you include the following (notice that you can’t include spaces in URLs, so you need to encode them as plus-signs.): <img src="http://chart.apis.google.com/chart?chtt=Food+and+Drink+Consumed+Christmas+2007&cht=p&chs=300x300&chd=s:ZreelPuevfgznf2008" /> Ok, that’s great, but there are still two things I want to do before I can call this pie chart complete. First I want to label each slice of the pie. And second I want to include the proper data (at the moment the slices are meaningless). If 2007 is anything like 2006, the break down will be roughly as follows: Egg nog 10% Christmas Ham 20% Milk (not including egg nog) 8% Cookies 25% Roasted Chestnuts 5% Chocolate 3% Various Other Beverages 15% Various Other Foods 9% Snacks 5% I have nine categories of food and drink to be tracked, so I need nine slice labels. To add these to the chart, I use the chl parameter. All nine labels are sent in one value; I use the vertical-pipe character, |, to separate them. So I need to append the following to the query string: chl=Egg+nog|Christmas+Ham|Milk+(not+including+egg+nog)|Cookies|Roast+Chestnuts|Chocolate|Various+Other+Beverages|Various+Other+Foods|Snacks Next I need to add the corresponding percentage values to the chart labels. Encoding the chart data is the trickiest part of the Google Charts API — but by no means complicated. There are three different ways to encode your data on a chart. As I’m only dealing with small numbers, I’m going to use what Google calls simple encoding. Simple encoding offers a sixty-two value spectrum in which to represent data. Remember the mandatory option, chd, from the first example? The value for this is split into two parts: the type of encoding and the graph data itself. These two parts are separated with a colon. To use simple encoding, the first character of the chd option must be a lower case s. Follow this with a colon and everything after it is considered data for the graph. In simple encoding, you have sixty-two values to represent your data. These values are lowercase and uppercase letters from the Latin alphabet (fifty-two characters in total) and the digits 0 to 9. Each letter of the alphabet represents a single number: A equals 0, B equals 1, and so on up to Z, which equals 25; a equals 26, b equals 27, and so on up to z, which equals 51. The ten digits represent the numbers 52 to 61: 0 equals 52, 1 equals 53, and 9 equals 61. In the previous two examples we used the string ZreelPuevfgznf2008 as our chart data; the Z is equal to 25, the r is equal to 42, the e is equal to 30, and so on. I want to encode the percentage values 10, 20, 8, 25, 5, 3, 15, 9 and 5, so in simple encoding I would use the string KUIZFDPJF. If you think figuring this out for each chart may make your head explode, don’t worry: help is out there. Do you remember I said I needed to change the image dimensions to be square, to accommodate the pie chart? Well now I’m including labels I need even more room. And as I’m in a Christmassy mood I’m going to add some festive colours too. The optional chco parameter is used to change the chart color. You set this using the same hexadecimal (“hex”) notation found in CSS. So let’s make our pie chart green by adding chco=00AF33 (don’t start it with a hash character as in CSS) to the image URL. If we only specify one hex colour for the pie chart Google Charts will use shades of that colour for each of the slices. To choose your own colours, pass a comma separated list of colours. The “Milk” and “Cookies” slices were consumed together, so we can make those two slices more of a redish colour. I’ll use shades of green for the other slices. My chco parameter now looks like this: chco=00AF33,4BB74C,EE2C2C,CC3232,33FF33,66FF66,9AFF9A,C1FFC1,CCFFCC. After all this, I’m left with the following URL: http://chart.apis.google.com/chart?chco=00AF33,4BB74C,EE2C2C,CC3232,33FF33,66FF66,9AFF9A,C1FFC1,CCFFCC&chl=Egg+nog|Christmas+Ham|Milk+(not+including+egg+nog)|Cookies|Roast+Chestnuts|Chocolate|Various+Other+Beverages|Various+Other+Foods|Snacks&chtt=Food+and+Drink+Consumed+Christmas+2007&cht=p&chs=600x300&chd=s:KUIZFDPJF What does that give us? I’m glad you asked. I have the rather beautiful 600-pixel wide pie chart you see in Figure 3. Figure 3: A Christmassy pie chart with labels. But I don’t like pie charts The pie chart was invented by the Scottish polymath William Playfair in 1801. But not everyone is as excited by pie charts as wee Billy, so if you’re an anti-pie-chartist, what can you do? You can easily reuse the same data but display it as a bar graph in a snap. The first thing we need to do is change the value of the cht parameter from p to bhg. This creates a horizontal bar graph (you can request a vertical bar graph using bvg). The data and labels all remain the same, but we need to decide where the labels will appear. I’ll talk more about how to do all this in the next section. In Figure 4 you’ll see the newly-converted bar graph. The URL for the graph is: http://chart.apis.google.com/chart?cht=bhg&chs=600x300&chd=s:KUIZFDPJF&chxt=x,y&chtt=Food+and+Drink+Consumed+Christmas+2007&chxl=1:|Egg+nog|Christmas+Ham|Milk+(not+including+egg+nog)|Cookies|Roast+Chestnuts|Chocolate|Various+Other+Beverages|Various+Other+Foods|Snacks&chco=00AF33 Figure 4: The pie chart from Figure 3 represented as a bar chart. Two lines, one graph Pie charts and bar charts are interesting, but what if I want to compare last year’s Christmas cheer with this year’s? That sounds like I’ll need two lines on one graph. The code is much the same as the previous examples; the most obvious difference is I need to set up the chart as a line graph. Creating some dummy values for the required parameters, I end up with: <img src="http://chart.apis.google.com/chart?chs=800x300&cht=lxy&chd=t:0,100|0,100" /> The chs=800x300 sets the dimensions of the new chart, while cht=lxy describes the type of chart we are using (in this case a line chart with x and y co-ordinates). For the chart data I’m going to demostrate a different encoding, text encoding. To use this I start the value of the chd parameter with “t:” instead of “s:”, and follow it with a list of x coordinates, a vertical pipe, |, and a list of y coordinates. Given the URL above, Google Charts will render the chart shown in Figure 5. Figure 5: A simple line graph with x and y co-ordinates. To make this graph a little more pleasing to the eye, I can add much the same as I did to the pie chart. I’ll add a chart title. Maybe something like “Projected Christmas Cheer for 2007”. Just as before I would add a chtt parameter to the image URL: &chtt=Projected+Christmas+Cheer+for+2007 Next, let’s add some labels on the y axis to represent a scale from 0 to 100. On the x axis let’s label for the most important days of December. To do this I need to use the chart axis type parameter, chxt. This allows us to specify the axes and associate some labels with them. As I’m only interested in the y-axis (to the left of the chart) and the x-axis (below the chart), we add chxt=x,y to our image URL. Now I need my label data. This is slightly more tricky because I want the data evenly spaced without labelling every item. The parameter for labels is chxl, the chart axis label. You match a label to an axis by using a number. So 0:Label1 is the zero index of chxt — in this case the x-axis. 1:Label2 is the first index of chxt — the y-axis. The order of these parameters or labels doesn’t matter as long as you associate them to their chxt correctly. The next thing to know about chxl is that you can add an empty label. Labels are separated by vertical pipe; if you don’t put any text in a label, you just leave the two vertical pipes empty (“||”) and Google Charts will allocate space but no label. For our vertical y axis, we want to label only 50% and 100% on the graph and plot them in their respective places. Since the y-axis is the second item, 1: (remember to start counting at zero), we add ten spaces to our image URL, chxl=1:||||||50|||||100 This will output the 50 halfway and the 100 at the top; all the other spaces will be empty. We can do the same thing to get specific dates along the x-axis as well. Let’s add the 1st of December, St. Nick’s Day (the 6th), Christmas Day, Boxing Day (a holiday common in the UK and the Commonwealth, on the 26th), and the final day of the month, the 31st. Since this is the x-axis I’ll use 0: as a reference in the chxt parameter tell Google Charts which axis to label. In full, the chxl parameter now looks like: chxl=1:||||||50|||||100|0:|Dec+1st|||||6th||||10th|||||15th|||||20th|||||25th|26th|||||Dec+31st That’s pretty. Before we begin to graph our data, I’ll do one last thing: add some grid lines to the chart so to better connect the data to the labels. The parameter for this is chg, short for chart grid lines. The parameter takes four comma-separated arguments. The first is the x-axis spacing for the grid. I have thirty-one days, so I need thirty vertical lines. The chart is 100% wide, so 3.33 (100 divided by 30) is the required spacing. As for the y-axis: the axis goes up to 100% but we probably only need to have a horizontal line every 10%, so the required spacing is 10 (100 divided by 10). That is the second argument. The last two arguments control the dash-style of the grid-lines. The first number is the length of the line dash and the second is the space between the dashes. So 6,3 would mean a six-unit dash with a three-unit space. I like a ratio of 1,3 but you can change this as you wish. Now that I have the four arguments, the chg parameter looks like: chg=3.333,10,1,3 If I add that to the chart URL I end up with: http://chart.apis.google.com/chart?chs=800x300&cht=lxy&chd=t:0,100|0,100&chtt=Projected+Christmas+Cheer+for+2007&chxt=x,y&chxl=0:|Dec+1st|||||6th|||||||||||||||||||25th|26th|||||Dec+31st|1:||||||50|||||100&chg=3.3333,10,1,3 Which results in the chart shown in Figure 6. Figure 6: Chart ready to receive the Christmas cheer values. Real data Now the chart is ready I can add historical data from 2006 and current data from 2007. Having a look at last year’s cheer levels we find some highs and lows through-out the month: Dec 1st Advent starts; life is good 30% Dec 6th St. Nick’s Day, awake to find good things in my shoes 45% Dec 8th Went Christmas carolling, nearly froze 20% Dec 10th Christmas party at work, very nice dinner 50% Dec 18th Panic Christmas shopping, hate rude people 15% Dec 23rd Off Work, home eating holiday food 80% Dec 25th Opened presents, good year, but got socks again from Grandma 60% Dec 26th Boxing Day; we’re off and no one knows why 70% Dec 28th Third day of left overs 40% Dec 29th Procured some fireworks for new years 55% Dec 31st New Year’s Eve 80% Since I’m plotting data for 2006 and 2007 on the same graph I’ll need two different colours — one for each year’s line — and a key to denote what each colour represents. The key is controlled by the chdl (chart data legend) parameter. Again, each part of the parameter is separated by a vertical pipe, so for two labels I’ll use chdl=2006|2007. I also want to colour-code them, so I’ll need to add the chco as I did for the pie chart. I want a red line and a green line, so I’ll use chco=458B00,CD2626 and add this to the image URL. Let’s begin to plot the 2006 data on the Chart, replacing our dummy data of chd=t:0,100|0,100 with the correct information. The chd works by first listing all the x coordinates (each separated by a comma), then a vertical pipe, and then all the y coordinates (also comma-separated). The chart is 100% wide, so I need to convert the days into a percentage of the month. The 1st of December is 0 and the 31st is 100. Everything else is somewhere in between. Our formula is: (d – 1) × 100 ÷ (31 – 1) Where d is the day of the month. The formula states that each day will be printed every 3.333 units; so the 6th of December will be printed at 16.665 units. I can repeat the process for the other dates listed to get the following x coordinates: 0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7. The y axis coordinates are easy because our scale is 100%, just like our rating, so we can simply copy them across as 30,45,20,50,15,80,60,70,40,55,80. This gives us a final chd value of: chd=t:0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7,100|30,45,20,50,15,80,60,70,40,55,80 Onto 2007: I can put the data for the month so far to see how we are trending. Dec 1st Christmas shopping finished already 50% Dec 4th Computer hard disk drive crashed (not Christmas related accident, but put me in a bad mood) 10% Dec 6th Missed St. Nick’s Day completely due to travelling 30% Dec 9th Dinner with friends before they travel 55% Dec 11th 24ways article goes live 60% Using the same system we did for 2006, I can take the five data points and plot them on the chart. The new x axis values will be 0,10,16.7,26.7 and the new y axis 50,10,30,65. We incorporate those into the image URL by appending these values onto the chd parameter we already have, which then becomes: chd=t:0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7,100|30,45,20,50,15,80,60,70,40,55,80|0,10,16.7,26.7,33.3|50,10,30,55,60 Passing this to Google Charts results in Figure 7. http://chart.apis.google.com/chart?chs=800x300&cht=lxy&chd=t:0,100|0,100&chtt=Projected+Christmas+Cheer+for+2007&chxt=x,y&chxl=0:|Dec+1st|||||6th|||||||||||||||||||25th|26th|||||Dec+31st|1:||||||50|||||100&chg=3.3333,10,1,3&chd=t:0,16.7,23.3,33.3,60,76.7,83.3,86.7,93.3,96.7,100|30,45,20,50,15,80,60,70,40,55,80|0,10,16.7,26.7,33.3|50,10,30,55,60&chco=458B00,CD2626&chdl=2006|2007 Figure 7: Projected Christmas cheer for 2006 and 2007. Did someone mention Edward Tufte? Google Charts are a robust set of chart types that you can create easily and freely using their API. As you can see, you can graph just about anything you want using the line graph, bar charts, scatter plots, venn diagrams and pie charts. One type of chart conspicuously missing from the API is sparklines. Sparklines were proposed by Edward Tufte as “small, high resolution graphics embedded in a context of words, numbers, images”. They can be extremely useful, but can you create them in Google Charts? The answer is: “Yes, but it’s an undocumented feature”. (The usual disclaimer about undocumented features applies.) If we take our original line graph example, and change the value of the cht parameter from lc (line chart) to lfi (financial line chart) the axis-lines are removed. This allows you to make a chart — a sparkline — small enough to fit into a sentence. Google uses the lfi type all throughout the their financial site, but it’s not yet part of the official API. MerryChristmas http://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:MerryChristmas 24ways http://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:24ways&chco=999999 HappyHolidays http://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:HappyHolidays&chco=ff0000 HappyNewYear http://chart.apis.google.com/chart?cht=lfi&chs=100x15&chd=s:HappyNewYear&chco=0000ff Summary The new Google Charts API is a powerful method for creating charts and graphs of all types. If you apply a little bit of technical skill you can create pie charts, bar graphs, and even sparklines as and when you need them. Now you’ve finished ready the article I hope you waste no more time: go forth and chart! Further reading Google Charts API More on Google Charts How to handle negative numbers 12 Days of Christmas Pie Chart 1 In order to remain within the 50,000 requests a day limit the Google Charts API imposes, chart images on this page have been cached and are being served from our own servers. But the URLs work – try them! 2007 Brian Suda briansuda 2007-12-11T00:00:00+00:00 https://24ways.org/2007/tracking-christmas-cheer-with-google-charts/ ux
334 Transitional vs. Strict Markup When promoting web standards, standardistas often talk about XHTML as being more strict than HTML. In a sense it is, since it requires that all elements are properly closed and that attribute values are quoted. But there are two flavours of XHTML 1.0 (three if you count the Frameset DOCTYPE, which is outside the scope of this article), defined by the Transitional and Strict DOCTYPEs. And HTML 4.01 also comes in those flavours. The names reveal what they are about: Transitional DOCTYPEs are meant for those making the transition from older markup to modern ways. Strict DOCTYPEs are actually the default – the way HTML 4.01 and XHTML 1.0 were constructed to be used. A Transitional DOCTYPE may be used when you have a lot of legacy markup that cannot easily be converted to comply with a Strict DOCTYPE. But Strict is what you should be aiming for. It encourages, and in some cases enforces, the separation of structure and presentation, moving the presentational aspects from markup to CSS. From the HTML 4 Document Type Definition: This is HTML 4.01 Strict DTD, which excludes the presentation attributes and elements that W3C expects to phase out as support for style sheets matures. Authors should use the Strict DTD when possible, but may use the Transitional DTD when support for presentation attribute and elements is required. An additional benefit of using a Strict DOCTYPE is that doing so will ensure that browsers use their strictest, most standards compliant rendering modes. Tommy Olsson provides a good summary of the benefits of using Strict over Transitional in Ten questions for Tommy Olsson at Web Standards Group: In my opinion, using a Strict DTD, either HTML 4.01 Strict or XHTML 1.0 Strict, is far more important for the quality of the future web than whether or not there is an X in front of the name. The Strict DTD promotes a separation of structure and presentation, which makes a site so much easier to maintain. For those looking to start using web standards and valid, semantic markup, it is important to understand the difference between Transitional and Strict DOCTYPEs. For complete listings of the differences between Transitional and Strict DOCTYPEs, see XHTML: Differences between Strict & Transitional, Comparison of Strict and Transitional XHTML, and XHTML1.0 Element Attributes by DTD. Some of the differences are more likely than others to cause problems for developers moving from a Transitional DOCTYPE to a Strict one, and I’d like to mention a few of those. Elements that are not allowed in Strict DOCTYPEs center font iframe strike u Attributes not allowed in Strict DOCTYPEs align (allowed on elements related to tables: col, colgroup, tbody, td, tfoot, th, thead, and tr) language background bgcolor border (allowed on table) height (allowed on img and object) hspace name (allowed in HTML 4.01 Strict, not allowed on form and img in XHTML 1.0 Strict) noshade nowrap target text, link, vlink, and alink vspace width (allowed on img, object, table, col, and colgroup) Content model differences An element type’s content model describes what may be contained by an instance of the element type. The most important difference in content models between Transitional and Strict is that blockquote, body, and form elements may only contain block level elements. A few examples: text and images are not allowed immediately inside the body element, and need to be contained in a block level element like p or div input elements must not be direct descendants of a form element text in blockquote elements must be wrapped in a block level element like p or div Go Strict and move all presentation to CSS Something that can be helpful when doing the transition from Transitional to Strict DOCTYPEs is to focus on what each element of the page you are working on is instead of how you want it to look. Worry about looks later and get the structure and semantics right first. 2005 Roger Johansson rogerjohansson 2005-12-13T00:00:00+00:00 https://24ways.org/2005/transitional-vs-strict-markup/ code
165 Transparent PNGs in Internet Explorer 6 Newer breeds of browser such as Firefox and Safari have offered support for PNG images with full alpha channel transparency for a few years. With the use of hacks, support has been available in Internet Explorer 5.5 and 6, but the hacks are non-ideal and have been tricky to use. With IE7 winning masses of users from earlier versions over the last year, full PNG alpha-channel transparency is becoming more of a reality for day-to-day use. However, there are still numbers of IE6 users out there who we can’t leave out in the cold this Christmas, so in this article I’m going to look what we can do to support IE6 users whilst taking full advantage of transparency for the majority of a site’s visitors. So what’s alpha channel transparency? Cast your minds back to the Ghost of Christmas Past, the humble GIF. Images in GIF format offer transparency, but that transparency is either on or off for any given pixel. Each pixel’s either fully transparent, or a solid colour. In GIF, transparency is effectively just a special colour you can chose for a pixel. The PNG format tackles the problem rather differently. As well as having any colour you chose, each pixel also carries a separate channel of information detailing how transparent it is. This alpha channel enables a pixel to be fully transparent, fully opaque, or critically, any step in between. This enables designers to produce images that can have, for example, soft edges without any of the ‘halo effect’ traditionally associated with GIF transparency. If you’ve ever worked on a site that has different colour schemes and therefore requires multiple versions of each graphic against a different colour, you’ll immediately see the benefit. What’s perhaps more interesting than that, however, is the extra creative freedom this gives designers in creating beautiful sites that can remain web-like in their ability to adjust, scale and reflow. The Internet Explorer problem Up until IE7, there has been no fully native support for PNG alpha channel transparency in Internet Explorer. However, since IE5.5 there has been some support in the form of proprietary filter called the AlphaImageLoader. Internet Explorer filters can be applied directly in your CSS (for both inline and background images), or by setting the same CSS property with JavaScript. CSS: img { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(...); } JavaScript: img.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(...)"; That may sound like a problem solved, but all is not as it may appear. Firstly, as you may realise, there’s no CSS property called filter in the W3C CSS spec. It’s a proprietary extension added by Microsoft that could potentially cause other browsers to reject your entire CSS rule. Secondly, AlphaImageLoader does not magically add full PNG transparency support so that a PNG in the page will just start working. Instead, when applied to an element in the page, it draws a new rendering surface in the same space that element occupies and loads a PNG into it. If that sounds weird, it’s because that’s precisely what it is. However, by and large the result is that PNGs with an alpha channel can be accommodated. The pitfalls So, whilst support for PNG transparency in IE5.5 and 6 is possible, it’s not without its problems. Background images cannot be positioned or repeated The AlphaImageLoader does work for background images, but only for the simplest of cases. If your design requires the image to be tiled (background-repeat) or positioned (background-position) you’re out of luck. The AlphaImageLoader allows you to set a sizingMethod to either crop the image (if necessary) or to scale it to fit. Not massively useful, but something at least. Delayed loading and resource use The AlphaImageLoader can be quite slow to load, and appears to consume more resources than a standard image when applied. Typically, you’d need to add thousands of GIFs or JPEGs to a page before you saw any noticeable impact on the browser, but with the AlphaImageLoader filter applied Internet Explorer can become sluggish after just a handful of alpha channel PNGs. The other noticeable effect is that as more instances of the AlphaImageLoader are applied, the longer it takes to render the PNGs with their transparency. The user sees the PNG load in its original non-supported state (with black or grey areas where transparency should be) before one by one the filter kicks in and makes them properly transparent. Both the issue of sluggish behaviour and delayed load only really manifest themselves with volume and size of image. Use just a couple of instances and it’s fine, but be careful adding more than five or six. As ever, test, test, test. Links become unclickable, forms unfocusable This is a big one. There’s a bug/weirdness with AlphaImageLoader that sometimes prevents interaction with links and forms when a PNG background image is used. This is sometimes reported as a z-index issue, but I don’t believe it is. Rather, it’s an artefact of that weird way the filter gets applied to the document almost outside of the normal render process. Often this can be solved by giving the links or form elements hasLayout using position: relative; where possible. However, this doesn’t always work and the non-interaction problem cannot always be solved. You may find yourself having to go back to the drawing board. Sidestepping the danger zones Frankly, it’s pretty bad news if you design a site, have that design signed off by your client, build it and then find out only at the end (because you don’t know what might trigger a problem) that your search field can’t be focused in IE6. That’s an absolute nightmare, and whilst it’s not likely to happen, it’s possible that it might. It’s happened to me. So what can you do? The best approach I’ve found to this scenario is Isolate the PNG or PNGs that are causing the problem. Step through the PNGs in your page, commenting them out one by one and retesting. Typically it’ll be the nearest PNG to the problem, so try there first. Keep going until you can click your links or focus your form fields. This is where you really need luck on your side, because you’re going to have to fake it. This will depend on the design of the site, but some way or other create a replacement GIF or JPEG image that will give you an acceptable result. Then use conditional comments to serve that image to only users of IE older than version 7. A hack, you say? Well, you started it chum. Applying AlphaImageLoader Because the filter property is invalid CSS, the safest pragmatic approach is to apply it selectively with JavaScript for only Internet Explorer versions 5.5 and 6. This helps ensure that by default you’re serving standard CSS to browsers that support both the CSS and PNG standards correct, and then selectively patching up only the browsers that need it. Several years ago, Aaron Boodman wrote and released a script called sleight for doing just that. However, sleight dealt only with images in the page, and not background images applied with CSS. Building on top of Aaron’s work, I hacked sleight and came up with bgsleight for applying the filter to background images instead. That was in 2003, and over the years I’ve made a couple of improvements here and there to keep it ticking over and to resolve conflicts between sleight and bgsleight when used together. However, with alpha channel PNGs becoming much more widespread, it’s time for a new version. Introducing SuperSleight SuperSleight adds a number of new and useful features that have come from the day-to-day needs of working with PNGs. Works with both inline and background images, replacing the need for both sleight and bgsleight Will automatically apply position: relative to links and form fields if they don’t already have position set. (Can be disabled.) Can be run on the entire document, or just a selected part where you know the PNGs are. This is better for performance. Detects background images set to no-repeat and sets the scaleMode to crop rather than scale. Can be re-applied by any other JavaScript in the page – useful if new content has been loaded by an Ajax request. Download SuperSleight Implementation Getting SuperSleight running on a page is quite straightforward, you just need to link the supplied JavaScript file (or the minified version if you prefer) into your document inside conditional comments so that it is delivered to only Internet Explorer 6 or older. <!--[if lte IE 6]> <script type="text/javascript" src="supersleight-min.js"></script> <![endif]--> Supplied with the JavaScript is a simple transparent GIF file. The script replaces the existing PNG with this before re-layering the PNG over the top using AlphaImageLoaded. You can change the name or path of the image in the top of the JavaScript file, where you’ll also find the option to turn off the adding of position: relative to links and fields if you don’t want that. The script is kicked off with a call to supersleight.init() at the bottom. The scope of the script can be limited to just one part of the page by passing an ID of an element to supersleight.limitTo(). And that’s all there is to it. Update March 2008: a version of this script as a jQuery plugin is also now available. 2007 Drew McLellan drewmclellan 2007-12-01T00:00:00+00:00 https://24ways.org/2007/supersleight-transparent-png-in-ie6/ code
252 Turn Jekyll up to Eleventy Sometimes it pays not to over complicate things. While many of the sites we use on a daily basis require relational databases to manage their content and dynamic pages to respond to user input, for smaller, simpler sites, serving pre-rendered static HTML is usually a much cheaper — and more secure — option. The JAMstack (JavaScript, reusable APIs, and prebuilt Markup) is a popular marketing term for this way of building websites, but in some ways it’s a return to how things were in the early days of the web, before developers started tinkering with CGI scripts or Personal HomePage. Indeed, my website has always served pre-rendered HTML; first with the aid of Movable Type and more recently using Jekyll, which Anna wrote about in 2013. By combining three approachable languages — Markdown for content, YAML for data and Liquid for templating — the ergonomics of Jekyll found broad appeal, influencing the design of the many static site generators that followed. But Jekyll is not without its faults. Aside from notoriously slow build times, it’s also built using Ruby. While this is an elegant programming language, it is yet another ecosystem to understand and manage, and often alongside one we already use: JavaScript. For all my time using Jekyll, I would think to myself “this, but in Node”. Thankfully, one of Santa’s elves (Zach Leatherman) granted my Atwoodian wish and placed such a static site generator under my tree. Introducing Eleventy Eleventy is a more flexible alternative Jekyll. Besides being written in Node, it’s less strict about how to organise files and, in addition to Liquid, supports other templating languages like EJS, Pug, Handlebars and Nunjucks. Best of all, its build times are significantly faster (with future optimisations promising further gains). As content is saved using the familiar combination of YAML front matter and Markdown, transitioning from Jekyll to Eleventy may seem like a reasonable idea. Yet as I’ve discovered, there are a few gotchas. If you’ve been considering making the switch, here are a few tips and tricks to help you on your way1. Note: Throughout this article, I’ll be converting Matt Cone’s Markdown Guide site as an example. If you want to follow along, start by cloning the git repository, and then change into the project directory: git clone https://github.com/mattcone/markdown-guide.git cd markdown-guide Before you start If you’ve used tools like Grunt, Gulp or Webpack, you’ll be familiar with Node.js but, if you’ve been exclusively using Jekyll to compile your assets as well as generate your HTML, now’s the time to install Node.js and set up your project to work with its package manager, NPM: Install Node.js: Mac: If you haven’t already, I recommend installing Homebrew, a package manager for the Mac. Then in the Terminal type brew install node. Windows: Download the Windows installer from the Node.js website and follow the instructions. Initiate NPM: Ensure you are in the directory of your project and then type npm init. This command will ask you a few questions before creating a file called package.json. Like RubyGems’s Gemfile, this file contains a list of your project’s third-party dependencies. If you’re managing your site with Git, make sure to add node_modules to your .gitignore file too. Unlike RubyGems, NPM stores its dependencies alongside your project files. This folder can get quite large, and as it contains binaries compiled to work with the host computer, it shouldn’t be version controlled. Eleventy will also honour the contents of this file, meaning anything you want Git to ignore, Eleventy will ignore too. Installing Eleventy With Node.js installed and your project setup to work with NPM, we can now install Eleventy as a dependency: npm install --save-dev @11ty/eleventy If you open package.json you should see the following: … "devDependencies": { "@11ty/eleventy": "^0.6.0" } … We can now run Eleventy from the command line using NPM’s npx command. For example, to covert the README.md file to HTML, we can run the following: npx eleventy --input=README.md --formats=md This command will generate a rendered HTML file at _site/README/index.html. Like Jekyll, Eleventy shares the same default name for its output directory (_site), a pattern we will see repeatedly during the transition. Configuration Whereas Jekyll uses the declarative YAML syntax for its configuration file, Eleventy uses JavaScript. This allows its options to be scripted, enabling some powerful possibilities as we’ll see later on. We’ll start by creating our configuration file (.eleventy.js), copying the relevant settings in _config.yml over to their equivalent options: module.exports = function(eleventyConfig) { return { dir: { input: "./", // Equivalent to Jekyll's source property output: "./_site" // Equivalent to Jekyll's destination property } }; }; A few other things to bear in mind: Whereas Jekyll allows you to list folders and files to ignore under its exclude property, Eleventy looks for these values inside a file called .eleventyignore (in addition to .gitignore). By default, Eleventy uses markdown-it to parse Markdown. If your content uses advanced syntax features (such as abbreviations, definition lists and footnotes), you’ll need to pass Eleventy an instance of this (or another) Markdown library configured with the relevant options and plugins. Layouts One area Eleventy currently lacks flexibility is the location of layouts, which must reside within the _includes directory (see this issue on GitHub). Wanting to keep our layouts together, we’ll move them from _layouts to _includes/layouts, and then update references to incorporate the layouts sub-folder. We could update the layout: frontmatter property in each of our content files, but another option is to create aliases in Eleventy’s config: module.exports = function(eleventyConfig) { // Aliases are in relation to the _includes folder eleventyConfig.addLayoutAlias('about', 'layouts/about.html'); eleventyConfig.addLayoutAlias('book', 'layouts/book.html'); eleventyConfig.addLayoutAlias('default', 'layouts/default.html'); return { dir: { input: "./", output: "./_site" } }; } Determining which template language to use Eleventy will transform Markdown (.md) files using Liquid by default, but we’ll need to tell Eleventy how to process other files that are using Liquid templates. There are a few ways to achieve this, but the easiest is to use file extensions. In our case, we have some files in our api folder that we want to process with Liquid and output as JSON. By appending the .liquid file extension (i.e. basic-syntax.json becomes basic-syntax.json.liquid), Eleventy will know what to do. Variables On the surface, Jekyll and Eleventy appear broadly similar, but as each models its content and data a little differently, some template variables will need updating. Site variables Alongside build settings, Jekyll let’s you store common values in its configuration file which can be accessed in our templates via the site.* namespace. For example, in our Markdown Guide, we have the following values: title: "Markdown Guide" url: https://www.markdownguide.org baseurl: "" repo: http://github.com/mattcone/markdown-guide comments: false author: name: "Matt Cone" og_locale: "en_US" Eleventy’s configuration uses JavaScript which is not suited to storing values like this. However, like Jekyll, we can use data files to store common values. If we add our site-wide values to a JSON file inside a folder called _data and name this file site.json, we can keep the site.* namespace and leave our variables unchanged. { "title": "Markdown Guide", "url": "https://www.markdownguide.org", "baseurl": "", "repo": "http://github.com/mattcone/markdown-guide", "comments": false, "author": { "name": "Matt Cone" }, "og_locale": "en_US" } Page variables The table below shows a mapping of common page variables. As a rule, frontmatter properties are accessed directly, whereas derived metadata values (things like URLs, dates etc.) get prefixed with the page.* namespace: Jekyll Eleventy page.url page.url page.date page.date page.path page.inputPath page.id page.outputPath page.name page.fileSlug page.content content page.title title page.foobar foobar When iterating through pages, frontmatter values are available via the data object while content is available via templateContent: Jekyll Eleventy item.url item.url item.date item.date item.path item.inputPath item.name item.fileSlug item.id item.outputPath item.content item.templateContent item.title item.data.title item.foobar item.data.foobar Ideally the discrepancy between page and item variables will change in a future version (see this GitHub issue), making it easier to understand the way Eleventy structures its data. Pagination variables Whereas Jekyll’s pagination feature is limited to paginating posts on one page, Eleventy allows you to paginate any collection of documents or data. Given this disparity, the changes to pagination are more significant, but this table shows a mapping of equivalent variables: Jekyll Eleventy paginator.page pagination.pageNumber paginator.per_page pagination.size paginator.posts pagination.items paginator.previous_page_path pagination.previousPageHref paginator.next_page_path pagination.nextPageHref Filters Although Jekyll uses Liquid, it provides a set of filters that are not part of the core Liquid library. There are quite a few — more than can be covered by this article — but you can replicate them by using Eleventy’s addFilter configuration option. Let’s convert two used by our Markdown Guide: jsonify and where. The jsonify filter outputs an object or string as valid JSON. As JavaScript provides a native JSON method, we can use this in our replacement filter. addFilter takes two arguments; the first is the name of the filter and the second is the function to which we will pass the content we want to transform: // {{ variable | jsonify }} eleventyConfig.addFilter('jsonify', function (variable) { return JSON.stringify(variable); }); Jekyll’s where filter is a little more complicated in that it takes two additional arguments: the key to look for, and the value it should match: {{ site.members | where: "graduation_year","2014" }} To account for this, instead of passing one value to the second argument of addFilter, we can instead pass three: the array we want to examine, the key we want to look for and the value it should match: // {{ array | where: key,value }} eleventyConfig.addFilter('where', function (array, key, value) { return array.filter(item => { const keys = key.split('.'); const reducedKey = keys.reduce((object, key) => { return object[key]; }, item); return (reducedKey === value ? item : false); }); }); There’s quite a bit going on within this filter, but I’ll try to explain. Essentially we’re examining each item in our array, reducing key (passed as a string using dot notation) so that it can be parsed correctly (as an object reference) before comparing its value to value. If it matches, item remains in the returned array, else it’s removed. Phew! Includes As with filters, Jekyll provides a set of tags that aren’t strictly part of Liquid either. This includes one of the most useful, the include tag. LiquidJS, the library Eleventy uses, does provide an include tag, but one using the slightly different syntax defined by Shopify. If you’re not passing variables to your includes, everything should work without modification. Otherwise, note that whereas with Jekyll you would do this: <!-- page.html --> {% include include.html value="key" %} <!-- include.html --> {{ include.value }} in Eleventy, you would do this: <!-- page.html --> {% include "include.html", value: "key" %} <!-- include.html --> {{ value }} A downside of Shopify’s syntax is that variable assignments are no longer scoped to the include and can therefore leak; keep this in mind when converting your templates as you may need to make further adjustments. Tweaking Liquid You may have noticed in the above example that LiquidJS expects the names of included files to be quoted (else it treats them as variables). We could update our templates to add quotes around file names (the recommended approach), but we could also disable this behaviour by setting LiquidJS’s dynamicPartials option to false. Additionally, Eleventy doesn’t support the include_relative tag, meaning you can’t include files relative to the current document. However, LiquidJS does let us define multiple paths to look for included files via its root option. Thankfully, Eleventy allows us to pass options to LiquidJS: eleventyConfig.setLiquidOptions({ dynamicPartials: false, root: [ '_includes', '.' ] }); Collections Jekyll’s collections feature lets authors create arbitrary collections of documents beyond pages and posts. Eleventy provides a similar feature, but in a far more powerful way. Collections in Jekyll In Jekyll, creating collections requires you to add the name of your collections to _config.yml and create corresponding folders in your project. Our Markdown Guide has two collections: collections: - basic-syntax - extended-syntax These correspond to the folders _basic-syntax and _extended-syntax whose content we can iterate over like so: {% for syntax in site.extended-syntax %} {{ syntax.title }} {% endfor %} Collections in Eleventy There are two ways you can set up collections in 11ty. The first, and most straightforward, is to use the tag property in content files: --- title: Strikethrough syntax-id: strikethrough syntax-summary: "~~The world is flat.~~" tag: extended-syntax --- We can then iterate over tagged content like this: {% for syntax in collections.extended-syntax %} {{ syntax.data.title }} {% endfor %} Eleventy also allows us to configure collections programmatically. For example, instead of using tags, we can search for files using a glob pattern (a way of specifying a set of filenames to search for using wildcard characters): eleventyConfig.addCollection('basic-syntax', collection => { return collection.getFilteredByGlob('_basic-syntax/*.md'); }); eleventyConfig.addCollection('extended-syntax', collection => { return collection.getFilteredByGlob('_extended-syntax/*.md'); }); We can extend this further. For example, say we wanted to sort a collection by the display_order property in our document’s frontmatter. We could take the results of collection.getFilteredByGlob and then use JavaScript’s sort method to sort the result: eleventyConfig.addCollection('example', collection => { return collection.getFilteredByGlob('_examples/*.md').sort((a, b) => { return a.data.display_order - b.data.display_order; }); }); Hopefully, this gives you just a hint of what’s possible using this approach. Using directory data to manage defaults By default, Eleventy will maintain the structure of your content files when generating your site. In our case, that means /_basic-syntax/lists.md is generated as /_basic-syntax/lists/index.html. Like Jekyll, we can change where files are saved using the permalink property. For example, if we want the URL for this page to be /basic-syntax/lists.html we can add the following: --- title: Lists syntax-id: lists api: "no" permalink: /basic-syntax/lists.html --- Again, this is probably not something we want to manage on a file-by-file basis but again, Eleventy has features that can help: directory data and permalink variables. For example, to achieve the above for all content stored in the _basic-syntax folder, we can create a JSON file that shares the name of that folder and sits inside it, i.e. _basic-syntax/_basic-syntax.json and set our default values. For permalinks, we can use Liquid templating to construct our desired path: { "layout": "syntax", "tag": "basic-syntax", "permalink": "basic-syntax/{{ title | slug }}.html" } However, Markdown Guide doesn’t publish syntax examples at individual permanent URLs, it merely uses content files to store data. So let’s change things around a little. No longer tied to Jekyll’s rules about where collection folders should be saved and how they should be labelled, we’ll move them into a folder called _content: markdown-guide └── _content ├── basic-syntax ├── extended-syntax ├── getting-started └── _content.json We will also add a directory data file (_content.json) inside this folder. As directory data is applied recursively, setting permalink to false will mean all content in this folder and its children will no longer be published: { "permalink": false } Static files Eleventy only transforms files whose template language it’s familiar with. But often we may have static assets that don’t need converting, but do need copying to the destination directory. For this, we can use pass-through file copy. In our configuration file, we tell Eleventy what folders/files to copy with the addPassthroughCopy option. Then in the return statement, we enable this feature by setting passthroughFileCopy to true: module.exports = function(eleventyConfig) { … // Copy the `assets` directory to the compiled site folder eleventyConfig.addPassthroughCopy('assets'); return { dir: { input: "./", output: "./_site" }, passthroughFileCopy: true }; } Final considerations Assets Unlike Jekyll, Eleventy provides no support for asset compilation or bundling scripts — we have plenty of choices in that department already. If you’ve been using Jekyll to compile Sass files into CSS, or CoffeeScript into Javascript, you will need to research alternative options, options which are beyond the scope of this article, sadly. Publishing to GitHub Pages One of the benefits of Jekyll is its deep integration with GitHub Pages. To publish an Eleventy generated site — or any site not built with Jekyll — to GitHub Pages can be quite involved, but typically involves copying the generated site to the gh-pages branch or including that branch as a submodule. Alternatively, you could use a continuous integration service like Travis or CircleCI and push the generated site to your web server. It’s enough to make your head spin! Perhaps for this reason, a number of specialised static site hosts have emerged such as Netlify and Google Firebase. But remember; you can publish a static site almost anywhere! Going one louder If you’ve been considering making the switch, I hope this brief overview has been helpful. But it also serves as a reminder why it can be prudent to avoid jumping aboard bandwagons. While it’s fun to try new software and emerging technologies, doing so can require a lot of work and compromise. For all of Eleventy’s appeal, it’s only a year old so has little in the way of an ecosystem of plugins or themes. It also only has one maintainer. Jekyll on the other hand is a mature project with a large community of maintainers and contributors supporting it. I moved my site to Eleventy because the slowness and inflexibility of Jekyll was preventing me from doing the things I wanted to do. But I also had time to invest in the transition. After reading this guide, and considering the specific requirements of your project, you may decide to stick with Jekyll, especially if the output will essentially stay the same. And that’s perfectly fine! But these go to 11. Information provided is correct as of Eleventy v0.6.0 and Jekyll v3.8.5 ↩ 2018 Paul Lloyd paulrobertlloyd 2018-12-11T00:00:00+00:00 https://24ways.org/2018/turn-jekyll-up-to-eleventy/ content
174 Type-Inspired Interfaces One of the things that terrifies me most about a new project is the starting point. How is the content laid out? What colors do I pick? Once things like that are decided, it becomes significantly easier to continue design, but it’s the blank page where I spend the most time. To that end, I often start by choosing type. I don’t need to worry about colors or layout or anything else… just the right typefaces that support the art direction. (This article won’t focus on how to choose a typeface, but there are some really great resources if you interested in that sort of thing.) And just like that, all your work is done. “Hold it just a second,” you might say. “All I’ve done is pick type. I still have to do the rest!” To which I would reply, “Silly rabbit. You already have!” You see, picking the right typeface gets you farther than you might think. Here are a few tips on taking cues from type to design interfaces and interface elements. Perfecting Web 2.0 If you’re going for that beloved rounded corner look, you might class it up a bit by choosing the wonderful Omnes Pro by Joshua Darden. As the typeface already has a rounded aesthetic, making buttons that fit the style should be pretty easy. I’ve found that using multiples helps to keep your interfaces looking balanced and proportional. Noticing that the top left edge of the letter “P” has about an 12px corner radius, let’s choose a 24px radius for our button (a multiple of 2), so that we get proper rounded corners. By taking mathematical measurements from the typeface, our button looks more thought out than just “place arbitrary text on arbitrarily-sized button.” Pretty easy, eh? What’s in a name(plate)? Rounded buttons are pretty popular buttons nowadays, so let’s try something a bit more stylized. Have a gander at Brothers, a sturdy face from Emigre. The chiseled edges give us a perfect cue for a stylized button. Using the same slope, you can make plated-looking buttons that fit a different kind of style. Headlining You might even take some cues from the style of the typeface itself. Didone serifs are known for their lack of bracketsーthat is, a gradual transition from the stem to the serif. Instead, they typically connect at a right angle. Another common characteristic is the high contrast in the strokes: very thick stems, very thin serifs. So, when using a high contrast typeface, you can use it to your advantage to enhance hierarchy. Following our “multiples” guideline, a 12px measurement from the stems helps us create a top rule with a height of 24px (a multiple of 2). We can take the exact 1px measurement from the serif—a multiple of 1—to create the bottom rule. Voilà! I use this technique a lot. Swashbucklers And don’t forget the importance of visual “speed bumps” to break up long passages of text. A beautiful face like Alejandro Paul’s Ministry Script has over a thousand characters that can be manipulated or even combined to create elegant interface elements. Altering the partial differential character (∂) creates a delightful ornament that can help to guide the eye through content. Stagger & Swagger What about layout? How can we use typography to inform how our content is displayed? Let’s take a typeface like Assembler. We might use this for a design that needs to feel uneasy or uncomfortable. In design terms, that might translate into using irregular shapes and asymmetry. Using the proportional distances and degrees from the perpendiculars, we could easily create a multi-column layout that jives with the general tone. And for all you skeptics that don’t think a layout like this is doable on the web, stranger things have happened. Background texture generously offered by Bittbox. Overall Design Direction Finally, your typography could impact the entire look of the site, from the navigation to the interaction and everything in between. Check out how the (now-defunct) Nike Free site’s typography echoes the product itself, and in turn influences the navigation. Find Your Type With thousands of fonts to choose from, the possibilities are ridiculously open. From angles to radii to color to weight, you’ve got endless fodder before you. Great type designers spent countless hours slaving over these detailed letterforms; take advantage of it! Don’t feel like you have to limit yourself to the same old Helvetica and wet floors… unless your design calls for it. Happy hunting! 2009 Dan Mall danmall 2009-12-07T00:00:00+00:00 https://24ways.org/2009/type-inspired-interfaces/ design