Month: July 2019

A More Accessible Portals Demo

The point of the <portal> element (behind a flag in Chrome Canary) is that you can preload another whole page (like <iframe>), but then have APIs to animate it to the current page. So “Single Page App”-like functionality (SPA), but natively. I think that’s pretty cool. I’m a fan of JavaScript frameworks in general, when they are providing value by helping do things that are otherwise difficult, like fancy state management, efficient re-rendering, and component composition. But if the framework is being reached for just for SPA qualities, that’s unfortunate. The web platform is at its best when it seems what people are doing are in step with native, standardized solutions.

But it’s not the web platform at its best when things are done inaccessibly. Steve Faulkner wrote “Short note on the portal element” where he points out seven issues with the portal element as it exists now. Here’s a demo of it with some of those issues addressed. I guess it’s somewhat of an implementation issue if a lot can be fixed from the outside, but I imagine much of it cannot (e.g. back button behavior, whether the loaded pages becomes part of the accessibility tree, etc.).

Here’s a video of the basic behavior:

Direct Link to ArticlePermalink

The post A More Accessible Portals Demo appeared first on CSS-Tricks.

CSS-Tricks

, , ,

Bringing CSS Grid to WordPress Layouts

December 6th, 2018 was a special date for WordPress: it marked the release of version 5.0 of the software that, to this day, powers more than one-third of the web. In the past, people working on the platform pointed out that there has never been any special meaning to version numbers used in WordPress releases; as such, WordPress 5.0 was simply the follower to WordPress 4.9. Yet, 5.0 brought possibly the biggest innovation since Custom Post Types were introduced in version 3.0 – that’s almost a decade, folks.

The Block Editor — codename “Gutenberg” — is now the new default writing tool in WordPress. Before its adoption in Core, our beloved CMS has relied on what we now call the Classic Editor. And, by the way, the Classic Editor isn’t really gone: you can bring it back by installing a plugin that restores the default editing experience you’ve known all these years.

So, why was the Classic Editor replaced? Essentially because it embodied an old concept of writing, a concept that was conceived when the only need of a text editor was to visually compose HTML code.

Not to create layouts. Not to embed dynamic content form heterogeneous sources. Not to offer a representation of what your post or page would look like when you pressed that “Publish” button, and go live with your piece of content.

In short, the Classic Editor delivered a very basic writing experience and, frankly, it always fell short at creating anything more than flowing text.

The Block Editor is based on the idea of content “blocks” in the sense that everything we can add to a page — a text paragraph, an image, an embed — is technically a block, that is, an atomic entity that’s defined by a certain series of properties. The combination of these properties determines the state of that particular block. Combine several blocks one after the other, and you’ll get the content of your page.

In this transition from unorganized text to rigorous content structure lies the biggest change introduced by the Block Editor.

Layouts pre-Block Editor

Before all of this bursted into existence, people who wanted to create a layout within WordPress had to choose between either of these options:

  1. Create a custom template from scratch, getting their hands dirty with code – a noble intent, yet not so appealing to the masses.
  2. Use a tool, better if a visual one, that helped them composing a page structure without having much code knowledge.

That’s how page builders were born: page builders are plugins that provide a visual way to compose a layout, ideally without touching a single line of code, and they were created out of necessity to fill a gap between visual mockups and the actual, finished website. Elementor and Beaver Builder are two popular builders that come to mind.

Page builders have always suffered from a bad reputation, for a variety of reasons:

  1. They tend to be slow and bulky.
  2. Some offer poor editing experiences.
  3. They end up locking users into a framework or ecosystem that’s tough to replace.

The first point is as obvious as it is unavoidable: if you’re a page builder author (and, hopefully, aspire to sell copies of your product), you have to make it as appealing as possible; physiologically, builders started to slowly become big code soups with everything in them, at the detriment of performance.

The second point may be subjective, at least to to some extent. The third point, however, is a fact. Sure, one could be perfectly fine using the same tool for every project, perfecting knowledge of the instrument as time goes by, but the more you stick to it, the harder it gets to potentially stop using it one day.

The Block Editor aims to surpass this deadlock: from the user’s point of view, it aims at offering a better, richer writing experience, while, from the developer’s perspective, providing a unified, shared API from which to build upon.

A brief history of CSS layouts

If you’re old enough, you’ll probably know the story already. If not, it might be fun for you to hear what life was like for a front-end developer back in the day.

The first version of the CSS specification dates back to 1996, and it allowed an embedded stylesheet to add font styling, pick colors for elements, change the alignments and spacing of objects in the page. The problem was that, in those days, the concept of semantic HTML wasn’t exactly widespread. In other words, there was no clear separation between content and form. The markup we’d write and the appearance we want were completely intertwined in the same document.

This led to HTML elements to be used more for presentation purposes, than conveying meaning to their presence in the page. For example, on the layout side of things, this also led to to table elements being used to create layouts instead of actual tabular data. To achieve even more complex layouts, tables began being nested into other tables, making the page become a nightmare from the semantic point of view, its size grow and grow, and resulting very hard to maintain over time. If you’ve ever coded an HTML email, then you have a good idea of what life was like. And, really, this still sort of happens in websites today, even if it’s for smaller elements rather than complete page layouts.

Then the Web Standards movement came along with the goal to raise awareness among developers that we could be doing things differently and better; that style and content should be separated, that we need to use HTML elements for their meaning, and reinforcing the concept that a lighter page (in terms of code weight) is a fundamentally better option than an unmanageable ocean of nested tables.

We then began (over)using div elements, and juxtaposed them using the float property. The presentation focus was shifted from the markup to the stylesheet. Floats became the most reliable layout tool available for years, yet they can be a bit problematic to handle, since they have to be cleared in order for the page to return to its standard flow. Also, in this age, page markups were still too redundant, even though using divs instead of tables helped make our content more accessible.

The turnaround moment came in 2012, with the publication of the Flexbox specification. Flexbox allowed developers to solve a whole series of long standing little layout problems, complete with an elegant syntax that requires a lot less markup to be implemented. Suddenly (well, not that suddenly, we still have to care about browser support, right?), reliably centering things on both axises wasn’t an issue anymore. It was refreshing. Finally, tweaking a layout could be reduced to altering just one property in our stylesheet.

As important as Flexbox is to this day, it is not the end of the story.

It’s 2019! Let’s use CSS Grid.

If you’ve come this far reading this piece, we think it’s safe to assume that two things are for sure:

  1. That we clearly aren’t in this industry to live peaceful, quiet professional lives.
  2. The things we use are going to change.

In 2017, the CSS Grid Layout Module specification was officially published, but, as it always happens with CSS specs, its draft and interim implementations had already been around for some time.

CSS Grid is a bold leap into what CSS can and should do. What if we stopped micromanaging our pages styles, and started thinking more holistically? What if we had a system to reliably position elements on the screen that doesn’t depend at all on the markup being used, nor the order of elements, and that is, at the same time, programmatically applicable on smaller screens?

No, this isn’t just a thought. This is more of a dream; one of those good ones you don’t want to wake up from. Except that, in 2019, this has become a reality.

The main difference between Grid and Flexbox is more nuanced, of course, but basically comes down to Grid operating in two dimensions, while Flexbox is limited to one. Knowing what elements are going to be placed within the limits of a container, we can choose exactly where those elements are going to end up, entirely from directives written in the stylesheet.

Do we want to tweak the layout down the road? Fine, that modification won’t affect the markup.

The basic idea behind Grid is that elements are laid out in, well, a grid. By definition, a grid is composed by a certain amount of columns and rows, and the boundaries between columns and rows form a series of cells that can be filled with content.

The savings of this approach in terms of quantity of code being used to achieve the desired result are extraordinary: we just need to identify a container element, apply the display: grid rule to it, and then pick elements within that container and tell CSS what column/row they begin/end in.

.my-container {   display: grid;   grid-template-columns: repeat( 3, 1fr );   grid-template-rows: repeat( 2, 1fr ); }  .element-1 {   grid-column-start: 2;   grid-column-end: 4;   grid-row-start: 1;   grid-row-end: 3; }

The above example creates a 3×2 grid associated to the .my-container element; .element-1 is a 2×2 block that is inscribed in the grid, with its upper left vortex being positioned in the second column of the first row of the grid.

Sounds pretty neat, right?

The even neater thing about CSS Grid is the fact that you can create template areas, give those areas meaningful names (e.g. “header” or “main”), and then use those identifiers to programmatically position elements in those areas.

.item-a {   grid-area: header; } .item-b {   grid-area: main; } .item-c {   grid-area: sidebar; } .item-d {   grid-area: footer; }  .container {   display: grid;   grid-template-columns: 50px 50px 50px 50px;   grid-template-rows: auto;   grid-template-areas:      "header header header header"     "main main . sidebar"     "footer footer footer footer"; }

For those who have begun working in this business in the tables era, the code above is nothing short of science fiction.

More good news, anyway: support for CSS Grid is pretty great, today.

Using CSS Grid in WordPress

So, this is great, and knowing that we can do so many more things today than we could compared to a few years ago probably makes you want to give Grid a try, at last.

If you are working on a WordPress project, you’re back facing the two options mentioned above: do we start from scratch and manually coding a template, or is there something that can give us a little help? Luckily, there is a plugin that might interest you, one that we have created with a dual goal in mind:

  1. Create a bridge between the Block Editor and CSS Grid.
  2. Create a plugin that could perhaps make people move past the initial skepticism of adopting the Block Editor.

It’s called Grids, and it’s a free download on the WordPress plugins repository.

Grids only takes care of the layout structure. It puts a 12×6 grid at your disposal (called Section), over which you can drag and draw the elements (Areas) that are going to be contained in that Section.

The system allows you to manually specify dimensions, backgrounds, responsive behavior, all using visual controls in the Block Editor, but by design, it doesn’t provide any content block. Sure, one could see this approach as a weak point, but we think it’s actually Grids’ biggest strength because it enables the plugin to integrate with the myriad content blocks that other developers all around the world are creating. More so, in a way Grids helps bringing those blocks, and WordPress as a platform, in touch with CSS Grid itself.

Yet, even if the plugin doesn’t strictly produce content, it’s inevitable to put it in the same phrase with successful page builders, in fact comparing its functionality to that offered by those. If you care about concepts like separation of form and content, page weight, ease of maintenance, Grids offers a cleaner solution to the problem of creating visually appealing layouts in WordPress.

The generated markup is minimal. In its most basic form, a Section (that is, the element with the display: grid property) is only composed by its own element — of course, an internal wrapper (that couldn’t be avoided and that’s used for spacing purposes), and then one element per Area belonging to the Section. This is a huge step forward in terms of avoiding using unnecessary markup.

For those of you who haven’t been afraid of getting your hands dirty with the development of blocks for the Block Editor, the rendering of the block is done server-side, which allows for custom classes to be added to Section and Area elements using filters.

This choice also directly determines what happens in the eventuality that you disable Grids in your install.
​​
​​If you don’t re-save your page again, what’s left of Grids on the front end is actually exclusively the content you put inside the content Areas. Not any extra markup elements, not any weird-looking shortcode.
​​
​​On the back-end side of things, the Block Editor has a system in place that warns you if you’re editing a page that is supposed to use a particular block type, but that block type isn’t currently available: in that case, you could easily turn Grids back on temporarily, move your content in another place, and then get rid of the Section altogether.

CSS generated to create the grid is also dynamically added to the page, as an inline style in the <head> portion of the document. We haven’t been exactly fans of styles written in the page directly, because ideally we’d like to delegate all of the styling to files that we could put under version control, yet this is a case where we found that approach to be very convenient.

Another viable option would have been to identify all the possible combinations of column/row starting/ending points, and programmatically map those with classes that could then be used to actually position elements within the grid. On a 12×6 grid, that would have lead to having a grand total of 36 class selectors, looking like this:

.grids-cs-1 {   grid-column-start: 1; }  .grids-ce-2 {   grid-column-end: 2; }

What if we decide to offer more control over how a grid is composed and, say, give users access to options that determine how many columns or rows form the grid structure?

We’d have to manually map the classes that we don’t yet have in the stylesheet (and release an update to the plugin just for that), or, again, generate them inline, and then add those classes to the grid elements.

While perfectly fine, this approach kind of goes against the idea of having a leaner, more scannable markup, so we’ve decided not to follow this route, and pay the price of having style dynamically put in the head of the document, knowing that it could be easily cached.

Because of the experimental nature of the plugin, the backend UI that’s being used to actually compose the grid is created with CSS Grid, and a set of CSS variables through which we control the properties of content Areas. Using variables has immensely sped up our work behind the grid creator prototype — had we chosen a different path there, things wouldn’t just be much longer in terms of development times, but also more complex and less clear to maintain down the road.

Feedback wanted!

To further foster the adoption of CSS Grid, we need tools that automate the process of creating layouts with it.

While we have been seeing great examples of this technology out in the wild, it would be short-sighted to assume that every website that is published today has a team of front-end devs behind it, that can take care of the issue.

We need tools that produce good markup, that don’t hinder the maintenance of the website stylesheets, and, most importantly in the WordPress world, that can be easily integrated with the existing themes that people love to use.

We think Grids is a step forward in that direction, as it’s a tool that is built upon two standards — the Block Editor API, and CSS Grid — and, as such, suffers less risk of reinventing the proverbial wheel.

While we’ve been recording general interest in the plugin at the recent WordCamp Europe in Berlin – with Matt Mullenweg himself displaying a brief demo of the plugin during his keynote — we know that it still needs a lot of feedback that can only be obtained with real-life scenarios. So, if you want to take Grids for a spin, please use it, test it and, why not, suggest new features.

The post Bringing CSS Grid to WordPress Layouts appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Intrinsically Responsive CSS Grid with minmax() and min()

The most famous line of code to have come out of CSS grid so far is:

grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));

Without any media queries, that will set up a grid container that has a flexible number of columns. The columns will stretch a little, until there is enough room for another one, and then a new column is added, and in reverse.

The only weakness here is that first value in minmax() (the 10rem value above). If the container is narrower than whatever that minimum is, elements in that single column will overflow. Evan Minto shows us the solution with min():

grid-template-columns: repeat(auto-fill, minmax(min(10rem, 100%), 1fr));

The browser support isn’t widespread yet, but Evan demonstrates some progressive enhancement techniques to take advantage of now.

Direct Link to ArticlePermalink

The post Intrinsically Responsive CSS Grid with minmax() and min() appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Brisk Graphics’ Design and Illustration Work

[Top]

How much specificity do @rules have, like @keyframes and @media?

I got this question the other day. My first thought is: weird question! Specificity is about selectors, and at-rules are not selectors, so… irrelevant?

To prove that, we can use the same selector inside and outside of an at-rule and see if it seems to affect specificity.

body {   background: red; } @media (min-width: 1px) {   body {     background: black;   } }

The background is black. But… is that because the media query increases the specificity? Let’s switch them around.

@media (min-width: 1px) {   body {     background: black;   } } body {   background: red; }

The background is red, so nope. The red background wins here just because it is later in the stylesheet. The media query does not affect specificity.

If it feels like selectors are increasing specificity and overriding other styles with the same selector, it’s likely just because it comes later in the stylesheet.

Still, the @keyframes in the original question got me thinking. Keyframes, of course, can influence styles. Not specificity, but it can feel like specificity if the styles end up overridden.

See this tiny example:

@keyframes winner {   100% { background: green; } } body {   background: red !important;   animation: winner forwards; }

You’d think the background would be red, especially with the !important rule there. (By the way, !important doesn’t affect specificity; it’s a per-rule thing.) It is red in Firefox, but it’s green in Chrome. So that’s a funky thing to watch out for. (It’s been a bug since at least 2014 according to Estelle Weyl.)

The post How much specificity do @rules have, like @keyframes and @media? appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,
[Top]

Run useEffect Only Once

React has a built-in hook called useEffect. Hooks are used in function components. The Class component comparison to useEffect are the methods componentDidMount, componentDidUpdate, and componentWillUnmount.

useEffect will run when the component renders, which might be more times than you think. I feel like I’ve had this come up a dozen times in the past few weeks, so it seems worthy of a quick blog post.

import React, { useEffect } from 'react';  function App() {   useEffect(() => {     // Run! Like go get some data from an API.   });    return (     <div>       {/* Do something with data. */}     </div>   ); }

In a totally isolated example like that, it’s likely the useEffect will run only once. But in a more complex app with props flying around and such, it’s certainly not guaranteed. The problem with that is that if you’re doing something like fetching data from an API, you might end up double-fetching which is inefficient and unnecessary.

The trick is that useEffect takes a second parameter.

The second param is an array of variables that the component will check to make sure changed before re-rendering. You could put whatever bits of props and state you want in here to check against.

Or, put nothing:

import React, { useEffect } from 'react';  function App() {   useEffect(() => {     // Run! Like go get some data from an API.   }, []);    return (     <div>       {/* Do something with data. */}     </div>   ); }

That will ensure the useEffect only runs once.

Note from the docs:

If you use this optimization, make sure the array includes all values from the component scope (such as props and state) that change over time and that are used by the effect. Otherwise, your code will reference stale values from previous renders.

The post Run useEffect Only Once appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

The Simplest Way to Load CSS Asynchronously

Scott Jehl:

One of the most impactful things we can do to improve page performance and resilience is to load CSS in a way that does not delay page rendering. That’s because by default, browsers will load external CSS synchronously—halting all page rendering while the CSS is downloaded and parsed—both of which incur potential delays.

<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">

Don’t just up and do this to all your stylesheets though, otherwise, you’ll get a pretty nasty “Flash of Unstyled Content” (FOUC) as the page loads. You need to pair the technique with a way to ship critical CSS. Do that though, and like Scott’s opening sentence said, it’s quite impactful.

Interesting side story… on our Pen Editor page over at CodePen, we had a FOUC problem:

What makes it weird is that we load our CSS in <link> tags in the <head> completely normally, which should block-rendering and prevent FOUC. But there is some hard-to-reproduce bug at work. Fortunately we found a weird solution, so now we have an empty <script> tag in the <head> that somehow solves it.

Direct Link to ArticlePermalink

The post The Simplest Way to Load CSS Asynchronously appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Creating Dynamic Routes in a Nuxt Application

In this post, we’ll be using an ecommerce store demo I built and deployed to Netlify to show how we can make dynamic routes for incoming data. It’s a fairly common use-case: you get data from an API, and you either don’t know exactly what that data might be, there’s a lot of it, or it might change. Luckily for us, Nuxt makes the process of creating dynamic routing very seamless.

In the last post, we showed how to set up stripe payments with Netlify Functions, which allow us to create serverless lambda functions with ease. We’ll use this same application to show another Nuxt-specific functionality as well.

Let’s get started!

Creating the page

In this case, we’ve got some dummy data for the store that I created in mockaroo and am storing in the static folder. Typically you’ll use fetch or axios and an action in the Vuex store to gather that data. Either way, we store the data with Vuex in store/index.js, along with the UI state, and an empty array for the cart.

import data from '~/static/storedata.json'  export const state = () => ({  cartUIStatus: 'idle',  storedata: data,  cart: [] })

It’s important to mention that in Nuxt, all we have to do to set up routing in the application is create a .vue file in the pages directory. So we have an index.vue page for our homepage, a cart.vue page for our cart, and so on. Nuxt automagically generates all the routing for these pages for us.

In order to create dynamic routing, we will make a directory to house those pages. In this case, I made a directory called /products, since that’s what the routes will be, a view of each individual product details.

In that directory, I’ll create a page with an underscore, and the unique indicator I want to use per page to create the routes. If we look at the data I have in my cart, it looks like this:

[  {    "id": "9d436e98-1dc9-4f21-9587-76d4c0255e33",    "color": "Goldenrod",    "description": "Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.",    "gender": "Male",    "name": "Desi Ada",    "review": "productize virtual markets",    "starrating": 3,    "price": 50.40,    "img": "1.jpg"  },   … ]

You can see that the ID for each entry is unique, so that’s a good candidate for something to use, we’ll call the page:

_id.vue

Now, we can store the id of the particular page in our data by using the route params:

data() {  return {    id: this.$  route.params.id,   } },

For the entry from above, our data if we looked in devtools would be:

id: "9d436e98-1dc9-4f21-9587-76d4c0255e33"

We can now use this to retrieve all of the other information for this entry from the store. I’ll use mapState:

import { mapState } from "vuex";  computed: {  ...mapState(["storedata"]),  product() {    return this.storedata.find(el => el.id === this.id);  } },

And we’re filtering the storedata to find the entry with our unique ID!

Let the Nuxt config know

If we were building an app using yarn build, we’d be done, but we’re using Nuxt to create a static site. When we use Nuxt to create a static site, we’ll use the yarn generate command. We have to let Nuxt know about the dynamic files with the generate command in nuxt.config.js.

This command will expect a function that will return a promise that resolves in an array that will look like this:

export default {   generate: {     routes: [       '/product/1',       '/product/2',       '/product/3'     ]   } }

To create this, at the top of the file we’ll bring in the data from the static directory, and create the function:

import data from './static/storedata.json' let dynamicRoutes = () => {  return new Promise(resolve => {    resolve(data.map(el => `product/$  {el.id}`))  }) }

We’ll then call the function within our config:

generate: {   routes: dynamicRoutes },

If you’re gathering your data from an API with axios instead (which is more common), it would look more like this:

import axios from 'axios' let dynamicRoutes = () => {  return axios.get('https://your-api-here/products').then(res => {    return res.data.map(product => `/product/$  {product.id}`)  }) }

And with that, we’re completely done with the dynamic routing! If you shut down and restart the server, you’ll see the dynamic routes per product in action!

For the last bit of this post, we’ll keep going, showing how the rest of the page was made and how we’re adding items to our cart, since that might be something you want to learn, too.

Populate the page

Now we can populate the page with whatever information we want to show, with whatever formatting we would like, as we have access to it all with the product computed property:

<main>  <section class="img">    <img :src="`/products/$  {product.img}`" />  </section>  <section class="product-info">    <h1>{{ product.name }}</h1>    <h4 class="price">{{ product.price | dollar }}</h4>    <p>{{ product.description }}</p>  </section>  ... </main>

In our case, we’ll also want to add items to the cart that’s in the store. We’ll add the ability to add and remove items (while not letting the decrease count dip below zero

<p class="quantity">  <button class="update-num" @click="quantity > 0 ? quantity-- : quantity = 0">-</button>  <input type="number" v-model="quantity" />  <button class="update-num" @click="quantity++">+</button> </p> ... <button class="button purchase" @click="cartAdd">Add to Cart</button>

In our methods on that component, we’ll add the item plus a new field, the quantity, to an array that we’ll pass as the payload to mutation in the store.

methods: {  cartAdd() {    let item = this.product;    item.quantity = this.quantity;    this.tempcart.push(item);    this.$  store.commit("addToCart", item);  } }

In the Vuex store, we’ll check if the item already exists. If it does, we’ll just increase the quantity. If not, we’ll add the whole item with quantity to the cart array.

addToCart: (state, payload) => {  let itemfound = false  state.cart.forEach(el => {    if (el.id === payload.id) {      el.quantity += payload.quantity      itemfound = true    }  })  if (!itemfound) state.cart.push(payload) }

We can now use a getter in the store to calculate the total, which is what we’ll eventually pass to our Stripe serverless function (the other post picks up from here). We’ll use a reduce for this as reduce is very good at retrieving one value from many. (I wrote up more details on how reduce works here).

cartTotal: state => {  if (!state.cart.length) return 0  return state.cart.reduce((ac, next) => ac + next.quantity * next.price, 0) }

And there you have it! We’ve set up individual product pages, and Nuxt generates all of our individual routes for us at build time. You’d be Nuxt not to try it yourself. 😬

The post Creating Dynamic Routes in a Nuxt Application appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Lessons Learned from a Year of Testing the Web Platform

Mike Pennisi:

The web-platform-tests project is a massive suite of tests (over one million in total) which verify that software (mostly web browsers) correctly implement web technologies. It’s as important as it is ambitious: the health of the web depends on a plurality of interoperable implementations.

Although Bocoup has been contributing to the web-platform-tests, or “WPT,” for many years, it wasn’t until late in 2017 that we began collecting test results from web browsers and publishing them to wpt.fyi

Talk about doing God’s work.

The rest of the article is about the incredible pain of scaling a test suite that big. Ultimately Azure Pipelines was helpful.

Direct Link to ArticlePermalink

The post Lessons Learned from a Year of Testing the Web Platform appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,
[Top]

The Guardian digital design system

Here’s a fascinating look at The Guardian’s design system with a step-by-step breakdown of what’s gone into it and what options are available to designers and developers. It shows us how the team treats colors, typography, layouts, and visual cues like rules and borders.

I’ve been struggling to think about how to describe design systems internally to folks and this is giving me a ton of inspiration right now. I like that this website has all the benefits of a video (great tone and lovely visuals) with all the benefits of a UI kit (by showing what options are available to folks).

This also loosely ties back into something Chris has been discussing lately, which is being mindful of knowing who a design system is for. Some are meant for internal use and others, some are meant for internal use but are openly available for people like contractors, and others are meant for varying degrees of external use. Here, The Guadian is not explicit about who their design system is for, but the description of it gives a pretty good hint:

A guide to digital design at the Guardian

So please, enjoy looking at this well-documented, highly interactive and gorgeous design system. At the same time, remember it’s made for a specific use case and may not line up with all the needs of your project or organization. It sure is inspirational to look at, one way or the other!

Direct Link to ArticlePermalink

The post The Guardian digital design system appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]