Daily Link Aggregating from the Best Design & Showcase Sites
17,217 Links to Search From


30+ Best Procreate Brushes

Posted by Design Shack - 39 mins ago
If you’re a digital artist searching for the perfect Procreate brush to craft stunning illustrations or to design unique website header images, we’ve got a great collection of professional Procreate brushes just for you. Procreate is amongst the most popular drawing apps available for iPad Pro. It’s actually more than just a simple drawing app....

Concrete

Posted by cssdsgn - 6 hours ago

Accessibility Through Semantic HTML

Posted by 24 Ways - 15 hours ago

Laura Kalbag takes us back to basics to make sure we consider accessibility when structuring our HTML. The Christmas tree needs to be standing firm before we drape it in lights and tinsel, and until you lot start doing it, we’re not going to stop preaching it.


Brought to you by An Event Apart. Discover the future of web design. At the UX and front-end conference where the future always seems to arrive first.


Working on Better, a tracker blocker, I spend an awful lot of my time with my nose in other people’s page sources. I’m mostly there looking for harmful tracking scripts, but often notice the HTML on some of the world’s most popular sites is in a sad state of neglect.

What does neglected HTML look like? Here’s an example of the markup I found on a news site just yesterday. There’s a bit of text, a few links, and a few images. But mostly it’s div elements.

<div>
  <div>
    <div>
      <div id="block1242235">
        <div>
          <div>
            <a href="#"><i></i></a>
          </div>
          <div></div>
          Some text <span>more text</span>
        </div>
      </div>
    </div>
  </div>
</div>

divs and spans, why do we use them so much?

While I find tracking scripts completely inexcusable, I do understand why people write HTML like the above. As developers, we like to use divs and spans as they’re generic elements. They come with no associated default browser styles or behaviour except that div displays as a block, and span displays inline. If we make our page up out of divs and spans, we know we’ll have absolute control over styles and behaviour cross-browser, and we won’t need a CSS reset.

Absolute control may seem like an advantage, but there’s a greater benefit to less generic, more semantic elements. Browsers render semantic elements with their own distinct styles and behaviours. For example, button looks and behaves differently from a. And ul is different from ol. These defaults are shortcuts to a more usable and accessible web. They provide consistent and well-tested components for common interactions.

Semantic elements aid usability

A good example of how browser defaults can benefit the usability of an element is in the <select> option menu. In Safari on the desktop, the browser renders <select> as a popover-style menu. On a touchscreen, Safari overlays the same menu over the lower half of the screen as a “picker view.”

Option menu in Safari on macOS.
Option menu picker in Safari on iOS.

The iOS picker is a much better experience than struggling to pick from a complicated interface inside the page. The menu is shown more clearly than in the confined space on the page, which makes the options easier to read. The required swipe and tap gestures are consistent with the rest of the operating system, making the expected interaction easier to understand. The whole menu is scaled up, meaning the gestures don’t need such fine motor control. Good usability is good accessibility.

When we choose to use a div or span over a more semantic HTML element, we’re also doing hard work the browser could be doing for us. We don’t need to tie ourselves in knots making a custom div into a keyboard navigable option menu. Using select passes the bulk of the responsibility over to the browser. 

Letting the browser do most of the work is also more future-friendly. More devices, with different expected interactions, will be released in the future. When that happens, the devices’ browsers can adapt our sites according to those interactions. Then we can spend our time doing something more fun than rewriting cross-browser JavaScript for each new device.

HTML’s impact on accessibility

Assistive technology also uses semantic HTML to understand how best to convey each element to its user.

For screen readers

Semantic HTML gives context to screen readers. Screen readers are a type of assistive technology that reads the content of the screen to the person using it. All sites have a linear page source. Sighted visitors can use visual cues on the page to navigate to their desired content in a non-linear fashion. As screen readers output audio (and sometimes braille), those visual cues aren’t usable in the same way.

Screen readers provide alternative means of navigation, enabling people to jump between different types of content, such as links, forms, headings, lists, and paragraphs. If all our content is marked up using divs and spans, we’re not giving screen readers a chance to index the valuable content.

For keyboard navigation

Keyboard-only navigation is also aided by semantic HTML. Forms, option menus, navigation, video, and audio are particularly hard for people relying on a keyboard to access. For instance, option menus and navigation can be very fiddly if you need to use a mouse to hover a menu open and move to select the desired item at the same time. 

Again, we can leave much of the interaction to the browser through semantic HTML. Semantic form elements can convey if a check box has been checked, or which label is associated with which input field. These default behaviours can make the difference between a person being able to use a form or leaving the site out of frustration.

Did I convince you yet? I hope so. Let’s finish with some easy guidelines to follow.

1. Use the most semantic HTML element for the job

When you reach for a div, first check if there’s a better element to do the job. What is the role of that element? How should a person be interacting with the element?

Are you using class names like nav, header, or main? There are HTML5 elements for those sections! Using specific elements can also make writing CSS simpler, and ensure a consistent design with minimal effort.

2. Separate structure and style

Don’t choose HTML elements based on how they’re styled in your CSS. Nowadays, common practice is to use class names rather than elements for CSS selectors. You’re unlikely to wrap all your page content in an <h1> element because you want all the text to be big and bold. Still, it can be easy to choose an HTML element because it will be the easiest to style. Focusing on content without style will help us choose the most semantic HTML element without that temptation. For example, you could add a class of .btn to a div to make it look like a button. But we all know that only a button will really behave like a button.

3. Use progressive enhancement for enhanced functionality

Airbnb and Groupon recently proved we’re not past the laziness of “this site only works in X browser.” Baffling disregard for the open web aside, making complex interactive experiences work cross-browser and cross-device is not easy. We can use progressive enhancement to layer fancy or unsupported features on top of a baseline “it works” experience. 

We should build the baseline experience on a foundation of accessible, semantic HTML. Then, if you really want to add a specific feature for a proprietary browser, you can layer that on top, without breaking the underlying experience.

4. Test your work

Validators are always valuable for checking the browser will be able to correctly interpret your markup. Document outline checkers can be valuable for testing your structure, but be aware that the HTML5 document outline is not actually implemented in browsers.

Once you’ve got something resembling a web page, test the experience! Ensure that semantic HTML element you chose looks and behaves in a predictable manner consistent with its use across the web. Test cross-browser, test cross-device, and test with assistive technology. Testing with assistive technology is not as expensive as it used to be, you can even use your smartphone for testing on iOS and Android. Your visitors will thank you!

Further reading


About the author

Laura Kalbag is a designer from the UK, and author of Accessibility For Everyone from A Book Apart. She’s one third of Ind.ie, a tiny two-person-and-one-husky not-for-profit working for social justice in the digital age. At Ind.ie, Laura follows the Ethical Design Manifesto, and works on a web privacy tool called Better.

More articles by Laura

Zero Studios

Posted by cssdsgn - 1 day ago

Shared Text Styles

Posted by One Page Love - 2 days ago
Clean One Pager for Shared Text Styles – a free plugin to easily import and export your text styles in Sketch. Neat touch how the site actually hides the download button on mobile – as you wouldn’t need it. Full Review | Direct Link

How to Teach Marketers to Design: 3 Tips and 4 Essential Tools

Posted by Web Designer Depot - 2 days ago
Professionals often interpret things differently: a common problem when a marketer sets a brief for a designer without clear instructions, is the designer has to redo the project countless times until they are both satisfied with the final result. Sometimes the task can be trivial, so much so that it’s quicker and easier for marketers […]

The Fine Line

Posted by Best Web Gallery - 2 days ago

The Warren Trust

Posted by Site Inspire - 3 days ago

5 Ways to Make Your Users Angry (And Productive)

Posted by Web Designer Depot - 3 days ago
Now why on Earth would you want to make anyone angry? Angry people are unpleasant to deal with at the best of times. Getting users angry seems awfully counterproductive. Why did you even write this stu… Well, you don’t want them angry at you, of course. I wrote a whole article about that. Anger, temporary […]

The White Rabbit Collection

Posted by cssdsgn - 3 days ago

Wavy

Posted by Site Inspire - 2 hours ago

Jake Stangel

Posted by Site Inspire - 6 hours ago

Bands For Hire

Posted by CSS Mania - 23 hours ago

Open Wear

Posted by Awwwards - 1 day ago
Experience the flow of powder riding in the new e-commerce platform for sustainable outerwear of Open Wear.

Ben Mingo

Posted by cssdsgn - 2 days ago

Faculty

Posted by Site Inspire - 2 days ago

Getting Hardboiled with CSS Custom Properties

Posted by 24 Ways - 3 days ago

Andy Clarke lifts the lid on Custom Properties, and adds a little spice with an elegant method for providing fallbacks for those with older browsers. Remember, at Christmas we all need to look out for our elders, be they friends, family or even just browsers.


Sponsor: Aquent Gymnasium offers free online courses on web development, design, user experience, and content.


Custom Properties are a fabulous new feature of CSS and have widespread support in contemporary browsers. But how do we handle browsers without support for CSS Custom Properties? Do we wait until those browsers are lying dead in a ditch before we use them? Do we tool up and prop up our CSS using a post-processor? Or do we get tough? Do we get hardboiled?

Previously only pre-processing tools like LESS and Sass enabled developers to use variables in their stylesheets, but now Custom Properties have brought variables natively to CSS.

How do you write a custom property? It’s hardly a mystery. Simply add two dashes to the start of a style rule. Like this:

--color-text-default : black;

If you’re more the underscore type, try this:

--color_text_default : black;

Hyphens or underscores are allowed in property names, but don’t be a chump and try to use spaces.

Custom property names are also case-sensitive, so --color-text-default and --Color_Text_Default are two distinct properties.

To use a custom property in your style rules, var() tells a browser to retrieve the value of a property. In the next example, the browser retrieves the black colour from the color-text-default variable and applies it to the body element:

body {
    color : var(--color-text-default); 
}

Like variables in LESS or Sass, CSS Custom Properties mean you don’t have to be a dumb mug and repeat colour, font, or size values multiple times in your stylesheets. Unlike a preprocessor variable though, CSS Custom Properties use the cascade, can be modified by media queries and other state changes, and can also be manipulated by Javascript.

(Serg Hospodarets wrote a fabulous primer on CSS Custom Properties where he dives deeper into the code and possible applications.)

Browser support

Now it’s about this time that people normally mention browser support. So what about support for CSS Custom Properties? Current versions of Chrome, Edge, Firefox, Opera, and Safari are all good. Internet Explorer 11 and before? Opera Mini? Nasty.

Sound familiar?

Can I Use css-variables? Data on support for the css-variables feature across the major browsers from caniuse.com.

Not to worry, we can manually check for Custom Property support in a browser by using an @support directive, like this:

--color-text-default : black;

body {
    color : black;  
}

@supports ((--foo : bar)) {
    body {
        color : var(--color-text-default); 
    }
}

In that example we first set body element text to black and then override that colour with a Custom Property value when the browser supports our fictitious foo bar variable.

Post-processing

Of course we could use a post-processor plugin to turn Custom Properties into plain CSS, but hang on one goddam minute kiddo.

Haven’t we been down this road before? Didn’t we engineer elaborate workarounds to enable us to use ‘advanced’ CSS3 properties like border-radius, CSS columns, and Flexbox in the past? We did what we had to do to get the job done, but came away feeling dirty.

I think there’s a better way, one that allows us to enjoy the benefits of CSS Custom Properties in browsers that support them, while providing an appropriate, but not identical experience, for people who use less capable browsers. Guess what, I’ve been down this road before too.

2Tone Stuff & Nonsense

When Internet Explorer 6 was the big dumb browser everyone hated, I served two different designs on my website.

For the modern browsers of the time, mod arrows and targets were everywhere in glorious red, white, and blue, and I implemented all of them using CSS attribute selectors which were considered advanced at the time:

[class="banner"] {
    background-colour : red; 
}

Internet Explorer 6 ignored any selectors it didn’t understand, so people using that browser saw a simpler black and white, 2Tone-based design that I’d implemented for them using class selectors:

.banner {
    background-colour : black; 
}

You don’t have to be a detective to find out that most people thought I’d lost my wits, but Microsoft even used my website as a reference when they tested attribute selectors in Internet Explorer 7. They did, as I suggested, “Stomp to da betta browser.”

Substitutions

So how does this approach relate to tackling any lack of support for CSS Custom Properties? How can we take advantage of them without worrying about browsers with no support and having to implement complex workarounds?

Turns out, the answer is substitutions and guess what, they’re built right into CSS Custom Properties. Substitutions are similar to font stacks in that they contain a comma separated list of values:

body {
    color : var(--color-text-default), black; 
}

If a browser’s too damn stupid to understand the first variable value it encounters (var(--color-text-default)), it will ignore it and move onto the next value in the list (black).

Repeat this for every style that contains a variable, baking an alternative, perhaps simpler design into your stylesheets for people who use less capable browsers, just like I did with Stuff & Nonsense.

Conclusion

I doubt that anyone agrees with presenting a design that looks broken or unloved—and I’m not advocating for that—but websites need not look the same in every browser. We can use substitutions to present a simpler design to people using less capable browsers.

The decision when to start using new CSS properties isn’t always a technical one. Sometimes a change in attitude about browser support is all that’s required. So get tough with dumb browsers and benefit from all the advantages that CSS Custom Properties offer. Get hardboiled.

Resources:


About the author

Andy Clarke is one of the world’s best-known digital designers, a speaker, and writer, now based in Sydney, Australia. He works as Head of Design at Ansarada, helping the company to express its brand strategy through digital products and marketing. Andy founded Stuff & Nonsense in 1998 specialising in creative design for digital products and websites.

Andy’s the author of three web design books including ‘Transcending CSS’ and ‘Hardboiled Web Design Fifth Anniversary Edition’ and is known for his many conference presentations and contributions to the web design industry. He really, really loves gorillas.

More articles by Andy

Friends & Associates

Posted by One Page Love - 3 days ago
Dark-schemed One Pager with a splash of brutalism for Friends & Associates – a series of exhibitions celebrating contemporary design. Full Review | Direct Link

Breaking the Grid Without Breaking Design

Posted by Web Designer Depot - 3 days ago
Symmetry is safe. It’s comfortable, non-threatening, and aesthetically pleasing. It can also be very dull. Using ‘asymmetrical balance’ can make things more interesting while still sticking to a grid to keep things ordered. In design, as in so many other things, the higher the risks the greater the potential rewards. Symmetry has long been considered […]

The Disaster Artist

Posted by Awwwards - 3 days ago
Welcome to official website for The Disaster Artist, a place for dreams. Read latest on movie, see what friends of Tommy think of movie, and just have fun guys.

Concrete

Posted by Site Inspire - 3 hours ago

Waters

Posted by Site Inspire - 6 hours ago

Pantone’s Color of the Year: Ultra Violet (And How to Use It)

Posted by Design Shack - 1 day ago
Ultra Violet. It sounds like the name of a pop band. Pantone’s Color of the Year for 2018 is inspired by music and art and individuality. The color is reminiscent of Prince’s famous purple and it is part of a growing trend in design to use bolder, brighter colors in more projects. Here’s a look...

CSS Conf

Posted by Best Web Gallery - 1 day ago

MyWoodenlife

Posted by cssdsgn - 2 days ago

A Message From Earth

Posted by cssdsgn - 2 days ago

How to Create a Beautiful Website With Wix

Posted by Design Shack - 3 days ago
You don’t need a graphic design or computer science degree to create a beautiful and functional website. Thanks to Wix, a website builder, anyone can create a stylish website, all on their own. What sets Wix apart from some of the other tools out there is that it allows you full creative freedom to create...

10 Web Design Trends to Watch for in 2018

Posted by Design Shack - 3 days ago
As 2017 winds down, it’s a good time to reflect on the accomplishments of the past year and start thinking about designs yet to come. Looking at more recent designs, redesigns and even just design tweaks, a few distinct trends are starting to emerge as the front-runners heading into 2018. Here’s a look at some...

The Warren Trust

Posted by cssdsgn - 3 days ago

Maria Callas official website

Posted by Awwwards - 3 days ago
Warner Classics is celebrating her life, her voice, her iconic style, and her legacy with the first official website dedicated to La Divina.

The Simple Way to Turn Your WordPress Website Into a Mobile App

Posted by Web Designer Depot - 5 hours ago
Even if your WordPress website is mobile-first and responsive, you could still be missing out on a huge chunk of traffic by not offering your visitors a mobile app, and the smooth user experience that comes with it. The only problem is that it’s incredibly difficult (and expensive) to build a native mobile app from […]

Club of the Waves

Posted by css Drive - Gallery - 6 hours ago

10 Game-Changing SEO Tips For Ecommerce in 2018

Posted by Web Designer Depot - 1 day ago
Traffic is among the deciding factors which determine the ultimate success of an e-commerce website. As it brings potential customers to the businesses, it also helps maintain a robust rank among competitors in Google SERPs. Visibility is the key factor that ensures a website remains displayed on SERPs and keeps attracting users towards its products […]

Why Design Systems Fail

Posted by 24 Ways - 2 days ago

Una Kravets takes some time to consider the implementation of design systems, and how and why they might not succeed. Don’t let your design system be like a New Year’s resolution that starts off well but fades by the Spring. With appropriate care it should start to blossom as the snow melts away.


Brought to you by The CSS Layout Workshop. Does developing layouts with CSS seem like hard work? How much time could you save without all the trial and error? Are you ready to really learn CSS layout?


Design systems are so hot right now, and for good reason. They promote a modular approach to building a product, and ensure organizational unity and stability via reusable code snippets and utility styles. They make prototyping a breeze, and provide a common language for both designers and developers.

A design system is a culmination of several individual components, which can include any or all of the following (and more):

  • Style guide or visual pattern library
  • Design tooling (e.g. Sketch Library)
  • Component library (where the components live in code)
  • Code usage guidelines and documentation
  • Design usage documentation
  • Voice and tone guideline
  • Animation language guideline

Design systems are standalone (internal or external) products, and have proven to be very effective means of design-driven development. However, in order for a design system to succeed, everyone needs to get on board.

I’d like to go over a few considerations to ensure design system success and what could hinder that success.

Organizational Support

Put simply, any product, including internal products, needs support. Something as cross-functional as a design system, which spans every vertical project team, needs support from the top and bottom levels of your organization.

What I mean by that is that there needs to be top-level support from project managers up through VP’s to see the value of a design system, to provide resources for its implementation, and advocate for its use company-wide. This is especially important in companies where such systems are being put in place on top of existing, crufty codebases, because it may mean there needs to be some time and effort put in the calendar for refactoring work.

Support from the bottom-up means that designers and engineers of all levels also need to support this system and feel responsibility for it. A design system is an organization’s product, and everyone should feel confident contributing to it. If your design system supports external clients as well (such as contractors), they too can become valuable teammates.

A design system needs support and love to be nurtured and to grow. It also needs investment.

Investment

To have a successful design system, you need to make a continuous effort to invest resources into it. I like to compare this to working out.

You can work out intensely for 3 months and see some gains, but once you stop working out, those will slowly fade away. If you continue to work out, even if its less often than the initial investment, you’ll see yourself maintaining your fitness level at a much higher rate than if you stopped completely.

If you invest once in a design system (say, 3 months of overhauling it) but neglect to keep it up, you’ll face the same situation. You’ll see immediate impact, but that impact will fade as it gets out of sync with new designs and you’ll end up with strange, floating bits of code that nobody is using. Your engineers will stop using it as the patterns become outdated, and then you’ll find yourself in for another round of large investment (while dreading going through the process since its fallen so far out of shape).

With design systems, small incremental investments over time lead to big gains overall.

With this point, I also want to note that because of how they scale, design systems can really make a large impact across the platform, making it extremely important to really invest in things like accessibility and solid architecture from the start. You don’t want to scale a brittle system that’s not easy to use.

Take care of your design systems, and keep working on them to ensure their effectiveness. One way to ensure this is to have a dedicated team working on this design system, managing tickets and styling updates that trickle out to the rest of your company.

Responsibility

With some kind of team to act as an owner of a design system, whether it be the design team, engineering team, or a new team made of both designers and engineers (the best option), your company is more likely to keep a relevant, up-to-date system that doesn’t break.

This team is responsible for a few things:

  • Helping others get set up on the system (support)
  • Designing and building components (development)
  • Advocating for overall UI consistency and adherence (evangelism)
  • Creating a rollout plan and update system (product management)

As you can see, these are a lot of roles, so it helps to have multiple people on this team, at least part of the time, if you can. One thing I’ve found to be effective in the past is to hold office hours for coworkers to book slots within to help them get set up and to answer any questions about using the system. Having an open Slack channel also helps for this sort of thing, as well as for bringing up bugs/issues/ideas and being an channel for announcements like new releases.

Communication

Once you have resources and a plan to invest in a design system, its really important that this person or team acts as a bridge between design and engineering. Continuous communication is really important here, and the way you communicate is even more important.

Remember that nobody wants to be told what to do or prescribed a solution, especially developers, who are used to a lot of autonomy (usually they get to choose their own tools at work). Despite how much control the other engineers have on the process, they need to feel like they have input, and feel heard.

This can be challenging, especially since ultimately, some party needs to be making a final decision on direction and execution. Because it’s a hard balance to strike, having open communication channels and being as transparent as possible as early as possible is a good start.

Buy-in

For all of the reasons we’ve just looked over, good communication is really important for getting buy-in from your users (the engineers and designers), as well as from product management.

Building and maintaining a design system is surprisingly a lot of people-ops work.

To get buy-in where you don’t have a previous concensus that this is the right direction to take, you need to make people want to use your design system. A really good way to get someone to want to use a product is to make it the path of least resistance, to show its value.

Gather examples and usage wins, because showing is much more powerful than telling.

If you can, have developers use your product in a low-stakes situation where it provides clear benefits. Hackathons are a great place to debut your design system. Having a hackathon internally at DigitalOcean was a perfect opportunity to:

  • Evangelize for the design system
  • See what people were using the component library for and what they were struggling with (excellent user testing there)
  • Get user feedback afterward on how to improve it in future iterations
  • Let people experience the benefits of using it themselves

These kinds of moments, where people explore on their own are where you can really get people on your side and using the design system, because they can get their hands on it and draw their own conclusions (and if they don’t love it — listen to them on how to improve it so that they do). We don’t always get so lucky as to have this sort of instantaneous user feedback from our direct users.

Architecture

I briefly mentioned the scalable nature of design systems. This is exactly why it’s important to develop a solid architecture early on in the process. Build your design system with growth and scalability in mind. What happens if your company acquires a new product? What happens when it develops a new market segment? How can you make sure there’s room for customization and growth?

A few things we’ve found helpful include:

Namespacing

Use namespacing to ensure that the system doesn’t collide with existing styles if applying it to an existing codebase. This means prefixing every element in the system to indicate that this class is a part of the design system. To ensure that you don’t break parts of the existing build (which may have styled base elements), you can namespace the entire system inside of a parent class. Sass makes this easy with its nested structure.

This kind of namespacing wouldn’t be necessary per se on new projects, but it is definitely useful when integrating new and old styles.

Semantic Versioning

I’ve used Semantic Versioning on all of the design systems I’ve ever worked on. Semantic versioning uses a system of Major.Minor.Patch for any updates. You can then tag released on Github with versioned updates and ensure that someone’s app won’t break unintentionally when there is an update, if they are anchored to a specific version (which they should be).

We also use this semantic versioning as a link with our design system assets at DigitalOcean (i.e. Sketch library) to keep them in sync, with the same version number corresponding to both Sketch and code.

Our design system is served as a node module, but is also provided as a series of built assets using our CDN for quick prototyping and one-off projects. For these built assets, we run a deploy script that automatically creates folders for each release, as well as a latest folder if someone wanted the always-up-to-date version of the design system.

So, semantic versioning for the system I’m currently building is what links our design system node module assets, sketch library assets, and statically built file assets.

The reason we have so many ways of consuming our design system is to make adoption easier and to reduce friction.

Friction

A while ago, I posed the question of why design systems become outdated and unused, and a major conclusion I drew from the conversation was:

“If it’s harder for people to use than their current system, people just won’t use it”

You have to make your design system the path of least resistance, lowering cognitive overhead of development, not adding to it. This is vital. A design system is intended to make development much more efficient, enforce a consistent style across sites, and allow for the developer to not worry as much about small decisions like naming and HTML semantics. These are already sorted out for them, meaning they can focus on building product.

But if your design system is complicated and over-engineered, they may find it frustrating to use and go back to what they know, even if its not the best solution. If you’re a Sass expert, and base your system on complex mixins and functions, you better hope your user (the developer) is also a Sass expert, or wants to learn. This is often not the case, however. You need to talk to your audience.

With the DigitalOcean design system, we provide a few options:

Option 1

Users can implement the component library into a development environment and use Sass, select just the components they want to include, and extend the system using a hook-based system. This is the most performant and extensible output. Only the components that are called upon are included, and they can be easily extended using mixins.

But as noted earlier, not everyone wants to work this way (including Sass a dependency and potentially needing to set up a build system for it and learn a new syntax). There is also the user who just wants to throw a link onto their page and have it look nice, and thats where our versioned built assets come in.

Option 2

With Option 2, users pull in links that are served via a CDN that contain JS, CSS, and our SVG icon library. The code is a big bigger than the completely customized version, but often this isn’t the aim when people are using Option 2.

Reducing friction for adoption should be a major goal of your design system rollout.

Conclusion

Having a design system is really beneficial to any product, especially as it grows. In order to have an effective system, it’s important to primarily always keep your user in mind and garner support from your entire company. Once you have support and acceptance, this system will flourish and grow. Make sure someone is responsible for it, and make sure its built with a solid foundation from the start which will be carefully maintained toward the future. Good luck, and happy holidays!


About the author

Una Kravets is an international speaker, technical writer, open source advocate, and UI Engineer on the UX team at DigitalOcean. Una also co-hosts the Toolsday podcast and started both the DC and Austin Sass Meetups. She’s a performance nerd, loves the open source community and listens to way too many audio books.

More articles by Una

Bigtime.

Posted by cssdsgn - 2 days ago

Troa

Posted by cssdsgn - 2 days ago

Dot

Posted by Site Inspire - 3 days ago

Teach the CLI to Talk Back

Posted by 24 Ways - 3 days ago

Anna Debenham sets out to humanise our interactions with the command line to put more of the user into the user interface. Like an injured hedgehog in the winter snow, sometimes we can all benefit from interacting with a human.


Brought to you by With Jack. With Jack helps you freelance confidently. Jack arranges insurance for designers and developers that protects you financially and legally when problems happen, keeping you in business.


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!


About the author

Anna Debenham lives in London and is Snyk’s Lead Front-End Developer.

She’s the author of Front-end Style Guides, and when she’s not playing on them, she’s testing as many game console browsers as she can get her hands on.

More articles by Anna

Spazio Maiocchi

Posted by cssdsgn - 3 days ago

Tao Tajima

Posted by Site Inspire - 3 days ago

Bachoy

Posted by One Page Love - 5 hours ago
Impressive dark-schemed One Page portfolio for Ryan Magno. The Single Page website features loads of attention to detail including a command prompt style intro text, spotlight effect background, hover sensitive content items and changing backgrounds to match the current project you are browsing. Full Review | Direct Link

Paradiso

Posted by Awwwards - 7 hours ago
Paradiso offers more than 1000 programs. They play an important role in the recent history of Amsterdam and in the Dutch pop culture in general.We've created a full responsive site.

Volta Loftid

Posted by css Drive - Gallery - 1 day ago

Chris Shiflett

Posted by Site Inspire - 2 days ago

Folder Studio

Posted by cssdsgn - 2 days ago

TAO TAJIMA | Filmmaker

Posted by Awwwards - 2 days ago
A director and film maker with the Tokyo visual design studio Tangram.

The Sill

Posted by Site Inspire - 3 days ago

Design Systems and CSS Grid

Posted by 24 Ways - 3 days ago

Stuart Robson tackles the thorny issue of integrating modern CSS Grid layouts into an existing design system, but in doing so reaps the benefits of leaner, more easily maintainable markup. It goes to show that with careful planning, there’s no reason old and new CSS layout methods cannot meet under the mistletoe.


Brought to you by An Event Apart. What’s better? Mastering cutting-edge techniques, or crafting great user experiences? Why choose between them? Attend the one conference that helps you do both.


Recently, my client has been looking at creating a few new marketing pages for their website. They currently have a design system in place but they’re looking to push this forward into 2018 with some small and possibly some larger changes.

To start with we are creating a couple of new marketing pages. As well as making use of existing components within the design systems component library there are a couple of new components. Looking at the first couple of sketch files I felt this would be a great opportunity to use CSS Grid, to me the newer components need to be laid out on that page and grid would help with this perfectly.

As well as this layout of the new components and the text within it, imagery would be used that breaks out of the grid and pushes itself into the spaces where the text is aligned.

The existing grid system

When the site was rebuilt in 2015 the team decided to make use of Sass and Susy, a “lightweight grid-layout engine using Sass”. It was built separating the grid system from the components that would be laid out on the page with a container, a row, an optional column, and a block.

To make use of the grid system on a page for a component that would take the full width of the row you would have to write something like this:

<div>
  <div>
    <div>
      <div>
        <!-- component code here -->
      </div>
    </div>
  </div>
</div>

Using a grid system similar to this can easily create quite the tag soup. It could fill the HTML full of divs that may become complex to understand and difficult to edit.

Although there is this reliance on several <div>s to lay out the components on a page it does allow a tidy way to place the component code within that page. It abstracts the layout of the page to its own code, its own system, so the components can ‘fit’ where needed.

The requirements of the new grid system

Moving forward I set myself some goals for what I’d like to have achieved in this new grid system:

It needs to behave like the existing grid systems

We are not ripping up the existing grid system, it would be too much work, for now, to retrofit all of the existing components to work in a grid that has a different amount of columns, and spacing at various viewport widths.

Allow full-width components

Currently the grid system is a 14 column grid that becomes centred on the page when viewport is wide enough. We have, in the past, written some CSS that would allow for a full-width component, but his had always felt like a hack. We want the option to have a full-width element as part of the new grid system, not something that needs CSS to fight against.

Less of a tag soup

Ideally we want to end up writing less HTML to layout the page. Although the existing system can be quite clear as to what each element is doing, it can also become a little laborious in working out what each grid row or block is doing where.

I would like to move the layout logic to CSS as much as is possible, potentially creating some utility classes or additional ‘layout classes’ for the components.

Easier for people to use and author

With many people using the existing design systems codebase we need to create a new grid system that is as easy or easier to use than the existing one. I think and hope this would be helped by removing as many <div>s as needed and would require new documentation and examples, and potentially some initial training.

Separating layout from style

There still needs to be a separation of layout from the styles for the component. To allow for the component itself to be placed wherever needed in the page we need to make sure that the CSS for the layout is a separate entity to the CSS for that styling.

With these base requirements I took to CodePen and started working on some throwaway code to get started.

Making the new grid(s)

The Full-Width Grid

To start with I created a grid that had three columns, one for the left, one for the middle, and one for the right. This would give the full-width option to components.

Thankfully, one of Rachel Andrew’s many articles on Grid discussed this exact requirement of the new grid system to break out with Grid.

I took some of the code in the examples and edited to make grid we needed.

.container {
  display: grid;
  grid-template-columns:
    [full-start]
      minmax(.75em, 1fr)
        [main-start]
          minmax(0, 1008px)
        [main-end]
      minmax(.75em, 1fr)
    [full-end];
}

We are declaring a grid, we have four grid column lines which we name and we define how the three columns they create react to the viewport width. We have a left and right column that have a minimum of 12px, and a central column with a maximum width of 1008px.

Both left and right columns fill up any additional space if the viewport is wider that 1032px wide. We are also not declaring any gutters to this grid, the left and right columns would act as gutters at smaller viewports.

At this point I noticed that older versions of Sass cannot parse the brackets in this code. To combat this I used Sass’ unquote method to wrap around the value of the grid-template-column.

.container {
  display: grid;
  grid-template-columns:
  unquote("
    [full-start]
      minmax(.75em, 1fr)
        [main-start]
          minmax(0, 1008px)
        [main-end]
      minmax(.75em, 1fr)
    [full-end]
  ");
}

The existing codebase makes use of Sass variables, mixins and functions so to remove that would be a problem, but luckily the version of Sass used is up-to-date (note: example CodePens will be using CSS).

The initial full-width grid displays on a webpage as below:

The 14 column grid

I decided to work out the 14 column grid as a separate prototype before working out how it would fit within the full-width grid. This grid is very similar to the 12 column grids that have been used in web design. Here we need 14 columns with a gutter between each one.

Along with the many other resources on Grid, Mozilla’s MDN site had a page on common layouts using CSS Grid. This gave me the perfect CSS I needed to create my grid and I edited it as required:

.inner {
  display: grid;
  grid-template-columns: repeat(14, [col-start] 1fr);
  grid-gap: .75em;
}

We, again, are declaring a grid, and we are splitting up the available space by creating 14 columns with 1 fr-unit and giving each one a starting line named col-start.

This grid would display on web page as below:

Bringing the grids together

Now that we have got the two grids we need to help fulfil our requirements we need to put them together so that they are actually we we need.

The subgrid

There is no subgrid in CSS, yet. To workaround this for the new grid system we could nest the 14 column grid inside the full-width grid.

In the HTML we nest the 14 column inner grid inside the full-width container.

<div>
  <div>
  </div>
</div>

So that the inner knows where to be laid out within the container we tell it what column to start and end with, with this code it would be the start and end of the main column.

.inner {
  display: grid;
  grid-column: main-start / main-end;
  grid-template-columns: repeat(14, [col-start] 1fr);
  grid-gap: .75em;
}

The CSS for the container remains unchanged.

This works, but we have added another div to our HTML. One of our requirements is to try and remove the potential for tag soup.

The faux subgrid subgrid

I wanted to see if it would be possible to place the CSS for the 14 column grid within the CSS for the full-width grid. I replaced the CSS for the main grid and added the grid-column-gap to the .container.

.container {
  display: grid;
  grid-gap: .75em;
  grid-template-columns:
    [full-start]
      minmax(.75em, 1fr)
        [main-start]
          repeat(14, [col-start] 1fr)
        [main-end]
      minmax(.75em, 1fr)
    [full-end];
}

What this gave me was a 16 column grid. I was unable to find a way to tell the main grid, the grid betwixt main-start and main-end to be a maximum of 1008px as required.

I trawled the internet to find if it was possible to create our main requirement, a 14 column grid which also allows for full-width components. I found that we could not reverse minmax to minmax(1fr, 72px) as 1fr is not allowed as a minimum if there is a maximum. I tried working out if we could make the min larger than its max but in minmax it would be ignored.

I was struggling, I was hoping for a cleaner version of the grid system we currently use but getting to the point where needing that extra <div> would be a necessity.

At 3 in the morning, when I was failing to get to sleep, my mind happened upon an question: “Could you use calc?”

At some point I drifted back to sleep so the next day I set upon seeing if this was possible. I knew that the maximum width of the central grid needed to be 1008px. The left and right columns needed to be however many pixels were left in the viewport divided by 2. In CSS it looked like I would need to use calc twice. The first time to takeaway 1008px from 100% of the viewport width and the second to divide that result by 2.

calc(calc(100% - 1008px) / 2)

The CSS above was part of the value that I would need to include in the declaration for the grid.

.container {
  display: grid;
  grid-gap: .75em;
  grid-template-columns:
    [full-start]
      minmax(calc(calc(100% - 1008px) / 2), 1fr)
        [main-start]
          repeat(14, [col-start] 1fr)
        [main-end]
      minmax(calc(calc(100% - 1008px) / 2), 1fr)
    [full-end];
}

We have created the grid required. A full-width grid, with a central 14 column grid, using fewer <div> elements.

See the Pen Design Systems and CSS Grid, 6 by Stuart Robson (@sturobson) on CodePen.

Success!

Progressive enhancement

Now that we have created the grid system required we need to back-track a little.

Not all browsers support Grid, over the last 9 months or so this has gotten a lot better. However there will still be browsers that visit that potentially won’t have support. The effort required to make the grid system fall back for these browsers depends on your product or sites browser support.

To determine if we will be using Grid or not for a browser we will make use of feature queries. This would mean that any version of Internet Explorer will not get Grid, as well as some mobile browsers and older versions of other browsers.

@supports (display: grid) {
 /* Styles for browsers that support Grid */
}

If a browser does not pass the requirements for @supports we will fallback to using flexbox where possible, and if that is not supported we are happy for the page to be laid out in one column.

A website doesn’t have to look the same in every browser after all.

A responsive grid

We started with the big picture, how the grid would be at a large viewport and the grid system we have created gets a little silly when the viewport gets smaller.

At smaller viewports we have a single column layout where every item of content, every component stacks atop each other. We don’t start to define a grid before we the viewport gets to 700px wide. At this point we have an 8 column grid and if the viewport gets to 1100px or wider we have our 14 column grid.

/*
 * to start with there is no 'grid' just a single column
 */
.container {
  padding: 0 .75em;
}

/*
 * when we get to 700px we create an 8 column grid with
 * a left and right area to breakout of the grid.
 */
@media (min-width: 700px) {
  .container {
    display: grid;
    grid-gap: .75em;
    grid-template-columns:
      [full-start]
        minmax(calc(calc(100% - 1008px) / 2), 1fr)
          [main-start]
            repeat(8, [col-start] 1fr)
          [main-end]
        minmax(calc(calc(100% - 1008px) / 2), 1fr)
      [full-end];
    padding: 0;
  }
}

/*
 * when we get to 1100px we create an 14 column grid with
 * a left and right area to breakout of the grid.
 */
@media (min-width: 1100px) {
  .container {
    grid-template-columns:
    [full-start]
      minmax(calc(calc(100% - 1008px) / 2), 1fr)
        [main-start]
          repeat(14, [col-start] 1fr)
        [main-end]
      minmax(calc(calc(100% - 1008px) / 2), 1fr)
    [full-end];
  }
}

Being explicit in creating this there is some repetition that we could avoid, we will define the number of columns for the inner grid by using a Sass variable or CSS custom properties (more commonly termed as CSS variables).

Let’s use CSS custom properties. We need to declare the variable first by adding it to our stylesheet.

:root {
  --inner-grid-columns: 8;
}

We then need to edit a few more lines. First make use of the variable for this line.

repeat(8, [col-start] 1fr)
/* replace with */
repeat(var(--inner-grid-columns), [col-start] 1fr)

Then at the 1100px breakpoint we would only need to change the value of the —inner-grid-columns value.

@media (min-width: 1100px) {
  .container {
    grid-template-columns:
    [full-start]
      minmax(calc(calc(100% - 1008px) / 2), 1fr)
        [main-start]
          repeat(14, [col-start] 1fr)
        [main-end]
      minmax(calc(calc(100% - 1008px) / 2), 1fr)
    [full-end];
  }
}
/* replace with */
@media (min-width: 1100px) {
  .container {
    --inner-grid-columns: 14;
  }
}

See the Pen Design Systems and CSS Grid, 8 by Stuart Robson (@sturobson) on CodePen.

The final grid system

We have finally created our new grid for the design system. It stays true to the existing grid in place, adds the ability to break-out of the grid, removes a <div> that could have been needed for the nested 14 column grid.

We can move on to the new component.

Creating a new component

Back to the new components we are needing to create.

To me there are two components one of which is a slight variant of the first. This component contains a title, subtitle, a paragraph (potentially paragraphs) of content, a list, and a call to action.

To start with we should write the HTML for the component, something like this:

<article>
  <h3></h3>
  <p></p>
  <div>
    <p></p>
  </div>
  <ul>
    <li></li>
    <li></li>
  </ul>
  <a href=""></a>
</article>

To place the component on the existing grid is fine, but as child elements are not affected by the container grid we need to define another grid for the features component.

As the grid doesn’t get invoked until 700px it is possible to negate the need for a media query.

.features {
  grid-column: col-start 1 / span 6;
}

@supports (display: grid) {
  @media (min-width: 1100px) {
    .features {
      grid-column-end: 9;
    }
  }
}

We can also avoid duplication of declarations by making use of the grid-column shorthand and longhand. We need to write a little more CSS for the variant component, the one that will sit on the right side of the page too.

.features:nth-of-type(even) {
  grid-column-start: 4;
  grid-row: 2;
}

@supports (display: grid) {
  @media (min-width: 1100px) {
    .features:nth-of-type(even) {
      grid-column-start: 9;
      grid-column-end: 16;
    }
  }
}

We cannot place the items within features on the container grid as they are not direct children. To make this work we have to define a grid for the features component.

We can do this by defining the grid at the first breakpoint of 700px making use of CSS custom properties again to define how many columns there will need to be.

.features {
  grid-column: col-start 1 / span 6;
  --features-grid-columns: 5;
}

@supports (display: grid) {
  @media (min-width: 700px) {
    .features {
      display: grid;
    grid-gap: .75em;
      grid-template-columns: repeat(var(--features-grid-columns), [col-start] 1fr);
    }
  }
}

@supports (display: grid) {
  @media (min-width: 1100px) {
    .features {
      grid-column-end: 9;
      --features-grid-columns: 7;
    }
  }
}

See the Pen Design Systems and CSS Grid, 10 by Stuart Robson (@sturobson) on CodePen.

Laying out the parts

Looking at the spec and reading several articles I feel there are two ways that I could layout the text of this component on the grid.

We could use the grid-column shorthand that incorporates grid-column-start and grid-column-end or we can make use of grid-template-areas.

grid-template-areas allow for a nice visual way of representing how the parts of the component would be laid out. We can take the the mock of the features on the grid and represent them in text in our CSS.

Within the .features rule we can add the relevant grid-template-areas value to represent the above.

.features {
  display: grid;
  grid-template-columns: repeat(var(--features-grid-columns), [col-start] 1fr);
  grid-template-areas:
   ". title     title     title     title     title    title"
   ". subtitle  subtitle  subtitle  subtitle  subtitle .    "
   ". content   content   content   content   .        .    "
   ". list      list      list      .         .        .    "
   ". .         .         .         link      link     link ";
}

In order to make the variant of the component we would have to create the grid-template-areas for that component too.

We then need to tell each element of the component in what grid-area it should be placed within the grid.

.features__title { grid-area: title; }
.features__subtitle { grid-area: subtitle; }
.features__content { grid-area: content; }
.features__list { grid-area: list; }
.features__link { grid-area: link; }

See the Pen Design Systems and CSS Grid, 12 by Stuart Robson (@sturobson) on CodePen.

The other way would be to use the grid-column shorthand and the grid-column-start and grid-column-end we have used previously.

.features .features__title {
  grid-column: col-start 2 / span 6;
}
.features .features__subtitle {
  grid-column: col-start 2 / span 5;
}
.features .features__content {
  grid-column: col-start 2 / span 4;
}
.features .features__list {
  grid-column: col-start 2 / span 4;
}
.features .features__link {
  grid-column: col-start 5 / span 3;
}

For the variant of the component we can use the grid-column-start property as it will inherit the span defined in the grid-column shorthand.

.features:nth-of-type(even) .features__title {
  grid-column-start: col-start 1;
}
.features:nth-of-type(even) .features__subtitle {
  grid-column-start: col-start 1;
}
.features:nth-of-type(even) .features__content {
  grid-column-start: col-start 3;
}
.features:nth-of-type(even) .features__list {
  grid-column-start: col-start 3;
}
.features:nth-of-type(even) .features__link {
  grid-column-start: col-start 1;
}

See the Pen Design Systems and CSS Grid, 14 by Stuart Robson (@sturobson) on CodePen.

I think, for now, we will go with using grid-column properties rather than grid-template-areas. The repetition needed for creating the variant feels too much where we can change the grid-column-start instead, keeping the components elements layout properties tied a little closer to the elements rather than the grid.

Some additional decisions

The current component library has existing styles for titles, subtitles, lists, paragraphs of text and calls to action. These are name-spaced so that they shouldn’t clash with any other components. Looking forward there will be a chance that other products adopt the component library, but they may bring their own styles for titles, subtitles, etc.

One way that we could write our code now for that near future possibility is to make sure our classes are working hard. Using class-attribute selectors we can target part of the class attributes that we know the elements in the component will have using *=.

.features [class*="title"]  {
  grid-column: col-start 2 / span 6;
}
.features [class*="subtitle"] {
  grid-column: col-start 2 / span 5;
}
.features [class*="content"] {
  grid-column: col-start 2 / span 4;
}
.features [class*="list"] {
  grid-column: col-start 2 / span 4;
}
.features [class*="link"]  {
  grid-column: col-start 5 / span 3;
}

See the Pen Design Systems and CSS Grid, 15 by Stuart Robson (@sturobson) on CodePen.

Although the component we have created have a title, subtitle, paragraphs, a list, and a call to action there may be a time where one ore more of these is not required or available. One thing I found out is that if the element doesn’t exist then grid will not create space for it. This may be obvious, but it can be really helpful in making a nice malleable component.

We have only looked at columns, as existing components have their own spacing for the vertical rhythm of the page we don’t really want to have them take up equal space in the component and just take up the space as needed. We can do this by adding grid-auto-rows: min-content; to our .features. This is useful if you also need your component to take up a height that is more than the component itself.

The grid of the future

From prototyping this new grid and components in CSS Grid, I’ve found it a fantastic way to reimagine how we can create a layout or grid system for our sites. It gives us options to create the same layouts in differing ways that could suit a project and its needs.

It allows us to carry on – if we choose to – using a <div>-based grid but swapping out floats for CSS Grid or to tie it to our components so they have specific places to go depending on what component is being used. Or we could have several ‘grid components’ in our design system that we could use to layout various components throughout a page.

If you find yourself tasked with creating some new components for your design system try it. If you are starting from scratch I believe you really should start with CSS Grid for your layout.

It really feels like the possibilities are endless in terms of layout for the web.

Resources

Here are just a few resources I have pawed over these last few weeks whilst getting acquainted with CSS Grid.


About the author

Stuart Robson is a freelance front-end developer and design systems advocate who curates the design systems newsletter - news.design.systems

More articles by Stuart

Thomas Legrand

Posted by cssdsgn - 3 days ago

Bibliothèque

Posted by Site Inspire - 3 days ago