Developer News

Prevent Page Scrolling When a Modal is Open

Css Tricks - Mon, 06/03/2019 - 8:11am

Please stop me if you've heard this one before. You open a modal, scroll through it, close it, and wind up somewhere else on the page than you were when you opened the modal.

That's because modals are elements on a page just like any other. It may stay in place (assuming that's what it's meant to do) but the rest of page continues to behave as normal.

See the Pen
Avoid body scrollable in safari when modal dialog shown
by Geoff Graham (@geoffgraham)
on CodePen.

Sometimes this is a non-issue, like screens that are the exact height of the viewport. Anything else, though, we're looking at Scroll City. The good news is that we can prevent that with a sprinkle of CSS (and JavaScript) trickery.

Let's start with something simple

We can make a huge dent to open-modal-page-scrolling™ by setting the height of the entire body to the full height of the viewport and hiding vertical overflow when the modal is open:

body.modal-open { height: 100vh; overflow-y: hidden; }

That's good and all, but if we've scrolled through the <body> element before opening the modal, we get a little horizontal reflow. The width of the viewport is expanded about 15 pixels more, which is exactly the with of the scroll bar.

See the Pen
Avoid body scrollable in safari when modal dialog shown
by Geoff Graham (@geoffgraham)
on CodePen.

Let's adjust the right padding of the body a bit to avoid that.

body { height: 100vh; overflow-y: hidden; padding-right: 15px; /* Avoid width reflow */ }

Note that the modal needs to be shorter than the height of the viewport to make this work. Otherwise, the scroll bar on the body will be necessary.

Great, now what about mobile?

This solution works pretty great on desktop as well as Android Mobile. That said, Safari for iOS needs a little more love because the body still scrolls when a modal is open when tapping and moving about the touchscreen.

We can set the body to a fixed position as a workaround:

body { position: fixed; }

Works now! The body will not respond when the screen is touched. However, there's still a "small" problem here. Let's say the modal trigger is lower down the page and we click to open it up. Great! But now we're automatically scrolled back up to the top of the screen, which is just as disorientating as the scrolling behavior we're trying to resolve.

See the Pen
Avoid body scrollable in safari when modal dialog shown
by Geoff Graham (@geoffgraham)
on CodePen.

Boo!

That's why we've gotta turn to JavaScript

We can use JavaScript to avoid the touch event bubble. We all know there should be a backdrop layer when a modal is open. Unfortunately, stopPropagation is a little awkward with touch in iOS. But preventDefault works well. That means we have to add event listeners in every DOM node contained in the modal — not just on the backdrop or the modal box layer. The good news is, many JavaScript libraries can do this, including good ol' jQuery.

Oh, and one more thing: What if we need scrolling inside the modal? We still have to trigger a response for a touch event, but when reaching the top or bottom of the modal, we still need to prevent bubbling. Seems very complex, so we're not totally out of the woods here.

Let's enhance the fixed body approach

This is what we were working with:

body { position: fixed; }

If we know the top of the scroll location and add it to our CSS, then the body will not scroll back to the top of the screen, so problem solved. We can use JavaScript for this by calculating the scroll top, and add that value to the body styles:

// When the modal is shown, we want a fixed body document.body.style.position = 'fixed'; document.body.style.top = `-${window.scrollY}px`; // When the modal is hidden, we want to remain at the top of the scroll position document.body.style.position = ''; document.body.style.top = '';

This works, but there's still a little leakage here after the modal is closed. Specifically, it appears that the page already loses its scroll position when the modal is open and the body set to be fixed. So we have to retrieve the location. Let's modify our JavaScript to account for that.

// When the modal is hidden... const top = document.body.style.top; document.body.style.position = ''; document.body.style.top = ''; window.scrollTo(0, parseInt(scrollY || '0') * -1);

That does it! The body no longer scrolls when a modal is open and the scroll location is maintained both when the modal is open and when it is closed. Huzzah!

See the Pen
Avoid body scrollable in safari when modal dialog shown
by Geoff Graham (@geoffgraham)
on CodePen.

The post Prevent Page Scrolling When a Modal is Open appeared first on CSS-Tricks.

Material Theming: Making Material Your Own!

Css Tricks - Mon, 06/03/2019 - 4:15am

The web is a beautiful, expressive medium that’s evolved over time as trends and technology have changed. Moments of delight and flair are what set companies apart from one another. At the same time, today’s top products rely on scalable, component-based design systems to efficiently develop a coherent brand. And it’s more important than ever to have accessibility and a solid user experience baked in from the start! But these two worlds — creative web design and systematic web design — don’t need to be at arms. The beautiful gooey center of the web design world is where we can find a way to meld creative web design in with our systems, and luckily, you can have both!

One of those design systems is called Material Design (the team I just joined at Google!). Material is built on years of research and best practices to give designers and developers access to creating beautiful, accessible UIs with the least amount of work possible. But in its initial launch, one thing was missing from the equation: the ability to express a brand’s personality in an easy-to-implement way. The team heard two key pieces of feedback:

  1. Material wasn’t stylistically flexible enough to meet the needs of all products, brands, and users.
  2. It wasn’t easy enough to apply and build brand experiences systematically across products.

And as of last year (specifically, I/O 2018), Material announced new theming capabilities! Theming allows developers and designers to benefit from all the parts of Material that make it a world-class design system — and make it their own! In other words: You can customize the look and feel of Material Components by applying global changes to your product’s color, shape, and typography.

Material Components are built for multiple systems like Android, iOS, and Flutter, and we’re going to focus on the web for this post (this is CSS-Tricks after all). Let’s start off with a base login template using Material Components for the web to see how easy implementing a theme atop this will be:


About theming

The current theming implementations allow for color, typography, and shape adjustments that trickle down to every component in your product. These three subsystems may not sound like many options, but together they bring a big impact to the design, and are a great springboard to jump off of with more design changes on a more granular level.

Color

The first themable option is color. There’s a great color picker tool on Material.io for you to be able to see contrast and aid your color selection process. Since this is CSS-Tricks, let’s write some CSS (okay, more like SCSS), to get started with an example. In a few lines of code in our my-theme.scss file, we can entirely change the look and feel of this login screen:


We’ve set:

$mdc-theme-primary: #26418f; $mdc-theme-secondary: #d1c4e9; $mdc-theme-background: #fdf6f9;

Even though we have not specified a $mdc-theme-on-primary, the system knows to make this white now (using a Sass contrast function) to help us ensure accessible color contrast. We can also override the text color on the primary and secondary themes with $mdc-theme-on-primary and $mdc-theme-on-secondary. However, if no value is explicitly set, these will either be black or white based on the background. See the color picker for more information.

Typography

Material sets up a base typography scale, which can be customized with theming. You can adjust the typography for each individual headline level and apply it throughout your product in two ways:

  1. Using CSS classes to apply the styles. I.e. <h1 class="mdc-typography--headline1">
  2. Using mixins to extend the styles from a header component onto another (i.e. h1 {@include mdc-typography(headline1);}). You can see an example of this in our starter kit example on Glitch.

A quick way to change the typeface is by using Google Fonts — a really nice directory of free web fonts. We’re going to make this easy for ourselves and pick out a Google font called Josefin Sans. In order to use this in our project, we’ll need to import it, and then can set the base typography to use it:

@import url('https://fonts.googleapis.com/css?family=Josefin+Sans'); $mdc-typography-font-family: unquote("Josefin Sans, sans-serif");

We use unquote here because the typography in Material is set in a map. We can specify more styles like so:

$mdc-typography-styles-button: ( font-size: 14px, font-weight: 600, letter-spacing: 0.05em, );

Now our login page looks like this:


Shape

Shape is another way to be expressive with your code! What do I mean by shape? In Material, shape affects the corner radius of components, such as buttons, cards, and sheets. In product design, shape helps to define your brand. Is it angular and machine-like, or is it more rounded and organic? Changing shape trickles down through the rest of the system. Here are some examples of shape in Material:

The other cool thing about shape in Material Components is that you don’t have to have the same shape on each corner, or even the same component at different sizes. There are small, medium, and large components in Material, and you can apply different styles for these different component types, and you can mix it up and specify each corner, one-by-one, in a space-separated list of values just as you would with border-radius.

MDC Web does not currently support cut corners like the other platforms do since it is a non-trivial operation with current web standards. This is another reason I personally love Houdini and see a lot of impact for it in future CSS development!

In the example we’re working with, we have both large and small components. The large components are the text field inputs, and the small component is the “login” button. We can apply different shapes to these with:

$mdc-shape-small-component-radius: 12px 4px; $mdc-shape-large-component-radius: 8px;

And voilà! We have transformed our application in 12 lines of code.

Themes, themes, everywhere!

Now here’s the part where you get creative. There are so many ways to mix and match the elements of color, typography, and shape to really make your brand stand out. Here are four very distinct example apps that use color theory, typography, and shape to differentiate their products, each based on the baseline Material Components:

Themes IRL

Google itself customizes and extends upon the baseline Material Components with its own products. This is called the Google Material Theme, and it was defined by a number of product teams, including Gmail, Google News, Google Play, and Google Home:

But they are not the only company to use Material Design and its principles. A few companies have also extended Material Components in their own large-scale products.

Lyft, a ridesharing service, is just one example. They used an extended FAB component to highlight key actions, and designed it with a gradient to give it a unique feel that users were still familiar with. Lyft also leveraged Material’s elevation system in their own product.

Anchor, a free app that helps people record, distribute, and host podcasts, is another great example of making Material your own. They showcase their bold color palette, and integrate it with choice chips to delineate display options, a list of cards for content selection, and an extended FAB anchored to the bottom to remain persistently available for user actions.

Get started

Now you have everything you need to make own Material Theme with Material Components for the web. It’s easy to start building your web project with our Material Starter Kit, and exploring theming with the Build a Material theme Glitch project we’ve just released. Change around the variables in my-theme.scss to explore how they can customize the individual components. Then, you can open any template, paste those variables into the my-theme.scss, and start building.


TL;DR: If you thought that Material Design wasn’t for you in the past, it’s a great time to start exploring. Happy theming!

The post Material Theming: Making Material Your Own! appeared first on CSS-Tricks.

Implementing Private Variables In JavaScript

Css Tricks - Fri, 05/31/2019 - 1:07pm

JavaScript (or ECMAScript) is the programming language that powers the web. Created in May 1995 by Brendan Eich, it’s found its place as a widely-used and versatile technology. Despite its success, it’s been met with its fair share of criticism, especially for idiosyncrasies. Things like objects being casted to string form when used as indices, 1 == "1" returning true, or the notoriously confusing this keyword. A particularly interesting quirk though, is the existence of various techniques for variable privacy.

In its current state, there is no "direct” way to create a private variable in JavaScript. In other languages, you can use the private keyword or double-underscores and everything works, but variable privacy in JavaScript carries characteristics that make it seem more akin to an emergent trait of the language rather than an intended functionality. Let’s introduce some background to our problem.

The "var” keyword

Before 2015, there was essentially one way to create a variable, and that was the var keyword. var is function-scoped, meaning that variables instantiated with the keyword would only be accessible to code within the function. When outside of a function, or "global” essentially, the variable will be accessible to anything executed after the definition of the variable. If you try to access the variable in the same scope before its definition, you will get undefined rather than an error. This is due to the way the var keyword "hoists."

// Define "a" in global scope var a = 123; // Define "b" in function scope (function() { console.log(b); //=> Returns "undefined" instead of an error due to hoisting. var b = 456; })(); console.log(a); // => 123 console.log(b); // Throws "ReferenceError" exception, because "b" cannot be accessed from outside the function scope. The birth of ES6 variables

In 2015, ES6/ES2015 was made official, and with it came two new variable keywords: let and const. Both were block-scoped, meaning that variables created with the keywords would be accessible from anything within the same pair of braces. Same as with var, but the let and const variables could not be accessed outside of block scope with loops, functions, if statements, braces, etc.

const a = 123; // Block scope example #1 if (true) { const b = 345; } // Block scope example #2 { const c = 678; } console.log(a); // 123 console.log(b); // Throws "ReferenceError" because "b" cannot be accessed from outside the block scope. console.log(c); // Throws "ReferenceError" because "b" cannot be accessed from outside the block scope.

Since code outside of the scope cannot access the variables, we get an emergent trait of privacy. We’re going to cover some techniques for implementing it in different ways.

Using functions

Since functions in JavaScript also are blocks, all variable keywords work with them. In addition, we can implement a very useful design pattern called the "module.”

The Module Design Pattern

Google relies on the Oxford Dictionary to define a "module":

Any of a number of distinct but interrelated units from which a program may be built up or into which a complex activity may be analyzed.

—"Module" Definition 1.2

The module design pattern is very useful in JavaScript because it combines public and private components and it allows us to break a program into smaller components, only exposing what another part of the program should be able to access through a process called "encapsulation.” Through this method, we expose only what needs to be used and can hide the rest of the implementation that doesn’t need to be seen. We can take advantage of function scope to implement this.

const CarModule = () => { let milesDriven = 0; let speed = 0; const accelerate = (amount) => { speed += amount; milesDriven += speed; } const getMilesDriven = () => milesDriven; // Using the "return" keyword, you can control what gets // exposed and what gets hidden. In this case, we expose // only the accelerate() and getMilesDriven() function. return { accelerate, getMilesDriven } }; const testCarModule = CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven());

With this, we can get the number of miles driven, as well as the amount of acceleration, but since the user doesn’t need access to the speed in this case, we can hide it by only exposing the accelerate() and getMilesDriven() method. Essentially, speed is a private variable, as it is only accessible to code inside of the same block scope. The benefit to private variables begins to become clear in this situation. When you remove the ability to access a variable, function, or any other internal component, you reduce the surface area for errors resulting from someone else mistakenly using something that wasn’t meant to be.

The alternative way

In this second example, you’ll notice the addition of the this keyword. There’s a difference between the ES6 arrow function ( => ) and the traditional function(){}. With the function keyword, you can use this, which will be bound to the function itself, whereas arrow functions don’t allow any kind of use of the this keyword. Both are equally-valid ways to create the module. The core idea is to expose parts that should be accessed and leave other parts that should not be interacted with, hence both public and private data.

function CarModule() { let milesDriven = 0; let speed = 0; // In this case, we instead use the "this" keyword, // which refers to CarModule this.accelerate = (amount) => { speed += amount; milesDriven += speed; } this.getMilesDriven = () => milesDriven; } const testCarModule = new CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven()); Enter ES6 Classes

Classes were another addition that came with ES6. Classes are essentially syntactic sugar — in other words, still a function, but potentially "sweetening” it into a form that’s easier to express. With classes, variable privacy is (as of now) close to impossible without making some major changes to the code.

Let’s take a look at an example class.

class CarModule { /* milesDriven = 0; speed = 0; */ constructor() { this.milesDriven = 0; this.speed = 0; } accelerate(amount) { this.speed += amount; this.milesDriven += this.speed; } getMilesDriven() { return this.milesDriven; } } const testCarModule = new CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven());

One of the first things that stands out is that the milesDriven and speed variable are inside of a constructor() function. Note that you can also define the variables outside of the constructor (as shown in the code comment), but they are functionally the same regardless. The problem is that these variables will be public and accessible to elements outside of the class.

Let’s look at some ways to work around that.

Using an underscore

In cases where privacy is to prevent collaborators from making some catastrophic mistake, prefixing variables with an underscore (_), despite still being "visible” to the outside, can be sufficient to signal to a developer, "Don’t touch this variable.” So, for example, we now have the following:

// This is the new constructor for the class. Note that it could // also be expressed as the following outside of constructor(). /* _milesDriven = 0; _speed = 0; */ constructor() { this._milesDriven = 0; this._speed = 0; }

While this does work for its specific use case, it’s still safe to say that it’s less than ideal on many levels. You can still access the variable but you also have to modify the variable name on top of that.

Putting everything inside the constructor

Technically, there is a method for variable privacy in a class that you can use right now, and that’s placing all variables and methods inside the constructor() function. Let’s take a look.

class CarModule { constructor() { let milesDriven = 0; let speed = 0; this.accelerate = (amount) => { speed += amount; milesDriven += speed; } this.getMilesDriven = () => milesDriven; } } const testCarModule = new CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven()); console.log(testCarModule.speed); // undefined -- We have true variable privacy now.

This method accomplishes true variable privacy in the sense that there is no way to directly access any variables that aren’t intentionally exposed. The problem is that we now have, well, code that doesn’t look all that great compared to what we had before, in addition to the fact that it defeats the benefits of the syntactic sugar we had with classes. At this point, we might as well be using the function() method.

Using WeakMap

There’s another, more creative way to go about making a private variable, and that’s using WeakMap(). Although it may sound similar to Map, the two are very different. While maps can take any type of value as a key, a WeakMap only take objects and deletes the values in the WeakMap when the object key is garbage collected. In addition, a WeakMap cannot be iterated through, meaning that you must have access to the reference to an object key in order to access a value. This makes it rather useful for creating private variables, since the variables are effectively invisible.

class CarModule { constructor() { this.data = new WeakMap(); this.data.set(this, { milesDriven: 0, speed: 0 }); } accelerate(amount) { // In this version, we instead create a WeakMap and // use the "this" keyword as a key, which is not likely // to be used accidentally as a key to the WeakMap. const data = this.data.get(this); const speed = data.speed + amount; const milesDriven = data.milesDriven + data.speed; this.data.set({ speed, milesDriven }); } this.getMilesDriven = () => this.data.get(this).milesDriven; } const testCarModule = new CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven()); console.log(testCarModule.data); //=> WeakMap { [items unknown] } -- This data cannot be accessed easily from the outside!

This solution is good at preventing an accidental usage of the data, but it isn’t truly private, since it can still be accessed from outside the scope by substituting this with CarModule. In addition, it adds a fair amount of complexity to the mix and, therefore, isn’t the most elegant solution.

Using symbols to prevent collisions

If the intent is to prevent name collisions, there is a useful solution using Symbol. These are essentially instances that can behave as unique values that will never be equal to anything else, except its own unique instance. Here’s an example of it in action:

class CarModule { constructor() { this.speedKey = Symbol("speedKey"); this.milesDrivenKey = Symbol("milesDrivenKey"); this[this.speedKey] = 0; this[this.milesDrivenKey] = 0; } accelerate(amount) { // It's virtually impossible for this data to be // accidentally accessed. By no means is it private, // but it's well out of the way of anyone who would // be implementing this module. this[this.speedKey] += amount; this[this.milesDrivenKey] += this[this.speedKey]; } getMilesDriven() { return this[this.milesDrivenKey]; } } const testCarModule = new CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven()); console.log(testCarModule.speed); // => undefined -- we would need to access the internal keys to access the variable. Like the underscore solution, this method more or less relies on naming conventions to prevent confusion. TC39 private class field proposal

Recently, a new proposal was introduced that would introduce private variables to classes. It’s rather simple: put a # before the name of a variable, and it becomes private. No extra structural changes needed.

class CarModule { #speed = 0 #milesDriven = 0 accelerate(amount) { // It's virtually impossible for this data to be // accidentally accessed. this.#speed += amount; this.#milesDriven += speed; } getMilesDriven() { return this.#milesDriven; } } const testCarModule = new CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven()); console.log(testCarModule.speed); //=> undefined -- we would need to access the internal keys to access the variable.

The private class field proposal is not standard and cannot be done without using Babel as of this writing, so you’ll have to wait a bit for it to be usable on major browsers, Node, etc.

Conclusion

That sums up the various ways you can implement private variables in JavaScript. There isn’t a single "correct” way to do it. These will work for different needs, existing codebases, and other constraints. While each has advantages and disadvantages, ultimately, all methods are equally valid as long as they effectively solve your problem.

Thanks for reading! I hope this provides some insight into how scope and variable privacy can be applied to improve your JavaScript code. This is a powerful technique and can support so many different methods and make your code more usable and bug-free. Try out some new examples for yourself and get a better feel.

The post Implementing Private Variables In JavaScript appeared first on CSS-Tricks.

Weekly Platform News: Favicon Guidelines, Accessibility Testing, Web Almanac

Css Tricks - Fri, 05/31/2019 - 4:55am

Šime posts regular content for web developers on webplatform.news.

Google posts guidelines for defining favicons

Jamie Leach: Google Search now displays favicons in search results on mobile. Your favicon should be a multiple of 48×48 (Google will re-scale it to 16×16 for use in search results). If a website doesn’t have a favicon or Google deems the favicon inappropriate, a generic globe icon will be displayed instead.

Your favicon should be a visual representation of your website’s brand, in order to help users quickly identify your site when they scan through search results.

Top websites are surprisingly inconsistent in the way they declare icons (via <link> elements in the page’s head). Twitter and Pinterest, two relatively modern progressive web apps, provide icons in two sizes.

<!-- example --> <link rel="icon" href="/icon-32x32.png"> <link rel="apple-touch-icon" href="/icon-192x192.png"> The Paciello Group releases ARC Toolkit

In honor of Global Accessibility Awareness Day, TPG is releasing our professional-level accessibility testing tool to the public. Learn all about it at https://t.co/ol33pizq2v and download it from the Google Chrome store today. #GAAD

— The Paciello Group (@paciellogroup) May 16, 2019

The Paciello Group: ARC Toolkit, our professional-level accessibility testing tool, is now available as a Chrome DevTools extension. This tool detects issues related to the WCAG 2.1 guidelines. You can run the test on the entire page or just the node selected in the DevTools Elements panel.

Remember, automated accessibility tools are only able to find some accessibility issues, and manual testing is necessary to ensure full accessibility. Lighthouse (via the Audits panel) suggests manual checks after performing an accessibility audit.

Other news
  • Jeff Jaffe: W3C and WHATWG have reached an agreement to collaborate on the development of HTML. "W3C shall encourage the community ... to contribute directly to the WHATWG HTML and DOM repositories; raising issues, proposing solutions, commenting on proposed solutions, and indicating support or otherwise for proposals."
  • Paul Calvano: "There is a significant gap in the first- vs. third-party resource age of CSS and web fonts. 95% of first-party fonts are older than one week compared to 50% of third-party fonts ... This makes a strong case for self-hosting web fonts!"
  • Rachel Andrew: The CSS subgrid value is a relatively straightforward addition to grid layout. For example, if you have nested grids, and you apply grid-template-rows: subgrid to the child grid, then this grid will use the row tracks of the parent grid instead of creating its own row tracks. That’s all there is to it. (This feature is currently only supported in Firefox Nightly.)
  • GitHub Blog: GitHub can now generate automated security fixes for your dependencies with known security vulnerabilities. On GitHub’s website, check your repository’s Security tab for security alerts. If you open an alert and press the "Create automated security fix" button, GitHub will create an automated pull request that fixes the security vulnerability.
  • Rick Viscomi: HTTP Archive plans to release the first annual Web Almanac in November, a report of the state of the web with interesting insights written by different experts. About 50 volunteers from the web community are currently working on it, and they are looking for more contributors.

The post Weekly Platform News: Favicon Guidelines, Accessibility Testing, Web Almanac appeared first on CSS-Tricks.

Reducing motion with the picture element

Css Tricks - Fri, 05/31/2019 - 4:54am

Here’s a bonafide CSS/HTML trick from Brad Frost and Dave Rupert where they use the <picture> element to switch out a GIF file with an image if the user has reduced motion enabled. This is how Brad goes about implementing that:

<picture> <!-- This image will be loaded if the media query is true --> <source srcset="no-motion.jpg" media="(prefers-reduced-motion: reduce)"></source> <!-- Otherwise, load this gif --> <img srcset="animated.gif" alt="brick wall"/> </picture>

How nifty is this? It makes me wonder if there are other ways this image-switching technique can be used besides accessibility and responsive images...

Also, it’s worth noting that Eric Bailey wrote about the reduced motion media query a while back where he digs into its history and various approaches to use it.

Direct Link to ArticlePermalink

The post Reducing motion with the picture element appeared first on CSS-Tricks.

A Practical Use Case for Vue Render Functions: Building a Design System Typography Grid

Css Tricks - Thu, 05/30/2019 - 5:07am

This post covers how I built a typography grid for a design system using Vue render functions. Here’s the demo and the code. I used render functions because they allow you to create HTML with a greater level of control than regular Vue templates, yet surprisingly I couldn’t find very much when I web searched around for real-life, non-tutorial applications of them. I’m hoping this post will fill that void and provide a helpful and practical use case on using Vue render functions.

I’ve always found render functions to be a little out-of-character for Vue. While the rest of the framework emphasizes simplicity and separation of concerns, render functions are a strange and often difficult-to-read mix of HTML and JavaScript.

For example, to display:

<div class="container"> <p class="my-awesome-class">Some cool text</p> </div>

...you need:

render(createElement) { return createElement("div", { class: "container" }, [ createElement("p", { class: "my-awesome-class" }, "Some cool text") ]) }

I suspect that this syntax turns some people off, since ease-of-use is a key reason to reach for Vue in the first place. This is a shame because render functions and functional components are capable of some pretty cool, powerful stuff. In the spirit of demonstrating their value, here’s how they solved an actual business problem for me.

Quick disclaimer: It will be super helpful to have the demo open in another tab to reference throughout this post.

Defining criteria for a design system

My team wanted to include a page in our VuePress-powered design system showcasing different typography options. This is part of a mockup that I got from our designer.

And here’s a sample of some of the corresponding CSS:

h1, h2, h3, h4, h5, h6 { font-family: "balboa", sans-serif; font-weight: 300; margin: 0; } h4 { font-size: calc(1rem - 2px); } .body-text { font-family: "proxima-nova", sans-serif; } .body-text--lg { font-size: calc(1rem + 4px); } .body-text--md { font-size: 1rem; } .body-text--bold { font-weight: 700; } .body-text--semibold { font-weight: 600; }

Headings are targeted with tag names. Other items use class names, and there are separate classes for weight and size.

Before writing any code, I created some ground rules:

  • Since this is really a data visualization, the data should be stored in a separate file.
  • Headings should use semantic heading tags (e.g. <h1>, <h2>, etc.) instead of having to rely on a class.
  • Body content should use paragraph (<p>) tags with the class name (e.g. <p class="body-text--lg">).
  • Content types that have variations should be grouped together by wrapping them in the root paragraph tag, or corresponding root element, without a styling class. Children should be wrapped with <span> and the class name.
<p> <span class="body-text--lg">Thing 1</span> <span class="body-text--lg">Thing 2</span> </p>
  • Any content that’s not demonstrating special styling should use a paragraph tag with the correct class name and <span> for any child nodes.
<p class="body-text--semibold"> <span>Thing 1</span> <span>Thing 2</span> </p>
  • Class names should only need to be written once for each cell that's demonstrating styling.
Why render functions make sense

I considered a few options before starting:

Hardcoding

I like hardcoding when appropriate, but writing my HTML by hand would have meant typing out different combinations of the markup, which seemed unpleasant and repetitive. It also meant that data couldn’t be kept in a separate file, so I ruled out this approach.

Here’s what I mean:

<div class="row"> <h1>Heading 1</h1> <p class="body-text body-text--md body-text--semibold">h1</p> <p class="body-text body-text--md body-text--semibold">Balboa Light, 30px</p> <p class="group body-text body-text--md body-text--semibold"> <span>Product title (once on a page)</span> <span>Illustration headline</span> </p> </div> Using a traditional Vue template

This would normally be the go-to option. However, consider the following:

See the Pen
Different Styles Example
by Salomone Baquis (@soluhmin)
on CodePen.

In the first column, we have:

- An <h1>> tag rendered as-is.
- A <p> tag that groups some <span> children with text, each with a class (but no special class on the <p> tag).
- A <p> tag with a class and no children.

The result would have meant many instances of v-if and v-if-else, which I knew would get confusing fast. I also disliked all of that conditional logic inside the markup.

Because of these reasons, I chose render functions. Render functions use JavaScript to conditionally create child nodes based on all of the criteria that’s been defined, which seemed perfect for this situation.

Data model

As I mentioned earlier, I’d like to keep typography data in a separate JSON file so I can easily make changes later without touching markup. Here’s the raw data.

Each object in the file represents a different row.

{ "text": "Heading 1", "element": "h1", // Root wrapping element. "properties": "Balboa Light, 30px", // Third column text. "usage": ["Product title (once on a page)", "Illustration headline"] // Fourth column text. Each item is a child node. }

The object above renders the following HTML:

<div class="row"> <h1>Heading 1</h1> <p class="body-text body-text--md body-text--semibold">h1</p> <p class="body-text body-text--md body-text--semibold">Balboa Light, 30px</p> <p class="group body-text body-text--md body-text--semibold"> <span>Product title (once on a page)</span> <span>Illustration headline</span> </p> </div>

Let’s look at a more involved example. Arrays represent groups of children. A classes object can store classes. The base property contains classes that are common to every node in the cell grouping. Each class in variants is applied to a different item in the grouping.

{ "text": "Body Text - Large", "element": "p", "classes": { "base": "body-text body-text--lg", // Applied to every child node "variants": ["body-text--bold", "body-text--regular"] // Looped through, one class applied to each example. Each item in the array is its own node. }, "properties": "Proxima Nova Bold and Regular, 20px", "usage": ["Large button title", "Form label", "Large modal text"] }

Here’s how that renders:

<div class="row"> <!-- Column 1 --> <p class="group"> <span class="body-text body-text--lg body-text--bold">Body Text - Large</span> <span class="body-text body-text--lg body-text--regular">Body Text - Large</span> </p> <!-- Column 2 --> <p class="group body-text body-text--md body-text--semibold"> <span>body-text body-text--lg body-text--bold</span> <span>body-text body-text--lg body-text--regular</span> </p> <!-- Column 3 --> <p class="body-text body-text--md body-text--semibold">Proxima Nova Bold and Regular, 20px</p> <!-- Column 4 --> <p class="group body-text body-text--md body-text--semibold"> <span>Large button title</span> <span>Form label</span> <span>Large modal text</span> </p> </div> The basic setup

We have a parent component, TypographyTable.vue, which contains the markup for the wrapper table element, and a child component, TypographyRow.vue, which creates a row and contains our render function.

I loop through the row component, passing the row data as props.

<template> <section> <!-- Headers hardcoded for simplicity --> <div class="row"> <p class="body-text body-text--lg-bold heading">Hierarchy</p> <p class="body-text body-text--lg-bold heading">Element/Class</p> <p class="body-text body-text--lg-bold heading">Properties</p> <p class="body-text body-text--lg-bold heading">Usage</p> </div> <!-- Loop and pass our data as props to each row --> <typography-row v-for="(rowData, index) in $options.typographyData" :key="index" :row-data="rowData" /> </section> </template> <script> import TypographyData from "@/data/typography.json"; import TypographyRow from "./TypographyRow"; export default { // Our data is static so we don't need to make it reactive typographyData: TypographyData, name: "TypographyTable", components: { TypographyRow } }; </script>

One neat thing to point out: the typography data can be a property on the Vue instance and be accessed using $options.typographyData since it doesn’t change and doesn’t need to be reactive. (Hat tip to Anton Kosykh.)

Making a functional component

The TypographyRow component that passes data is a functional component. Functional components are stateless and instanceless, which means that they have no this and don’t have access to any Vue lifecycle methods.

The empty starting component looks like this:

// No <template> <script> export default { name: "TypographyRow", functional: true, // This property makes the component functional props: { rowData: { // A prop with row data type: Object } }, render(createElement, { props }) { // Markup gets rendered here } } </script>

The render method takes a context argument, which has a props property that’s de-structured and used as the second argument.

The first argument is createElement, which is a function that tells Vue what nodes to create. For brevity and convention, I’ll be abbreviating createElement as h. You can read about why I do that in Sarah’s post.

h takes three arguments:

  1. An HTML tag (e.g. div)
  2. A data object with template attributes (e.g. { class: 'something'})
  3. Text strings (if we’re just adding text) or child nodes built using h
render(h, { props }) { return h("div", { class: "example-class" }, "Here's my example text") }

OK, so to recap where we are at this point, we’ve covered creating:

  • a file with the data that’s going to be used in my visualization;
  • a regular Vue component where I’m importing the full data file; and
  • the beginning of a functional component that will display each row.

To create each row, the data from the JSON file needs to be passed into arguments for h. This could be done all at once, but that involves a lot of conditional logic and is confusing.

Instead, I decided to do it in two parts:

  1. Transform the data into a predictable format.
  2. Render the transformed data.
Transforming the common data

I wanted my data in a format that would match the arguments for h, but before doing this, I wrote out how I wanted things structured:

// One cell { tag: "", // HTML tag of current level cellClass: "", // Class of current level, null if no class exists for that level text: "", // Text to be displayed children: [] // Children each follow this data model, empty array if no child nodes }

Each object represents one cell, with four cells making up each row (an array).

// One row [ { cell1 }, { cell2 }, { cell3 }, { cell4 } ]

The entry point would be a function like:

function createRow(data) { // Pass in the full row data and construct each cell let { text, element, classes = null, properties, usage } = data; let row = []; row[0] = createCellData(data) // Transform our data using some shared function row[1] = createCellData(data) row[2] = createCellData(data) row[3] = createCellData(data) return row; }

Let’s take another look at our mockup.

The first column has styling variations, but the rest seem to follow the same pattern, so let’s start with those.

Again, the desired model for each cell is:

{ tag: "", cellClass: "", text: "", children: [] }

This gives us a tree-like structure for each cell since some cells have groups of children. Let’s use two functions to create the cells.

  • createNode takes each of our desired properties as arguments.
  • createCell wraps around createNode so that we can check if the text that we’re passing in is an array. If it is, we build up an array of child nodes.
// Model for each cell function createCellData(tag, text) { let children; // Base classes that get applied to every root cell tag const nodeClass = "body-text body-text--md body-text--semibold"; // If the text that we're passing in as an array, create child elements that are wrapped in spans. if (Array.isArray(text)) { children = text.map(child => createNode("span", null, child, children)); } return createNode(tag, nodeClass, text, children); } // Model for each node function createNode(tag, nodeClass, text, children = []) { return { tag: tag, cellClass: nodeClass, text: children.length ? null : text, children: children }; }

Now, we can do something like:

function createRow(data) { let { text, element, classes = null, properties, usage } = data; let row = []; row[0] = "" row[1] = createCellData("p", ?????) // Need to pass in class names as text row[2] = createCellData("p", properties) // Third column row[3] = createCellData("p", usage) // Fourth column return row; }

We pass properties and usage to the third and fourth columns as text arguments. However, the second column is a little different; there, we’re displaying the class names, which are stored in the data file like:

"classes": { "base": "body-text body-text--lg", "variants": ["body-text--bold", "body-text--regular"] },

Additionally, remember that headings don’t have classes, so we want to show the heading tag names for those rows (e.g. h1, h2, etc.).

Let’s create some helper functions to parse this data into a format that we can use for our text argument.

// Pass in the base tag and class names as arguments function displayClasses(element, classes) { // If there are no classes, return the base tag (appropriate for headings) return getClasses(classes) ? getClasses(classes) : element; } // Return the node class as a string (if there's one class), an array (if there are multiple classes), or null (if there are none.) // Ex. "body-text body-text--sm" or ["body-text body-text--sm body-text--bold", "body-text body-text--sm body-text--italic"] function getClasses(classes) { if (classes) { const { base, variants = null } = classes; if (variants) { // Concatenate each variant with the base classes return variants.map(variant => base.concat(`${variant}`)); } return base; } return classes; }

Now we can do this:

function createRow(data) { let { text, element, classes = null, properties, usage } = data; let row = []; row[0] = "" row[1] = createCellData("p", displayClasses(element, classes)) // Second column row[2] = createCellData("p", properties) // Third column row[3] = createCellData("p", usage) // Fourth column return row; } Transforming the demo data

This leaves the first column that demonstrates the styles. This column is different because we’re applying new tags and classes to each cell instead of using the class combination used by the rest of the columns:

<p class="body-text body-text--md body-text--semibold">

Rather than try to do this in createCellData or createNodeData, let’s make another function to sit on top of these base transformation functions and handle some of the new logic.

function createDemoCellData(data) { let children; const classes = getClasses(data.classes); // In cases where we're showing off multiple classes, we need to create children and apply each class to each child. if (Array.isArray(classes)) { children = classes.map(child => // We can use "data.text" since each node in a cell grouping has the same text createNode("span", child, data.text, children) ); } // Handle cases where we only have one class if (typeof classes === "string") { return createNode("p", classes, data.text, children); } // Handle cases where we have no classes (ie. headings) return createNode(data.element, null, data.text, children); }

Now we have the row data in a normalized format that we can pass to our render function:

function createRow(data) { let { text, element, classes = null, properties, usage } = data let row = [] row[0] = createDemoCellData(data) row[1] = createCellData("p", displayClasses(element, classes)) row[2] = createCellData("p", properties) row[3] = createCellData("p", usage) return row } Rendering the data

Here’s how we actually render the data to display:

// Access our data in the "props" object const rowData = props.rowData; // Pass it into our entry transformation function const row = createRow(rowData); // Create a root "div" node and handle each cell return h("div", { class: "row" }, row.map(cell => renderCells(cell))); // Traverse cell values function renderCells(data) { // Handle cells with multiple child nodes if (data.children.length) { return renderCell( data.tag, // Use the base cell tag { // Attributes in here class: { group: true, // Add a class of "group" since there are multiple nodes [data.cellClass]: data.cellClass // If the cell class isn't null, apply it to the node } }, // The node content data.children.map(child => { return renderCell( child.tag, { class: child.cellClass }, child.text ); }) ); } // If there are no children, render the base cell return renderCell(data.tag, { class: data.cellClass }, data.text); } // A wrapper function around "h" to improve readability function renderCell(tag, classArgs, text) { return h(tag, classArgs, text); }

And we get our final product! Here’s the source code again.

Wrapping up

It’s worth pointing out that this approach represents an experimental way of addressing a relatively trivial problem. I’m sure many people will argue that this solution is needlessly complicated and over-engineered. I’d probably agree.

Despite the up-front cost, however, the data is now fully separated from the presentation. Now, if my design team adds or removes rows, I don’t have to dig into messy HTML — I just update a couple of properties in the JSON file.

Is it worth it? Like everything else in programming, I guess it depends. I will say that this comic strip was in the back of my mind as I worked on this:

Source: https://xkcd.com/974

Maybe that’s an answer. I’d love to hear all of your (constructive) thoughts and suggestions, or if you’ve tried other ways of going about a similar task.

The post A Practical Use Case for Vue Render Functions: Building a Design System Typography Grid appeared first on CSS-Tricks.

Customer Satisfaction Surveys with Wufoo

Css Tricks - Thu, 05/30/2019 - 5:06am

I was once tasked to create a makeshift customer service survey that would allow an employee to receive a customer call and send a survey to the custom once the call ended. The goal was to track customer satisfaction, which is a totally legit thing to want.

There are some solutions out there that do this out of the box. The problem was that my client neither had the desire or budget to use them. They did, however already use Campaign Monitor for sending emails and Wufoo for embedded forms. I figured, hey, if MacGyver can create complex gadgets out of bubble gum and paper clips, then I can cobble something together with these two robust tools. Right?

Right!

Knowing the data

The biggest challenge for a phone call is that it's sometimes difficult to track down an email address during the call. Without that, there's nowhere to send the survey, so that's a big bummer. That means the employee needs to capture the address, whether it's getting a custom ID at the start of the call or straight up asking for it.

I decided I would spin up Wufoo to create an internal form that employees can use to capture the data. Nothing fancy, only the following fields:

  • Employee Name: Used to associate the employee with the call
  • Customer Name: Used to personalize the email sent containing the survey link
  • Customer Email: Used to send the survey link

Wufoo makes this trivial, of course. Create a new form, add a few text fields, copy and paste the snippet onto a page. Voilà! We have a form! We could make it a little simpler (and dummy-proof) by creating a select field containing all employee names so the data remains consistent. We can also make the fields required and use Wufoo's built-in validation to ensure the email address is properly formatted.

There's also a lot of flexibility with the styling to boot, meaning the form can look like a native part of the site.

The employee can now fill that out during the call and submit it once the call is done. Plus, the form is embedded on a private page that can't accidentally get out to others.

Sending the survey

Did you know Wufoo can auto-send emails anywhere once a form is completed? Well, now you do!

This is super handy for most cases and I really wanted to use it for this task, but decided to go with Campaign Monitor because there's one little snag which is...

Each employee needs a unique survey form

Yep, that's a thing. Otherwise, we'd have to ask the customer to identify the employee's name in the survey, which we can't expect them to know. Sure, we could use another select field, but that requires the customer to recall the name as well, and not having the employee name makes it difficult to associate customer satisfaction results with specific employees for tracking.

So, the email needs to contain a unique link that goes to a form that's associated with a specific employee. Again, there are solutions for this stuff, but we're MacGyver'ing this thing.

I'm so glad Wufoo makes building forms so simple. All I needed to do was create one form, duplicate it for each employee, and change the employee value in each one.

On that note, we don't necessarily need to display the employee's name in the survey form. Wufoo accepts custom CSS which means we can hide any field! Plus, it allows us to pre-populate a field, so that gives us hidden fields that already contains the values we need to associate the survey data with a specific employee and create a webpage containing the form for that employee. &#x1f4a5;

Hidden fields are, well...hidden!

Now that there's a survey for each employee, all I needed to do was create webpages where I could embed each employee form and use those as the survey links.

Here's the flow:

Auto-sending the survey link

Let's go back to the first form for a moment. Remember, that's the one an employee fills out and submits once the call has ended. This should send an email to the customer containing a link to the webpage that has the survey form for that employee.

Campaign Monitor can segment lists by custom variables. In other words, we can create one list that contains all of the customers who have called in and create sub-lists that are divided by employee since we have that as a value in the internal employee form. And, since Campaign Monitor and Wufoo play nice together, all of the data we capture is contained in both places.

The other thing Campaign Monitor can do is trigger emails to send based on conditions. So, if the employee submits the internal form, Campaign Monitor can be configured to send a specific email template/campaign to a new subscriber that is added to the list. If we set up a trigger to send an email to any new customer who is added to the list, we can personalize the email to contain the link for the employee who took the call.

Watch the data roll in!

Great! We have a form employees can use to send a survey, surveys set up on webpages for each employee, and an auto-triggered email that's sent to a customer containing the survey link for the employee who submitted the internal survey.

All that's left is to monitor the data and — wouldn't you know it — Wufoo has reporting built right into it where all of that can be accessed and monitored 24/7. Heck, it even permits us to create custom reporting dashboards on a per-survey basis.

Wrapping up

Was this the best way to hack things together? Probably not. Is it bulletproof from incorrect data or misuse? Not entirely. But the fact that Wufoo could intervene at all and is flexible enough to power this sort of thing is awesome. It's more than awesome; it's amazing. It sure wasn't intended to be used that way, but it did the trick anyway.

Thanks, Wufoo!

The post Customer Satisfaction Surveys with Wufoo appeared first on CSS-Tricks.

A Quick Look at the First Public Working Draft for Color Adjust Module 1

Css Tricks - Wed, 05/29/2019 - 8:04am

We've been talking a lot about Dark Mode around here ever since Apple released it as a system setting in MacOS 10.14 and subsequently as part of Safari. It's interesting because of both what it opens up as as far as design opportunities as well as tailoring user experience based on actual user preferences.

This week, we got an Editor's Draft for the Color Adjust Module Level 1 specification and the First Public Working Draft of it. All of this is a work-in-progress, but the progression of it has been interesting to track. The spec introduces three new CSS properties that help inform how much control the user agent should have when determining the visual appearance of a rendered page based on user preferences.

color-scheme is the first property defined in the spec and perhaps the centerpiece of it. It accepts light and dark values which — as you may have guessed — correspond to Light Mode and Dark Mode preferences for operating systems that support them. And, for what it's worth, we could be dealing with labels other than "Light" and "Dark" (e.g. "Day" and "Night") but what we're dealing with boils down to a light color scheme versus a dark one.

Source: developer.apple.com

This single property carries some important implications. For one, the idea is that it allows us to set styles based on a user's system preferences which gives us fine-grained control over that experience.

Another possible implication is that declaring the property at all enables the user agent to take some responsibility for determining an element's colors, where declaring light or dark informs the user agent that an element is "aware" of color schemes and should be styled according to a preference setting matching the value. On the other hand, we can give the browser full control to determine what color scheme to use based on the user's system preferences by using the auto value. That tells the browser that an element is "unaware" of color schemes and that the browser can determine how to proceed using the user preferences and a systems's default styling as a guide.

It's worth noting at this point that we may also have a prefers-color-scheme media feature (currently in the Editor's Draft for the Media Queries Level 5 specification) that also serves to let us detect a user's preference and help gives us greater control of the user experience based on system preferences. Robin has a nice overview of it. The Color Adjust Module Level 1 Working Draft also makes mention of possibly using a color scheme value in a <meta> element to indicate color scheme support.

There's more to the property, of course, including an only keyword, chaining values to indicate an order of preference, and even an open-ended custom ident keyword. So definitely dig in there because there's a lot to take in.

Pretty interesting, right? Hopefully you're starting to see how this draft could open up new possibilities and even impacts how we make design decisions. And that's only the start because there are two more properties!

  • forced-color-adjust: This is used when we want to support color schemes but override the user agent's default stylesheet with our own CSS. This includes a note about possibly merging this into color-adjust.
  • color-adjust: Unlike forcing CSS overrides onto the user agent, this property provides a hint to browsers that they can change color values based on the both the user's preferences and other factors, such as screen quality, bandwidth, or whatever is "deem[ed] necessary and prudent for the output device." Eric Bailey wrote up the possibilities this property could open up as far as use cases, enhanced accessibility, and general implementations.

The current draft is sure to expand but, hey, this is where we get to be aware of the awesome work that W3C authors are doing, gain context for the challenges they face, and even contribute to the work. (See Rachel Andrew's advice on making contributions.)

The post A Quick Look at the First Public Working Draft for Color Adjust Module 1 appeared first on CSS-Tricks.

The difference between keyboard and screen reader navigation

Css Tricks - Wed, 05/29/2019 - 8:02am

There are a few differences between keyboards and screen readers and Léonie Watson highlights of them:

When using the tab key, keyboard focus and screen reader focus are synchronised with each other. The rest of the time, screen reader users have an enormous range of commands at their disposal for reading and navigating content independently of keyboard focus. The commands vary between screen readers, but they all have one thing in common: they’re tied to different HTML elements.

This is also a good reminder that screen readers behave differently from one another. It’s worth doing some research to see how our sites work in all these environments. One thing is clear from this post though: writing semantic and concise HTML is the best way to improve accessibility for both users with keyboards and screen readers. For example, Scott O'Hara has this recent post on best practices using the tabindex attribute to ensure accessible navigation using the keyboard.

Direct Link to ArticlePermalink

The post The difference between keyboard and screen reader navigation appeared first on CSS-Tricks.

Creating Interactive Maps in WordPress with MapSVG

Css Tricks - Wed, 05/29/2019 - 4:53am

The MapSVG plugin for WordPress allows you to create feature-rich, interactive maps quickly and through a smart admin UI. Interactive maps are a common request for projects when you need to visualize impact over particular locations. If you are already on WordPress, this comprehensive plugin could be your solution for production-ready maps.

Think about the last time you implemented or scoped an interactive map. You may wind up estimating a significant amount of time for mapping your data from its original source into JSON to be hooked to a visualization framework, like D3. Then comes configuring how users interact with the map itself. These are already significant development lifts.

Next comes the question of how you will manage your map data. Did it live in an external file? Require regular API calls to fetch data? It would be a lot easier to manage this data directly within your site’s WordPress admin as you would all other site content. No need to open up a code editor and maintain the map separately!

These and many other common map functionalities come baked into the MapSVG plugin for you to create multiple unique maps to fit your visualization needs. We’re going to dig into the plugin a little bit and use it to build an interactive SVG-based map in WordPress

Options for creating new maps

Once installed, MapSVG gives you five options for creating a new map based on vector, image, or Google Maps features. For the sake of this article, I will be focusing on the SVG features.

Choose between SVG, flat images and Google Maps as the base for each new map.

Within that New SVG map option are nearly 200 geo-calibrated and un-calibrated vector maps of countries and regions. The free version of this plugin, MapSVG Lite, lets site administrators create interactive maps with tooltips, customizable detail views, and markers placed by latitude/longitude coordinates. Upgrading to the paid version ($46) provides support for: map directory, integrated search, location filters, a detailed view of a map region, integrations with WordPress posts and Advanced Custom Fields, custom tooltips, and choropleth maps, among other premium features.

Creating a new map

Right, so we’ve chosen to create a new SVG-based map. Select one of the options from the dropdown to create a vector map. Whenever possible, choose geo-calibrated maps over ones that are un-calibrated. Geo-calibrated maps are newer and have region titles. Plus, they allow you to add map markers by geo-coordinates (i.e. latitude and longitude), or by entering an address that automatically converts to coordinates.

If using your own custom SVG file, select the Upload SVG option. Once uploaded, your custom file will be available in the New SVG Map dropdown under user-uploads/your-file-name.svg. There are a few additional steps I recommend to optimize your file prior to uploading it to the plugin's map:

  1. Regions that contain multiple vector paths (e.g. Hawaii), need to be grouped as a compound path in Illustrator. In Illustrator, this can be done by selecting the relevant paths, then going to Object > Compound Path > Make (or CMD + 8).
  2. Optimized custom SVG map of U.S. + British Columbia

  3. Ensure your layers have clear, unique names. The layer name will be used as the region {{id}} for templating and organizational purposes.
  4. Next, open your SVG file in a text editor and give each path a title attribute. This will be used as the region {{title}} in the templates.

The id and title fields are default attributes pulled from the file to associate them with the individual paths. As of the latest release (currently 5.3.7) of the plugin, you can edit the SVG file directly in the WordPress admin to set the id and title values of each path, along with adjusting the path definition and drawing new paths. I personally prefer the control of editing in Illustrator and a code editor, but this is a nice option to have available to you.

Let’s proceed by creating a demo using the geo-calibrated maps provided by the plugin and using entries from https://confs.tech to visualize (some of) this year’s tech conference data from around the world.

Styling the map

Now that we’ve got our SVG file all set up and selected for use, the plugin interface opens to the settings panel. This is where we set the map name, define sizing dimensions, and enable tooltips, among other primary settings.

Alongside the settings tab, you will see tabs for controlling and setting specific map features. Switching over to the next tab, Colors, is where we set the map theme.

As you can see above, we can control the fill and stroke values of the map and the various active states of each path. A benefit of using a vector based map! For that reason, I prefer to leave the fill and stroke values undefined in Illustrator if I’m creating a custom map file. Stroke width, however, cannot be efficiently adjusted within the UI (because it would requires editing the SVG and changing the value for every single path), so it is best to set it in Illustrator and re-upload the file.

Further down are color options for the containers (e.g. directory, filters, sidebars, etc.) as well as the minimum and max colors values for a choropleth map (more on this later!). Container styles can also be set globally either in your theme’s stylesheet or in the setting's CSS tab.

Setting up map data

By default, the Regions tab will be pre-populated by regions based on the paths of the selected SVG, displaying their id and title values. You can edit and create your own region’s fields as needed. The same applies for the Database tab — where you enter your map data and associate it with the regions of the map.

For both region and database entries, you have the option of manually creating the fields and content in the UI or upload the data from a CSV file.

This conference_count custom field will be used for the choropleth feature to create a thematic map of countries that have technical conferences this year, from least to most. Populating the Conference Count region's custom field. The populated database entries and the overlay displaying the data in the detailed view template.

Notice the final dataset in the screenshot above, specifically the custom Regions fields for conference_details, conference details, and a field to upload images that display the flag of each country in the database. We can take this a step further by separating the content from the map itself and pulling it in as post data of any WordPress post type. That’s where Advanced Custom Fields can help to create fields for that data in the post editor and creating a relationship between the submitted data to populate the values in the map. Not required, of course, but it’s nice to have this option for the sake of separation of concerns.

Displaying map data

When showing information about a region or database object on a map, we have to set up a template in the plugin. There are five types of templates: popovers, tooltips, detail view, directory, and labels.

Templates accept plain text, HTML, and Handlebar markup to display region and database variable values. If pulling in post data via the Post database field, you will have access to the standard WordPress fields, post.id, post.post_title, post.post_content, post.url, along with any custom fields created with Advanced Custom Fields with this syntax: post.acf.my_field_name. Whenever you need to render a rich text field such as with
post.post_content, you have to use Handlebars' {{{triple-stash}}} syntax to output the rendered HTML.

Details View template showing Handlebars conditional content and default helper comments.

The use of Handlebar syntax also means we can build conditional logic into the templates to create dynamic template views based on region and database values. In MapSVG 5.0 and up, the template options come pre-populated with HTML comments and starter markup for the default region and database fields. Super helpful!

Adding a map to a page

MapSVG includes a shortcode used to embed a map on any page or post. Drop a Gutenberg shortcode block on the page and call MapSVG with the ID of the map to embed: [mapsvg id="418"].

SVG equals 418 inside of square brackets." />Embedding a map using the shortcode block in the Gutenberg editor.

For those working in the classic WordPress editor or with a plugin version that predates 5.0, a map icon will be added to the TinyMCE toolbar, which will inject the shortcode to your post content that takes the map ID. The map ID can be found in the MapSVG editor dashboard or in the top breadcrumbs of the active map. A handy Copy to clipboard button is included next to both instances shortcode to grab it for use in the post editor.

Demo

With data entry complete and a few toggles of additional MapSVG settings, we have a fully functional interactive and responsive map! And notice just how little code we had to touch along the way.

View Full Demo

Going beyond maps

The great thing about the SVG feature of the plugin is that, at it’s core, SVG can be whatever we want. You can create an interactive "map" from the vector paths of just about anything: a building floor plan, an infographic, or maybe an interactive timeline of your career? It’s more than just maps!

Not on WordPress? No problem. MapSVG also comes as a jQuery plugin that's equally worth trying for interactive maps outside of WordPress.

Resources

The post Creating Interactive Maps in WordPress with MapSVG appeared first on CSS-Tricks.

Color contrast accessibility tools

Css Tricks - Tue, 05/28/2019 - 1:02pm

Accessibility is all the rage these days, specifically when it comes to color contrast. I’ve stumbled upon a couple of tools this week that I think are pretty nifty for helping make sure that all of the text on our websites is legible regardless of what background color they might have.

First up is the Accessible Color Generator which happens to be a wonderful tool for picking alternative colors. Let’s say you’re working on a brand with color X. You can generate a host of other complimentary colors like this:

Next up is Contrast, a rather great MacOS app that sits in the menu bar at all times and helps identify accessible color pairings based on WCAG Guidelines. This one is particularly useful if you happen to be a designer:

This reminds me of a wonderful post about how the Lyft design team re-approached the way they use color in their app. Kevyn Arnott explains:

Color, at least on the surface, appears almost naively simple, yet as it scales across larger products it becomes unbelievably complex. You have thousands of people building products all at once, and those products are all heavily reliant on color. This puts a lot of pressure on the color system to ensure that all the products are being created consistently, but very hard to implement since it’s all too easy to apply colors on a one-off basis.

The team then went ahead and built ColorBox.io which lets you systematically build out a ton of colors for your design systems work. It’s pretty nifty!

Plus the folks over at GOV.UK made their own color accessibility tool called Contrast Checker which (as you have guessed by the name) helps check the contrast between the background of an element and the page itself:

And, of course, there's the trusty WebAIM contrast checker, which is a go-to for many developers out there.

So far, we've looked at tools that check contrast. But there is a class of tooling that can automate accessible contrasts during development. Josh Bader wrote up an approach that enforces high contrast by pairing CSS custom properties with the calc() function. Facundo Corradini did something similar that switches font color based on the background color behind it.

Oh! And we may have something to look forward to with the color-adjust property. It is proposed in the CSS Color Module Level 4 specification and could give browsers more control to adjust color values that are declared in the stylesheet. It's not really geared towards color contrast, but there's something interesting about handing off the responsibility of rendering color values to the browser based on certain conditions.

The post Color contrast accessibility tools appeared first on CSS-Tricks.

Using the Grid Shepherd Technique to Order Data with CSS

Css Tricks - Tue, 05/28/2019 - 5:08am

Shepherds are good at tending to their sheep, bringing order and structure to their herds. Even if there are hundreds of those wooly animals, a shepherd still herds them back to the farm at the end of the day.

When dealing with data, programmers often don't know if it is correctly filtered or sorted. This is especially painful when iterating over an array then displaying the data on a site without knowing the locations of each element receiving it. The Grid Shepherd is a technique that helps position and sort items where you want them to be, using CSS Grid instead of JavaScript.

That’s what we’re going to look at in this post. The Grid Shepherd technique can bring order and structure to the data we work with while giving us greater visibility to where and how it’s being used than we would be able to otherwise.

Let’s dig in.

Sorting with JavaScript

We’re going to start by iterating over an unordered array of farm animals. Imagine that cows and sheep are happily grazing the fields. They can be grouped together programmatically with the Array.prototype.sort method and listed on a page:

let animals = [ { name: 'Edna', animal: 'cow' }, { name: 'Liam', animal: 'sheep' }, { name: 'Fink', animal: 'sheep' }, { name: 'Olga', animal: 'cow' }, ] let sortedAnimals = animals.sort((a, b) => { if (a.animal < b.animal) return -1 if (a.animal > b.animal) return 1 return 0 }) console.log(sortedAnimals) /* Returns: [ { name: 'Elga', animal: 'cow' }, { name: 'Olga', animal: 'cow' }, { name: 'Liam', animal: 'sheep' }, { name: 'Fink', animal: 'sheep' } ] */ Meet the Grid Shepherd

The Grid Shepherd method makes sorting data possible without the use of JavaScript. Instead, we rely on CSS Grid to do the lifting for us.

The structure is exactly the same as the JavaScript array of objects above, only represented in DOM nodes instead.

<main> <div class="cow">Edna</div> <div class="sheep">Liam</div> <div class="sheep">Jenn</div> <div class="cow">Fink</div> </main>

See the Pen
1. Start
by David Bernegger (@Achilles_2)
on CodePen.

To herd the animals, we have to fence them into a common area, which is what we’re using the <main> element to do. By setting that fence with display: grid, we’re creating a grid formatting context where we can define the column (or row) each animal should occupy.

.sheep { grid-column: 1; } .cow { grid-column: 2; }

And with grid-auto-flow: dense, each animal orders itself into the first available spot of each defined area. This can also be used with as many different sort options as you want — simply define another column and the data will be shepherded magically into it.

main display: grid; grid-auto-flow: dense; } .sheep { grid-column: 1; } .cow { grid-column: 2; }

See the Pen
2. Final
by David Bernegger (@Achilles_2)
on CodePen.

Pro Shepherding

We can take our herding example further with CSS Counters. That way, we can count how many animals we have in each column and — applying Heydon Pickering's quantity queries from Lea Verou's Talk in 2011 — conditionally style the them depending on how many there are.

Quantity queries rely on some sort of selector for counting the classes — which would be great with the :nth-child(An+B [of S]?) pseudo-class notation, but it’s currently only available in Safari). That means we have to use the :nth-of-type() selector as a workaround.

We need some new element types for this to work. This could be realized through Web Components or renaming any HTML element to a custom name. This works even if these elements are not in the HTML spec, as browsers use HTMLUnknownElement for undefined tags which results in them behaving much like a div. The document looks now like this:

<fence> <sheep>Lisa</sheep> <sheep>Bonnie</sheep> <cow>Olaf</cow> <sheep>Jenn</sheep> </fence>

Now we can access our custom element types. Let’s apply a red background when the number of sheep or the cows is equal to or less than 10.

sheep:nth-last-of-type(n+10), sheep:nth-last-of-type(n+10) ~ sheep, cow:nth-last-of-type(n+10), cow:nth-last-of-type(n+10) ~ cow, { background-color: red; }

Additionally the the counters can be simply realized by using counter-reset: countsheep countcow; on the parent element and using the before selector to target each element and count up.

sheep::before { counter-increment: countsheep; content: counter(countsheep); }

Here, we’re going to reach for Vue to dynamically add and remove animals using Vue transitions with two different sort options. Watch as the animals naturally occupy the correct columns, even as more are added and some are removed:

See the Pen
3. Final with Vue Transitions
by David Bernegger (@Achilles_2)
on CodePen.

Grid Shepherd can also be used with any non-ordered data to:

  • separate and count voters in a poll (maybe as two sections with their corresponding profile picture) with live insertion;
  • group people / co-workers according to their position, age, height; and
  • create any hierarchical structure
Shepherding and accessibility

grid-auto-flow: dense does not change the DOM structure of the grid — it merely reorders the contained elements visually. A side effect can be seen in the last example when ordering alphabetically as the counter numbers get mixed up. Changing the DOM structure not only affects people who use screen readers, but also effects tab traversal.

Also note that a flat document structure might not be good for screen readers. Instead, I would treat these presentational grids as graphs and provide the information with a longer textual alternative.

Round ‘em up!

It’s pretty neat to see how a powerful CSS layout tool like grid can be leveraged for use cases that fall outside of traditional layouts needs and into things where we may have reached for other languages in the past. In this case, we can see how the layout benefits of CSS Grid and the dynamic data-handling capabilities of JavaScript overlap and how that gives us more choices — and power — to bend rendered data to our will.

The post Using the Grid Shepherd Technique to Order Data with CSS appeared first on CSS-Tricks.

Prioritizing

Css Tricks - Mon, 05/27/2019 - 5:53am

You're faced with a lot of decisions in everyday work. There are multiple tasks calling for your focus, and you can burn daylight or even burn out trying to decide what comes first. There's a phenomenon called decision fatigue. There have been many studies that you can make poor choices when you're not able to decide what is most important that can lead to things like impaired judgement and even purchase decisions.

So how can you figure out what's most important to work on first, or even what tasks to work on at all? In this post, we'll explore how to sift through the inevitable weight of our to-do lists so that we can be efficient and clear with our direction.

If you feel like your to-do list is ruling you instead of you ruling it, read on.

How to invest your time

If you’re going to think smarter (and not harder) about how you prioritize tasks, you have to invest a little time away from your to-do list. Here’s the thing: what you work on informs your values. You may think it’s no big thing to work overtime for a little while, but something will be sacrificed with this decision. If you’re a parent, you might spend less time with your kids. Maybe it's less time hanging out with friends. Maybe you give up sleep or eating well.

Similarly, if you choose not to work much or effectively, you’re deciding that your values lie outside your career, which is ok too. No judgement here. But where you invest your time is not just about what you value, but also what you don’t value.

Photo by Jessica Lewis, Unsplash

Every quarter or so, I break down all the tasks I’ve committed doing. I write them all down, and I create four quadrants containing all of things I care about. This could be: helps the community, helps one-to-one relationships (which can include coworkers, friends, and family), makes money, and things I find personally fulfilling. This is just an example and your quadrants may be different, of course.

I then take all the things I have going and place them in the quadrants. I see how many of the boxes each one takes up. Some endeavors are counted in a quadrant twice to add weight to it.

Here are a couple allotments for me:

  • Writing things on CSS-Tricks (like this very article) is one of the rarest instances where all boxes are checked
  • Mentoring people checks: building one-to-one relationships, and something that I find personally fulfilling

Anything that fills just one box has to be reconsidered. Anything that fills nothing is usually on the chopping block. This activity allows me to see where I really want to invest my energy. It’s actually illuminating because sometimes I don’t really know what I value and how to prioritize tasks around those things until I do the exercise.

From here, the rest of the prioritization gets a little easier. I now have a better idea where my efforts are really paying off. I also know when I’m wasting my own time. This distinction helps me prevent decision fatigue quite a bit because I have a guiding light to help make choices.

What do you have to do?

In order to figure out a plan for yourself, the first thing you should be doing is gathering all of your tasks, large and small. Letting those things fester in our minds can make us feel burdened by what we have to do, so get it all out on proverbial paper. You can use notebooks, a homemade to-do list, applications like Notion, Evernote, or Clear. It's up to you.

I use several lists for a few reasons: I tend to retain information better if I write it down multiple in multiple places. For example, I need some things on mobile. I use Clear for those things, Notion on desktop, and a paper teacher planner (which I've shared before). I find that the repetition helps me solidify what’s important. That might not be right for you. That’s cool, do what works.

Coding priorities

You may work at a company that creates tickets for tasks. Some tickets are simple and you can knock them out quickly; some can be arduous. Whenever I have a larger coding task, I first break it down into a to-do list as comments in my code. It looks vaguely like this:

// get the request from the server // give us an error if it failed // do x thing with that request // format the data like so

That way, I can fill in the blanks with each task. I usually try to split each one into different pull requests so I can keep myself organized and make it easier on my reviewers. When it’s all done, I’ll go back and prune the comments or replace them with comments that explain the why (not how).

Overall prioritization

There are some tasks that are pretty straightforward. You need to do the thing. It’s indisputable. Other people are counting on you or your future self will depend on it somehow. These are actually easier to prioritize.

First I break down large tasks into smaller pieces. That helps me put things in order:

  1. Things that are actively on fire or are time-sensitive
  2. Things that can be done quickly
  3. Things that need a scheduled block of time
  4. Things that I may get to further along

Part of the reason we do the small things first is that morale is important. I feel more incensed to get my other work done because being productive feels good — there's a small dopamine rush associated with every check. This is also why I put things I've already accomplished on my list. It may sound silly, but acknowledging accomplishments makes me more likely to keep going and pushes me through the more complicated tasks.

Some people, like Alice Goldfuss, have this down to a science:

I have a kanban board for my personal life todo list and a cron job that empties my Done column and texts it to me every week, so I feel accomplished

— bletchley punk (@alicegoldfuss) May 25, 2019

Keep yourself motivated

Keeping yourself motivated is key. Sometimes this means keeping your own morale in mind. The good news is you know yourself pretty well. Here are some tricks that have served me well:

  • Put things on your to do list that you enjoy. You will start to associate your to do list with happiness. For instance, recently I put "read a dumb thriller fiction" on my to do list. It's ridiculous, but it works. It also helps me remember to do things outside of code all day.
  • Put things on your to do list that you've already done. When you mark them off you can get a sense of satisfaction that may entice you to gather more things you can check off. I think a lot of people do this. I definitely didn't come up with it.
  • Customize it a bit. Whether I use paper or digital means, I spend a minute or two customizing it and making it my own. It makes it more important to me, because I've invested in it, and I'm more likely to keep up with the contents.
Prioritizing based on energy levels

Chris Coyier mentioned a great blog post by Alex Sexton when I was pondering how I feel better suited for things like meetings on some days and heads-down coding on others.

I think this is brilliant! I’ve definitely had times in my career where I've suffered because of sporadic meetings with ill-defined amounts of time in between that were too small to be heads-down coding, and I would make up for it at night. That's not a recipe for success; it's a recipe for fatigue.

Photo by Ilya Ilford, Unsplash

Lately, I’ve been working on grouping similar tasks. For example, meetings should all happen in succession because it’s easier for me to jump from one to another than it is having an hour in between. I’m also more keen to communicate with others on Monday, when I’m getting the lay of the land. Towards the end of the week, my energy is higher if I’m dedicated to coding, especially if I’ve allotted uninterrupted time.

Notice when your energy levels are high and when they wane. Notice when you’re more productive for social activities and when you’re better off working in isolation. The more you study yourself, the easier planning becomes.

Scheduling

Now that you have your priorities in order, go ahead and schedule your time. I like to use the weekly planner in Notion. I’ll take all the things I think I can get done in a week and break them down day-by-day, based on when it makes the most sense to do each task. When I finish a task, it’s dragged to the top. Anything that’s unchecked at the bottom by the end of the day moves over to the next. I also have general to-do lists, and task-based lists, but the weekly planner is my holy grail. Again, you don’t have to do it exactly like I do, find what works for you.

I find some art to use as the cover for my weekly schedule so that I enjoy going to it. It's the little things. Know yourself

Most of these systems work for me because I know my strengths and weaknesses and I play to them: I work more efficiently when things are broken down into steps. I work best when my work has the most meaning, and I remove the cruft. I work best when I work along with, not against, my energy levels, where possible.

There’s one more thing I haven't addressed yet: forgiveness. You’ll be more productive on some days (or hell, even years!) than you will be on others, and that's OK. Life is full of ebbs and flows.

It’s good to check in to see if your waning productivity is the result of simply moving a little slower, signals signs of depression, represents misalignment with personal goals (or the company where you work), or if you’re reacting to a toxic environment.

In all cases, forgiveness is in order. In some cases, you may need more than a prioritization plan. But truly, you’ll never be able to do everything, because no one is capable of that. People you see on social media might also only be showing their successes, and conveniently leaving out their failures and struggles. The fact is that we all get distraught, and sometimes mental illness isn’t something we want to announce over the megaphone of social media. Try not to compare yourself to others. Forgive yourself a bit. Work an amount that’s reasonable for you.

Hopefully, if you’re prioritizing well, the amount of time that you do have to work is structured in a way that actually relieves stress and allows you to accomplish the most you can, when you can. The goal of prioritizing is to bring into focus the work that you find fulfilling, and removes tasks that don’t. That's the sweet spot.

The post Prioritizing appeared first on CSS-Tricks.

Night Mode with Mix Blend Mode: Difference

Css Tricks - Mon, 05/27/2019 - 5:53am

Dark mode designs are all the rage right now but here’s an interesting take: Wei Gao has built a night mode on her own site that uses mix-blend-mode: difference to create an effect that looks like this:

Wei explains how she implemented this technique and the edge cases she encountered along the way. I especially love what she had to say about mix-blend-mode functions here:

I remember first playing around with them in Photoshop years ago. Now that browsers are becoming more powerful and we are seeing complex graphical features native to browser rendering. This doesn’t mean we should implement a full photoshop in browsers and nor should we limit our imaginations to just that. Browsers and web pages have their own contexts and goals, as well as a different set of limits. Maybe we should welcome them like new habitants and discover use cases native to this territory.

Indeed! Although Wei's technique is pretty unique and awesome on its own, this all ties back into the thing that kicked off the whole trend: the prefers-color-scheme media feature that was released in Safari as part of the MacOS 10.4 release that gave us a dark mode preference setting. This is a developing space, so we're certain to see more innovations and approaches ahead.

Direct Link to ArticlePermalink

The post Night Mode with Mix Blend Mode: Difference appeared first on CSS-Tricks.

Code as Documentation: New Strategies with CSS Grid

Css Tricks - Fri, 05/24/2019 - 4:36am

I work for Supercool, a fast-moving design agency that makes custom built sites for arts clients, powered by the off-the-shelf system, Craft CMS; it's high-spec graphic design with relatively demanding typography and art direction. Over the past few months we’ve been moving to CSS grid. We’re transitioning slowly, allowing ourselves to discover new paradigms and design methods, instead of simply porting old habits to a new syntax.

So far, we've developed a number of really useful strategies for keeping track of the layout. I've written a couple of surprisingly nifty mixins, using named areas and templates, and we've hit upon some basic conventions to create highly readable code. I thought it would be valuable to walk through a fully-developed production implementation of a single major component using grid, digging in to some of the design questions it throws up and steering you away from some pitfalls we’ve encountered. CSS grid is a large spec, with lots of possible approaches and lots of right ways to do things, but at some point you have to lock down your method and get it live.

I’m expecting some basic familiarity with CSS, Sass, BEM, and some interest in the task of prototyping fully-realized, accessible, custom frameworks with 50+ components from Sketch or Photoshop-type documents on a tight timeline (say, a week).

First, let’s identify and separate out the design into distinct coding tasks and plan how we’ll approach them:

  1. Type: The designer has already defined a type system.
  2. Colors: First, we build a theme model and then include that in the partial.
  3. Content: What elements are in this block? What are its variations? This is where our BEM mixin comes in.
  4. Layout: This is how the content is placed in the block. You might want to skip directly to this.
  5. Conventions: This is exactly how we choose to write all the above. There are many right answers in CSS, so what is important is that we all just agree to a convention, the rules of the road. This really comes first, but for the sake of this article, we’ll conclude here.
Type system

We use utility classes (e.g. h-text--h1, h-text--badge) for type styles. There may be a hundred type styles in a project. We export those styles from Sketch right into our Patternlab using Typex. That’s a whole other article on its own, so let’s just stipulate type as handled. We won’t bring type into our component partial.

Color usage

See the Pen
CSS Variable fallbacks mixin v2
by limograf (@Sally_McGrath)
on CodePen.

Theming is a few tiny mixins dropped in, so we ideally won’t see a ton of color rules in our partial. We store them all together in a _themer.scss partial in our "Mixins and Models" library, so we can be sure to follow the design system of the site. This way, when someone comes back to the build later on, they have a key reference partial describing the design and branding rules. When building and maintaining numerous sites in broadly the same market — but each all with different brand spec — you’ve gotta make sure you don’t mix up one brand with another! So, much like type, we abstract the color rules away from the partial. In essence, we’re really only looking at layout (as much as possible) in our _header.scss file.

Given that we agree the convention to always theme using our mixin, this is how it would be included on an element:

@include var($property, $value);

Then we’ll set a theme model, of how colors work on this particular site and apply that theme to a component with:

@include theme;

Here’s the sample theme model we’re going to use with this page header. It’s super simple.

See the Pen
theme model
by limograf (@Sally_McGrath)
on CodePen.

We’re pairing a color with black or white. We depend on a contrast rule and flip them for emphasis, maybe on events, like hover, or a highlighted call to action. This is all we need to do to make that happen and now we have a document of how color should really work on this site. We can go to and check against if we need to debug or expand the UI.

We also want to prep inheritance to help us, so let’s identify some helpful conventions:

  • Set the fills on SVG icons to currentColor in your pipeline (and default size them as width: 1em; height: 1em; font-size: inherit; in the CSS while we’re at it).
  • Set <body> and <a> to currentColor) at base.
  • Write shorthand, inheriting borders (e.g. 1px solid or 1px solid currentColor).

Using this theme model, we might generate any number of themes, perhaps storing them as utility classes, or looping over a list of modifiers inside a component, or just allowing the user to set variables right on the block in the CMS. When IE 11 drops below 1% in our stats, we can do much more with variables, but this is enough for our current purposes.

Let’s not get side-tracked. What about grid?!

Content components

Grid lets us describe exactly what content we have in each partial in a new way. It’s really a game changer for design agencies building new UI for every project and we’re discovering new (and fun) applications for it as we explore.

To give context: we customize each interface for our clients, with custom fields made to suit their specific needs and their content model, using Craft CMS. We have internal tools that pull in events from ticketing APIs and create entries from that data, which may then be edited and expanded (or created entirely) in the CMS. The client can fill in or edit named fields in permanent page regions, and also add in whole designed, branded content blocks into the layout of each page as they build them.

There’s a lot of UI. The clients have a lot of control over content and we have a lot of control over the HTML, so we can ensure a high standard of accessible, semantic code on the page. We develop the content model together during discovery and then turn ’em loose on content creation. They add what they want and we ensure that it works and always looks right. Better than right! Super. (Sorry! :P)

So, as a developer, I have to balance competing priorities:

  • Accessibility, usability
  • Branding and graphic design
  • Performance
  • Maintenance and codebase health

Let’s look at those one by one:

Accessibility

Accessible, logical HTML is my jam. At minimum, I require a green accessibility score on Lighthouse score for my projects. (Who am I kidding, I want that delicious 100!) Core paths and pages are tested with a couple of screen readers, the keyboard tab, keyboard navigation), low vision simulators, dasher, voice access and binary switch. (I also work for Robots and Cake so this is a big part of my development.) I add giant clickable phone numbers and email addresses to pages over and over. I just want to get people where they are going.

I’ve been concerned about the way content can be re-ordered with grid (and flexbox, for that matter). Having gone through a few builds now, I actually think grid can help us with this problem. With CSS Grid, there’s no reason to move around HTML in service to the layout. We can go back to thinking about the whole document as a logical, linear sequence as our first concern.

Branding vs. Performance vs. Maintenance

Arts venues require high-spec graphic design, unified across print and web, and have constantly changing materials (e.g. programs, brochures, tickets, posters, microsites, etc.) they need to get out to their audiences, including contractual marketing obligations that must be met. As you can imagine, we have a lot of high quality large images we have to prioritize and typically come with strong print-led branding. That means we may be serving around fifteen custom fonts (including weight variations, display faces, etc.) and complex CSS to the page as well. We have to keep ourselves as lean as we can. We are shipping CSS that’s around 20 KB nano Gzipped at the moment but I’m working on reducing it further.

However, we do keep the grid area names full length by setting reduce identifiers to false in our PostCSS task. It’s vastly more useful to have the layout maps available in DevTools than it is to save those few bytes. For maintenance, self-documentation, and the sake of your future self who is debugging this site without repo access on a delayed train in Sowerby Bridge: keep the maps.

Code health

The way to balance all these competing needs is to articulate and agree on conventions so that there’s less to fix in testing and so that solved problems stay solved. We examine all the components we build and make sure they always start with a heading, that links go places, and buttons trigger actions, that countable objects are delivered as a list and preceded by a landmark heading, that navs are <nav> and times are <time> and div soup is eaten for breakfast— the basics.

With CSS Grid, there’s no excuse to move around HTML in service to the layout. Your content can always flow logically while changes in layout happen in CSS. And, as there’s no need for margins or padding to create gutters, you can simply declare:

.o-grid .o-grid { width:100%; }

...to be sure any number of nested groups all visually occupy the same page grid. The HTML can be a clearer guide to what things really are: a closer document.

See the Pen
lock down semantic accessible structures
by limograf (@Sally_McGrath)
on CodePen.

There’s a lot to manage between the heading and the action, and it’s my challenge to keep track of all these fields in all those components and make it traversable, scannable, linearizable, and easily read in some kind of logical, understandable manner, while making sure I’m faithfully executing the design spec.

Let’s bring in my first, surprisingly useful, grid mixin.

@mixin template($elements...) { @each $element in $elements { &__#{$element} { grid-area: $element; } } }

Using this mixin everywhere means:

  1. Each component partial now starts out with a list of all its possible elements, which is a very handy piece of documentation, especially when Twigging the actual front-end component.
  2. The mixin takes care of assigning the grid areas.
  3. Element and component names stay consistent across Sketch, CSS, and HTML and any inconsistencies will be very obvious, as the layout will fail. I’m firm, but fair.
  4. BEM naming is enforced automatically but isn’t muddling things up in the partial.

Now, in the partial, we will just declare grid-template-areas, using normal English words, giving us a series of maps of the layouts that also match the database fields. Super readable!

Here’s an example of this mixin working:

See the Pen
BEM ELEMENT AUTO ASSIGN
by limograf (@Sally_McGrath)
on CodePen.

We decided to stick to named areas for internal grids because I read a great article on this very site explaining how Autoprefixer can handle grid for IE 11 if you stick to the listed supported properties — and it does for the most part. If you view this test case with Autoprefixer applied in the super useful Debug Mode in a browser test, you’ll see it working.

So far, so good.

But there are pitfalls! You must set inline elements to block to make sure they always operate as grid cells in IE 11. Comment out the marked line in the example to see what happens otherwise:

Debug has caught an issue.

Ouch! Be careful with those blocks. You may find some versions of IE 11 don’t even pick up this fix, in which case you might try just using plain ol’ <p> tags... sigh.

I don’t include display: grid in this mixin because there are scenarios where the actual grid is set on an inner container, for example, but we’d still want the grid-areas to match on the correct BEM class.

So:

.c-header{ @include template(title, pretitle, posttitle, producer, venue, credit, quote, nav, infobar, search); }

Let’s lay these suckers out.

Layout

Let’s identify a few more rules of the road to ensure this component slides right into a page layout without hassle. At time of writing, there’s no subgrid) available (but there will be!), so this component knows nothing of the parent grid it’s living in. This happens to match the BEM component approach well — as each component is written flat, and orphaned, to limit inheritance. I’m not advocating for BEM (or BEM-ish as we obviously use) here — I’m just saying that if you’re already using it, this is a bonus.

In this example, the designer has set a page layout of 12 column grid with 20px (1.25rem) gutters, site-wide, with no offset pieces. Our component is a page region and will occupy all 12 grid columns. In this transitional period, we’re still using this kind of set grid as we have a ton of systems still based on this idea that we have to integrate with. So, here’s our convention for this condition: for a full width region drop the grip gap and write the grid template columns as fractional units (fr) of 12.

Doing things this way means:

  1. the sight lines of this internal grid broadly follow the grid it sits within;
  2. it’s easy to see the underlying design rules in the code; and
  3. it’s easy to line things up exactly, if required.
A quick note on "lining up"

Wait... what do I mean 'to have things line up exactly'? Doesn’t it already line up exactly?

Two equal columns split mid-gutter of the parent 12-column grid.

Well, no. The fractional units approach divides across the space perfectly, so you end up in the gutter. Two even columns lands you halfway across the gutter. Two columns where one is 2/3 and the other is 1/3 will split 1/3 of the way across that gutter, and so on.

Two unequal columns (set to 2fr and 1fr, respectively) split a third of the way into a gutter of the 12-column parent grid.

It’s not exactly hard to fix the alignment, as we know the width of our page grid gutter. For example, on an even split, we could include the grid gap.

However, we can’t do that with any other division. What we can do is add that gap as a margin — the margin is added inside no matter what box sizing you have set. In this example, we have three columns (two named areas and one empty space), splitting our gutter into thirds:

This is how to calculate those margins: Make sure the total fr units sum results in 12. Divide the grid gap by the number of columns in the parent grid, then multiply that like so:

The right margin multiplier of n is equal to the sum of the fr units to the right of n. The left margin of n is equal to the sum of the fr units to the left of n.

So, for grid-template-columns with a value of 2fr 3fr 2fr 4fr 1fr:

2 3 2 4 1 0/10 2/7 5/5 7/1 11/0

See the Pen
name spec inside and number spec outside -- page region, desktop
by limograf (@Sally_McGrath)
on CodePen.

You could even write that as a mixin if you find yourself writing calc() a lot. Something like this for aligning an inner grid to the parent grid:

See the Pen
auto align inner grid to parent grid
by limograf (@Sally_McGrath)
on CodePen.

...and something like this to auto-calculate margins when the name is specified inside but the number is specified outside the grid:

See the Pen
name spec inside and number spec outside -- auto calc margins
by limograf (@Sally_McGrath)
on CodePen.

I’m sure you can think of other solutions, like switching to named lines, or adding in extra fixed-width columns or even writing all maps with 12 named areas per row. There are so many ways you can deal with this, but I think a lot of them remove the advantage of named areas. Areas give us a readable layout map that contains what our future selves need to know. It is code as documentation.

To be clear, the design problem I’m walking us through is not one of alignment. Alignment is easy with grid. The question is not of solving the immediate, trivial, layout problem, but of solving it in a way that supports our goal of being able to come back in six months and grasp:

  1. What elements are in the component.
  2. How they are laid out.
  3. Why the code is written in this way.

The grid specification is huge and it’s easy to get lost in the options. Perhaps it’s a better plan to reset to a 12-column grid and use the number spec (i.e. explicitly link to our page grid, which uses the number spec) when absolute alignment is required — but I do feel there’s a smarter, simpler solution waiting to be found. For this site, we ended up writing a page grid object and added nested internal grid cells to it with classes: .o-page-grid__sidebar.

What do you all think? I definitely foresee differing perspectives on this. &#x1f926;‍♀️

A real, live grid!

We can use this to create a generic page header:

See the Pen
01 - Generic Page header
by limograf (@Sally_McGrath)
on CodePen.

Or, we can create a variation of the homepage:

See the Pen
02 - Home page
by limograf (@Sally_McGrath)
on CodePen.

What about a hero header that breaks out of our container? Sure! Or we can deliver it outside the container as well:

See the Pen
03 - Hero
by limograf (@Sally_McGrath)
on CodePen.

What next? A themed event header with a full width info bar that sticks and an internal button that lines up with the sidebar on the parent grid? You bet. I’ll include a parent grid so it’s easier to see:

See the Pen
04 - Event header
by limograf (@Sally_McGrath)
on CodePen.

What about a search with a central alignment? Let’s use a collapsing columns technique:

See the Pen
06 - Search with central alignment
by limograf (@Sally_McGrath)
on CodePen.

Here’s a demo of all these variations as one partial. Yes, it’s a map! And it’s a wrap!

Conventions

Phew, we covered a lot! But you can see how flexible and self-documenting a system like this can be, right?

  1. Type is handled with a separate type system.
  2. Colors are handled by a theme partial that describes the underlying color rules of the design, rather than simply coloring elements ad hoc.
  3. Elements are called what they are, in English, and included as a list at the top of the partial with the template mixin. This list can be taken into Twig or a template as a reference.
  4. Correct HTML is always used and nesting doesn’t break grid. That means you can apply any number of nested grids to the same layout space by setting a convention.
  5. Precise alignment is done in a number spec, and not a name spec (but note that alignment is possible with name spec).
  6. IE 11 is supported.
  7. I do have one more quick note and example of another component built with named areas. In this example, cards are not regions, but components placed in a grid, so there’s no reason to use the fr of 12 convention. You can expect a media object partial to look like this:

    .c-card { &--news { align-content: start; grid-template-areas: "image" "datetime" "title"; } &--search { justify-content: start; grid-template-columns: 1fr 3fr; grid-template-areas: "image page" "image title" "image summary"; } &--merchandise { grid-gap: 0; grid-template-columns: $b 1fr 1fr $b; grid-template-areas: "image image image image" ". title title ." ". summary summary ." ". price action ."; } &--donations { // donations thanks button is too long and must take up more space than input grid-gap: 0; grid-template-columns: $b 1fr 2fr $b; grid-template-areas: "image image image image" ". title title ." ". summary summary ." ". input action ."; } } // ...

    The post Code as Documentation: New Strategies with CSS Grid appeared first on CSS-Tricks.

Weekly Platform News: Mozilla WebThings, Internet Explorer mode, GraphQL

Css Tricks - Fri, 05/24/2019 - 4:28am

Šime posts regular content for web developers on webplatform.news.

Mozilla WebThings provides complete privacy for user data

If you, like many we surveyed, are also concerned about the security & privacy of you smart home check out @MozillaIoT's decentralized, open source solution for keeping your smarthome devices at bay—or learn more dropping by our Bay Area Maker Faire booth! https://t.co/rUcYpjBySH

— Mozilla Hacks (@mozhacks) May 17, 2019

Josephine Lau: Smart home companies require that users’ data goes through their servers, which means that people are giving up their privacy for the convenience of a smart home device (e.g., smart light bulb).

We’ve learned that people are concerned about the privacy of their smart home data. And yet, when there’s no alternative, they feel the need to trade away their privacy for convenience.

Mozilla WebThings is an alternative approach to the Internet of Things that stores user data in the user’s home. Devices can be controlled locally via a web interface, and the data is tunneled through a private HTTPS connection.

A diagram showing how Mozilla doesn’t store user data in the cloud, unlike smart home vendors. An Internet Explorer mode is coming to Edge

Still have questions on the recently announced IE mode? Our very own Fred Pullen has all the answers. Check out his in-depth breakdown on how the new IE mode works, and the benefits it will bring to our enterprise community once it goes live.https://t.co/RgewXGC1G2

— Microsoft Edge Dev (@MSEdgeDev) May 17, 2019

Fred Pullen: The next version of Edge will include an Internet Explorer mode for backward compatibility with legacy websites. Edge will also for the first time be available on older versions of Windows (including Windows 7 and 8.1).

By introducing Internet Explorer mode, we’re effectively blurring the lines between the browsers. From an end-user standpoint, it seems like a single browser. … You can use IE mode to limit the sites that instantiate Internet Explorer just to the sites that you approved.

Quick hits: Other interesting articles

Introducing the first Microsoft Edge preview builds for macOS (Microsoft Edge Blog)

Edge Canary (analogous to Chrome Canary) is now officially available on macOS. This version of Edge updates daily.

With our new Chromium foundation, you can expect a consistent rendering experience across the Windows and macOS versions of Microsoft Edge.

#EmberJS2019 More Accessible Than Ever (Yehuda Katz)

Navigating from one page to another in a client-side web app provides no feedback by default in virtually all popular routing solutions across the client-side ecosystem.

Their goal is to make Ember’s router more accessible and screen reader friendly.

Opinion: Five developer trends to watch in 2019 (DeveloperTech)

The article includes a good, short explanation of what GraphQL is and what problems it solves.

Part 2: What the Fr(action)? (CSS IRL)

Read the last section ("Intrinsic and extrinsic sizing"). All three columns have the size 1fr but the middle one is wider because of its content. This can be prevented by using the size minmax(0, 1fr) instead.

Parallel streaming of progressive images (Cloudflare Blog)

Instead of loading from top to bottom, progressive images appear blurry at first and become sharper as more data loads.

The benefits of progressive rendering are unique to JPEG (supported in all browsers) and JPEG 2000 (supported in Safari). GIF and PNG have interlaced modes, but these modes come at a cost of worse compression. WebP doesn't even support progressive rendering at all. This creates a dilemma: WebP is usually 20%-30% smaller than a JPEG of equivalent quality, but progressive JPEG appears to load 50% faster.

The post Weekly Platform News: Mozilla WebThings, Internet Explorer mode, GraphQL appeared first on CSS-Tricks.

The Power of Serverless v2.0! (Now an Open-Source Gatsby Site Hosted on Netlify)

Css Tricks - Thu, 05/23/2019 - 9:01am

I created a website called The Power of Serverless for Front-End Developers over at thepowerofserverless.info a little while back while I was learning about that whole idea. I know a little more now but still have an endless amount to learn. Still, I felt like it was time to revamp that site a bit.

For one thing, just like our little conferences website, the new site is a subdomain of this very site:

https://serverless.css-tricks.com/

Why? What's this site all about?

The whole idea behind the serverless buzzword is a pretty big deal. Rather than maintaining your own servers, which you already buy from some other company, you architect your app such that everything is run on commoditized servers you access on-demand instead.

Hosting becomes static, which is rife with advantages. Just look at Netlify who offer blazing-fast static hosting and innovate around the developer experience. The bits you still need back-end services for run in cloud functions that are cheap and efficient.

This is a big deal for front-end developers. We've already seen a massive growth in what we are capable of doing on the front end, thanks to the expanding power of JavaScript. Now a JavaScript developer can be building entire websites from end-to-end with the JAMstack concept.

But you still need to know how to string it all together. Who do you use to process forms? Where do you store the data? What can I use for user authentication? What content management systems are available in this world? That's what this site is all about! I'd like the site to be able to explain the concept and offer resources, but more importantly, be a directory to the slew of services out there that make up this new serverless world.

The site also features a section containing ideas that might help you figure out how you might use serverless technology. Perhaps you'll even take a spin making a serverless site.

Design by Kylie Timpani and illustration by Geri Coady

Kylie Timpani (yes, the same Kylie who worked on the v17 design of this site!) did all the visual design for this project.

Geri Coady did all the illustration work.

If anything looks off or weird, blame my poor implementation of their work. I'm still making my way through checklists of improvements as we speak. Sometimes you just gotta launch things and improve as you go.

Everything is on GitHub and contributions are welcome

It's all right here.

I'd appreciate any help cleaning up copy, adding services, making it more accessible... really anything you think would improve the site. Feel free to link up your own work, although I tend to find that contributions are stronger when you are propping up someone else rather than yourself. It's ultimately my call whether your pull request is accepted. That might be subjective sometimes.

Before doing anything dramatic, probably best to talk it out by emailing me or opening an issue. There's already a handful of issues in there.

I suspect companies that exist in this space will be interested in being represented in here somewhere, and I'm cool with that. Go for it. Perhaps we can open up some kind of sponsorship opportunities as well.

Creating with components: A good idea

I went with Gatsby for this project. A little site like this (a couple of pages of static content) deserves to be rendered entirely server-side. Gatsby does that, even though you work entirely in React, which is generally thought of as a client-side technology. Next.js and react-static are similar in spirit.

I purposely wanted to work in JavaScript because I feel like JavaScript has been doing the best job around the idea of architecting sites in components. Sure, you could sling some partials and pass local variables in Rails partials or Nunjucks includes, but it's a far cry from the versatility you get in a framework like React, Vue or Angular that are designing entirely to help build components for the front end.

The fact that these JavaScript frameworks are getting first-class server-side rendering stories is big. Plus, after the site's initial render, the site "hydrates" and you end up getting that SPA feel anyway... fantastic. Yet another thing that shows how a JavaScript-focused front-end developer is getting more and more powerful.

As an aside: I don't have much experience with more complicated content data structures and JAMstack sites. I suspect once you've gone past this "little simple cards of data" structure, you might be beyond what front-matter Markdown files are best suited toward and need to get into a more full-fledged CMS situation, hopefully with a GraphQL endpoint to get whatever you need. Ripe space, for sure.

The post The Power of Serverless v2.0! (Now an Open-Source Gatsby Site Hosted on Netlify) appeared first on CSS-Tricks.

Front-End Documentation, Style Guides and the Rise of MDX

Css Tricks - Thu, 05/23/2019 - 4:29am

You can have the best open source project in the world but, if it doesn’t have good documentation, chances are it’ll never take off. In the office, good documentation could save you having to repeatedly answer the same questions. Documentation ensures that people can figure out how things work if key employees decide to leave the company or change roles. Well documented coding guidelines help bring consistency to a codebase.

If you’re writing long-form text, Markdown is clearly a great alternative to authoring HTML. Sometimes though, Markdown syntax isn’t enough. It’s always been possible to write straight HTML inside of Markdown documents. This includes custom elements so, if you’re building a design system with native web components, it’s easy to incorporate them inside your text-based documentation. If you’re working with React (or any other framework that speaks JSX, like Preact or Vue), you can do the same thing by using MDX.

This article is a broad overview of the tools available for writing documentation and for building style guides. Not all the tools listed here make use of MDX but it’s increasingly being incorporated into documentation tooling.

What is MDX?

A .mdx file has exactly the same syntax as a regular Markdown file, but lets you import interactive JSX components and embed them within your content. Support for Vue components is in alpha. It’s easy to get MDX set up with Create React App. There are MDX plugins for Next.js and Gatsby. The forthcoming version two release of Docusaurus will also come with built-in support.

Writing documentation with Docusaurus

Docusaurus is made by Facebook and used by every Facebook open source project, apart from React. It’s also used by many major open source projects outside of Facebook, including Redux, Prettier, Gulp and Babel.

Projects making use of Docusaurus.

You can use Docusaurus to document anything — it isn’t front-end specific. Docusaurus uses React under the hood, but you don’t have to know that framework to make use of it. It’ll take your Markdown files and turn them into a nicely-structured, well-formatted and readable documentation site, with a nice design right out of the box.

The Redux site shows the typical Docusaurus layout

Sites created with Docusaurus can also include a Markdown-based blog. Prism.js is included by default for zero-setup syntax highlighting. While relatively new, Docusaurus has proven popular, being voted the number one new tool of 2018 on StackShare.

Other options for written content

Docusaurus specifically caters to building documentation. Of course, there are a million and one ways to make a website — so you could roll your own solution with any back-end language, CMS, or static site generator.

The documentation sites for React, IBM’s design system, Apollo and Ghost CMS use Gatsby, for example — a generic static site generator often used for blogs. If you work with the Vue framework, VuePress is becoming a popular option. MkDocs is an open source static site generator for creating documentation, written in Python and configured with a single YAML file. GitBook is a popular paid product that’s free for open-source and non-profit teams. If you're building internal documentation and want something easy, the reading experience on GitHub itself isn’t half bad, so you could just commit some Markdown files and leave it at that.

Documenting components: Docz, Storybook and Styleguidist

Style guides, design systems, pattern libraries — whatever you want to call them — have become a hugely popular area of concern in the last decade. What’s really made the difference in turning them from vanity projects into useful tools isn’t the pontificating of thought leaders but the emergence of component-driven frameworks, like React, and the tools mentioned here.

Storybook, Docz and Styleguidist all do much the same thing: display interactive UI components and document their API. A project may have dozens or even hundreds of components to keep track of — all with a variety to states and styles. If you want components to be reused, people have to know that they exist. We aid discoverability when we catalog components. A style guide gives an easily searchable and scannable overview of all your UI components. This helps to maintain visual consistency and avoid duplicating work.

These tools provide a convenient way to review different states. It can be difficult to reproduce every state of a component in the context of a real application. Rather than needing to click through an actual app, developing a component in isolation can be helpful. Hard-to-reach states (like a loading state, for example) can be mocked.

Dan Green wrote a nice synopsis of the benefits of using Storybook, but it applies equally to Docz and Styleguidist:

"Storybook has made it really easy for designers who code to collaborate with engineers. By working in storybook they don't need to get a whole environment running (docker container, etc). For Wave, we have many important components that are only visible in the middle of a process that is short lived and time consuming to reproduce (i.e. a loading screen that only shows while a user is having their payment account set up). Before Storybook, we didn't have a good way to work on these components and were forced to temporary hacks in order to make them visible. Now, with Storybook we have an isolated place to easily work on them, which has the bonus feature of being easily accessible for designers and PMs. It also makes it really easy for us to show off these states in sprint demos."

- Dan Green, Wave Financial

As well as visualizing different states side-by-side and listing props, its often helpful to have written content about a component — whether its explaining the design rationale, use-cases, or describing the results of user-testing. Markdown is easy enough for *anybody* to learn — ideally a style guide should be a joint resource for designers and developers that both disciplines contribute to. Docz, Styleguidist and Storybook all offer a way to seamlessly intermingle Markdown with the components themselves.

Docz

Currently, Docz is a React-only project, but is working on support for Preact, Vue and web components. Docz is the newest of the three tools, but has already amounted over 14,000+ stars on GitHub. It is, to my mind, the easiest solution to work with. Docz provides two components — <Playground> and <Props>. These are imported and used directly in .mdx files.

import { Playground, Props } from "docz"; import Button from "../src/Button"; ## You can _write_ **markdown** ### You can import and use components <Button>click</Button>

You can wrap your own React components with <Playground> to create the equivalent of an embedded CodePen or CodeSandbox — a view of your component alongside editable code.

<Playground> <Button>click</Button> </Playground>

<Props> will show all the available props for a given React component, default values, and whether the prop is required.

<Props of={Button} />

I personally find this MDX-based approach the simplest to understand and the easiest to work with.

If you’re a fan of the React-based static-site generator Gatsby, Docz offers great integration.

Styleguidist

Just like with Docz, examples are written using Markdown syntax. Styleguidist uses Markdown code blocks (triple backticks) in regular .md files rather than MDX:

```js <Button onClick={() => console.log('clicked')>Push Me</Button> ```

Code blocks in Markdown usually just show the code. With Styleguidist, any code block with a language tag of js, jsx or javascript will be rendered as a React component along with the code. Just like with Docz, the code is editable — you can change props and instantly see the result.

Styleguidist will automatically create a table of props from either PropTypes, Flow or Typescript declarations.

Styleguidist currently supports React and Vue.

Storybook

Storybook markets itself as "a development environment for UI components." Rather than writing examples of components inside Markdown or MDX files, you write *stories* inside Javascript files. A *story* documents a particular state of a component. A component might have stories for a loading state and a disabled state, for example.

storiesOf('Button', module) .add('disabled', () => ( <Button disabled>lorem ipsum</Button> ))

Storybook is less straightforward to use than Styleguidist and Docz. At over 36,000 GitHub stars though, it’s the most popular option. It’s an open source project with 657 contributors and a full-time maintainer. It is used by, among others, Airbnb, Algolia, Atlassian, Lyft, and Salesforce. Storybook supports more frameworks than any other offering — React, React Native, Vue, Angular, Mithril, Ember, Riot, Svelte and plain HTML are all supported.

Writing documentation about components currently requires addons. In a future release, Storybook is taking inspiration from Docz and adopting MDX.

# Button Some _notes_ about your button written with **markdown syntax**. <Story name="disabled"> <Button disabled>lorem ipsum</Button> </Story>

Storybook’s new Docs feature is being rolled out incrementally over the next couple of months and looks set to be a big step forward.

Do you use @storybookjs for component docs or design systems? You're gonna love DocBlocks:
&#x1f4e6; Drop into MDX
&#x1f3d7; Modular and composable
&#x1f91d; Compatible w/ @gatsbyjs, #nextjs, etc

&#x1f51c; https://t.co/AmE4l9B3FU by @mshilman pic.twitter.com/Q48PQCmiEt

— Dominic Nguyen (@domyen) April 28, 2019

Wrapping up

The benefits of pattern libraries have been extolled at nauseating length in a million Medium articles. When done well, they aid visual consistency and facilitate the creation of cohesive products. Of course, none of these tools can magic up a design system. That takes careful thought about both design and CSS. But when it comes time to communicate that system to the rest of an organization, Docz, Storybook and Styleguidist are all great options.

The post Front-End Documentation, Style Guides and the Rise of MDX appeared first on CSS-Tricks.

The Browser Can Remember Edited Content

Css Tricks - Wed, 05/22/2019 - 4:32am

You can make the text inside any HTML element editable by adding the contenteditable attribute.

<div contenteditable> Hey, I'm like a textarea kinda now! </div>

I wouldn't say there are wheelbarrows full of use-cases for that, but it's neat. One possible use might be an in-progress design in which editing the content from the design itself is useful either for you, or for someone else (a client?) who needs to change the text.

So, great, contenteditable. Now someone can click into the text and edit it.

There is nothing permanent about those changes. Refresh the page, look in another browser or whatever. Those edits are gone.

Say you wanted to do a little better job and make the changes persistent. You aren't trying to build a CMS here, or save the data through an authenticated connection to a database or anything. You just wanna make the edits to the text are maintained if the page refreshes.

One way is to chuck the data from the text changes you make into localStorage.

  1. When text is edited (on blur of the element), save the data to localStorage using a namespace and the
    ID of the element as the key.
  2. When the page loads, look through localStorage and see if there are any keys that match elements on the page and, if so, replace the content.
const editables = document.querySelectorAll("[contenteditable]"); // save edits editables.forEach(el => { el.addEventListener("blur", () => { localStorage.setItem("dataStorage-" + el.id, el.innerHTML); }) }); // once on load for (var key in localStorage) { if (key.includes("dataStorage-")) { const id = key.replace("dataStorage-",""); document.querySelector("#" + id).innerHTML = localStorage.getItem(key); } }

See the Pen
localStorage + contenteditable
by Chris Coyier (@chriscoyier)
on CodePen.

This reminds me of a few other things...

  • document.designMode = "on" is like a shortcut for making every element on the page behave like it has contenteditable.
  • Mavo is a little bit like this concept only with authentication, true data storage options, and editing UI.
  • If performance is a concern, KV storage is supposed to be a speeder async version of localStorage.

The post The Browser Can Remember Edited Content appeared first on CSS-Tricks.

Getting Started with React Testing Library

Css Tricks - Wed, 05/22/2019 - 4:19am

I can guess what you are thinking: another React testing library? So many have already been covered here on CSS-Tricks (heck, I’ve already posted one covering Jest and Enzyme) so aren’t there already enough options to go around?

But react-testing-library is not just another testing library. It’s a testing library, yes, but one that’s built with one fundamental principle that separates it from the rest.

The more your tests resemble the way your software is used, the more confidence they can give you.

It tries to address tests for how a user will use your application. In fact, it’s done in such a way that tests won’t break even when you refactor components. And I know that’s something we’ve all run into at some point in our React journey.

We’re going to spend some time writing tests together using react-testing-library for a light to-do application I built. You can clone the repo locally:

git clone https://github.com/kinsomicrote/todoapp-test.git

And, if you do that, install the required packages next:

## yarn yarn add --dev react-testing-library jest-dom ## npm npm install --save-dev react-testing-library jest-dom

In case you’re wondering why Jest is in there, we’re using it for assertion. Create a folder called __test__ inside the src directory and create a new file called App.test.js.

Taking snapshots

Snapshot tests keep a record of tests that have been performed on a tested component as a way to visually see what’s changes between changes.

When we first run this test, we take the first snapshot of how the component looks. As such, the first test is bound to pass because, well, there’s no other snapshot to compare it to that would indicate something failed. It only fails when we make a new change to the component by adding a new element, class, component, or text. Adding something that was not there when the snapshot was either created or last updated.

The snapshot test will be the first test we will be writing here. Let’s open the App.test.js file and make it look like this:

import React from 'react'; import { render, cleanup } from "react-testing-library"; import "jest-dom/extend-expect"; import App from './App'; afterEach(cleanup); it("matches snapshot", () => { const { asFragment } = render(<App />); expect(asFragment()).toMatchSnapshot(); });

This imports the necessary packages we are using to write and run the tests. render is used to display the component we want to test. We make use of cleanup to clear things out after each test runs — as you can see with the afterEach(cleanup) line.

Using asFragment, we get a DocumentFragment of the rendered component. Then we expect it to match the snapshot that had been created.

Let’s run the test to see what happens:

## yarn yarn test ## npm npm test

As we now know, a snapshot of the component gets created in a new folder called __snapshots__ inside the __tests__ directory if this is our first test. We actually get a file called App.test.js.snap in there that will look like this:

// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`matches snapshot 1`] = ` <DocumentFragment> <div class="container" > <div class="row" > <div class="col-md-6" > <h2> Add Todo </h2> </div> </div> <form> <div class="row" > <div class="col-md-6" > <input class="form-control" data-testid="todo-input" placeholder="Enter a task" type="text" value="" /> </div> </div> <div class="row" > <div class="col-md-6" > <button class="btn btn-primary" data-testid="add-task" type="submit" > Add Task </button> </div> </div> </form> <div class="row todo-list" > <div class="col-md-6" > <h3> Lists </h3> <ul data-testid="todos-ul" > <li> <div> Buy Milk <button class="btn btn-danger" > X </button> </div> </li> <li> <div> Write tutorial <button class="btn btn-danger" > X </button> </div> </li> </ul> </div> </div> </div> </DocumentFragment> `; Now, let’s Test DOM elements and events

Our app includes two to-do items that display by default the first time the app runs. We want to make sure that they do, in fact, show up by default on the first app run so, to test this, we have to target the unordered list (<ul>) and check the length. We expect the length to be equal to two — the number of items.

it('it displays default todo items', () => { const { getByTestId } = render(<App />); const todoList = getByTestId('todos-ul'); expect(todoList.children.length).toBe(2); });

We’re making use of getByTestId in that snippet to extract the test IDs from the App component. We then set todoList to target the todos-ul element. That’s what should return as two.

Using what we’ve learned so far, see if you can write a test to assert that a user can enter values in the input field. Here are the things you’ll want to do:

  • Get the input field
  • Set a value for the input field
  • Trigger a change event
  • Assert that the input field has its value as the one you set for it in Step 2

Don’t peek at my answer below! Take as much time as you need.

Still going? Great! I’ll go grab some coffee and be right back.

Mmm, coffee. ☕️

Oh, you’re done! You rock. Let’s compare answers. Mine looks like this:

it('allows input', () => { const {getByTestId } = render(<App />) let item = 'Learn React' const todoInputElement = getByTestId('todo-input'); todoInputElement.value = item; fireEvent.change(todoInputElement); expect(todoInputElement.value).toBe('Learn React') });

Using getByTestId, I am able to extract the test IDs in the application. Then I create a variable which is set to the string Learn React, and make it the value of the input field. Next, I obtain the input field using its test ID and fire the change event after setting the value of the input field. With that done, I assert that the value of the input field is indeed Learn React.

Does that check out with your answer? Leave a comment if you have another way of going about it!

Next, let’s test that we can add a new to-do item. We’ll need to get the input field, the button for adding new items and the unordered list because those are all of the elements needed to create an new item.

We set a value for the input field and then trigger a button click to add the task. We’re able to do this by obtaining the button using getByText — by triggering a click event on the DOM element with the text Add Task, we should be able to add a new to-do item.

Let’s assert that the number of children (list items) in unordered list element is equal to three. This assumes that the default tasks are still in tact.

it('adds a new todo item', () => { const { getByText, getByTestId } = render(<App />); const todoInputElement = getByTestId('todo-input'); const todoList = getByTestId('todos-ul'); todoInputElement.value = 'Learn React'; fireEvent.change(todoInputElement); fireEvent.click(getByText('Add Task')) expect(todoList.children.length).toBe(3); });

Pretty nice, right?

This is just one way to test in React

You can try react-testing-library in your next React application. The documentation in the repo is super thorough and — like most tools — the best place to start. Kent C. Dodds built it and has a full course on testing over at Frontend Masters (subscription required) that also covers the ins and outs of react-testing-library.

That said, this is just one testing resource for React. There are others, of course, but hopefully this is one you’re interested in trying out now that you’ve seen a bit of it but use what’s best for your project, of course.

The post Getting Started with React Testing Library appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.