Month: August 2019

Weekly Platform News: CSS font-style: oblique, webhin browser extension, CSS Modules V1

In this week’s roundup, variable fonts get oblique, a new browser extension for linting, and the very first version of CSS Modules.

Use font-style: oblique on variable fonts

Some popular variable fonts have a 'wght' (weight) axis for displaying text at different font weights and a 'slnt' (slant) axis for displaying slanted text. This enables creating many font styles using a single variable font file (e.g., see the “Variable Web Typography” demo page).

You can use font-style: oblique instead of the lower-level font-variation-settings property to display slanted text in variable fonts that have a 'slnt' axis. This approach works in Chrome, Safari, and Firefox.

/* BEFORE */ h2 {   font-variation-settings: "wght" 500, "slnt" 4; }  /* AFTER */ h2 {   font-weight: 500;   font-style: oblique 4deg; }

See the Pen
Using font-style: oblique on variable fonts
by Šime Vidas (@simevidas)
on CodePen.

The new webhint browser extension

The webhint linting tool is now available as a browser devtools extension for Chrome, Edge, and Firefox (read Microsoft’s announcement). Compared to Lighthouse, one distinguishing feature of webhint are its cross-browser compatibility hints.

In other news…

  • CSS Modules V1 is a new proposal from Microsoft that would extend the JavaScript modules infrastructure to allow importing a CSSStyleSheet object from a CSS file (e.g., import styles from "styles.css";) (via Thomas Steiner)
  • Web apps installed in the desktop version of Chrome can be uninstalled on the about:apps page (right-click on an app’s icon to reveal the Remove... option) (via Techdows)
  • Because of AMP’s unique requirements, larger news sites such as The Guardian should optimally have two separate codebases (one for the AMP pages and one for the regular website) (via The Guardian)

Read more news in my new, weekly Sunday issue. Visit webplatform.news for more information.

The post Weekly Platform News: CSS font-style: oblique, webhin browser extension, CSS Modules V1 appeared first on CSS-Tricks.

CSS-Tricks

, , , , , , , ,

Get the Best Domain Name for your New Website

(This is a sponsored post.)

If you’re on CSS-Tricks, we can probably bet that you’re in the process of building a really cool website. You’ve spent your time creating content, applying appropriate UX design techniques, coding it to perfection, and now you’re about ready to launch it to the world.

A great website deserves a domain name that represents all that you’ve built. With Hover, you have the flexibility to choose a domain name that truly reflects that. We offer not only the go-to domain name extensions, like .com and .org, or the familiar country code domain extensions, like .uk or .us, or .ca, but also the more niche extensions. We have .dev for developers, .design for designers, and .dog for your dog (yes, really!).

We have hundreds of domain names to choose from and all eligible domains come with free Whois privacy protection. We’re proud of the modern UX/UI and fabulous customer service we offer our customers. Find your next domain name with Hover!

Get Started

Direct Link to ArticlePermalink

The post Get the Best Domain Name for your New Website appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Design Principles for Developers: Processes and CSS Tips for Better Web Design

It is technically true that anyone can cook. But there’s a difference between actually knowing how to prepare a delicious meal and hoping for the best as you throw a few ingredients in a pot. Just like web development, you might know the ingredients—<span>, background-color, .heading-1—but not everyone knows how to turn those ingredients into a beautiful, easy-to-use website.

Whenever you use HTML and CSS, you are designing—giving form and structure to content so it can be understood by someone else. People have been designing for centuries and have developed principles along the way that are applicable to digital interfaces today. These principles manifest in three key areas: how words are displayed (typography), how content is arranged (spacing), and how personalty is added (color). Let’s discover how to use each of these web design ingredients through the mindset of a developer with CSS properties and guidelines to take the guesswork out of web design.

Table of Contents

Typography

Websites that are easy to read don’t happen by mistake. In fact, Taimur Abdaal wrote an entire article on the topic that’s chock-full of advice for developers working with type. We’re going to focus specifically on two fundamental principles of design that can help you display words in a more visually pleasing and easy-to-read way: repetition and hierarchy.

Use repetition for consistency and maintainability

Repetition comes fairly naturally on the web thanks to the importance of reusability in software. For example, CSS classes allow you to define a particular style for text and then reuse that style across the site. This results in repeating, consistent text styles for similar content which helps users navigate the site.

If, for example, you are working on styles for a new paragraph, first consider if there is existing content that has a similar style and try to use the same CSS class. If not, you can create a new class with a generic name that can be repeated elsewhere in your site. Think .paragraph--emphasize as opposed to .footer__paragraph--emphasize or .heading-1 as opposed to .hero__site-title. The first examples can be used across your site as opposed to the second which are scoped to specific components. You can even add a prefix like text- to indicate that the class is used specifically for text styles. This method will reduce the CSS file size and complexity while making it much easier to update global styles in the future.

Left: The black text is similar but uses a slightly different font size and line height. Right: The black text uses the same styles and therefore can use the same CSS class. Reducing the amount of CSS needed and adding repetition and consistency.

In design, there are endless ways to experiment with styles. Designers can sometimes go a little crazy with their font styles by creating numerous slight variations of similar styles. However, in code, it’s valuable to restrict text styles to a minimum. Developers should urge designers to combine similar styles in order to reduce code weight and increase reusability and consistency.

These headings look very similar but are slightly different and would require three separate CSS classes to style them. They could probably be combined into one and styled with a single class.

Hierarchy provides a clear visual order to content

Hierarchy is something you really only notice when it’s not there. In typography, hierarchy refers to the visual difference between various pieces of text. It’s the distinction between headings, paragraphs, links, and other text styles. This distinction is made by choosing different fonts, colors, size, capitalization, and other properties for each type of text content. Good hierarchy makes complex information easier to digest and guides users through your content.

Left: Poor hierarchy. There’s not much differentiation in the size or color of the text to help users digest the content. Right: Better hierarchy that uses more variety in font size, color, and spacing to help users quickly navigate the content.

Out of the box, HTML provides some hierarchy (like how the font size of headings gets smaller as you go from <h1> to <h6>), but CSS opens the door for even more creativity. By giving <h1> tags an even larger font size, you can quickly establish greater difference in size between heading levels—and therefore more hierarchy. To create more variety, you can also change the color, text-align, and text-transform properties.

A comparison of the way HTML headings look without styles versus adding more contrast with CSS.

A note on choosing fonts

With typography, we need to make sure it is as easy to read as possible. The greatest overall factor in readability is the font you choose—which is a huge topic. There are many factors that determine how “readable” a font is. Some fonts are made specifically to be used as headings or short lines of text; these are called “display” fonts, and they often have more personality than fonts designed to be used for text. Unique flourishes and quirks make display fonts harder to read at small sizes and when part of a large paragraph. As a rule of thumb, use a more straightforward font for text and only use display fonts for headings.

Left: Examples of display fonts that work better as headings. Right: Examples of text fonts that are more readable and can be used for headings, paragraphs, and any other text that needs to be easy to read.

If you’re in a pinch and need a readable font, try Google Fonts. Add a paragraph of text to the preview field and size it roughly how it will display on your website. You can then narrow down your results to serif or sans-serif and scan the list of fonts for one that is easy to read. Roboto, Noto Sans, Merriweather, and PT Serif are all very readable options.

CSS properties for better readability

  • The main paragraph font-size should be between 16pxand 18px (1em and 1.25em) depending on the font you choose.
  • Manually set line-height (the vertical space between two lines of text) to make your text less cramped and easier to read. Start with line-height: 1.25 (that is 1.25 times the font-size) for headings and at least 1.5 for paragraphs (but no more than 1.9) and adjust from there. The longer the line of text, the larger the line-height should be. To keep your text flexible, avoid adding a unit to your line-height. Without a unit the line-height you set will be proportional to your font-size. For example, line-height: 1.5 and font-size: 18px would give you a line height of 27 pixels. If you changed your font size to font-size: 16px on smaller screens, the computed line height would then change to 24 pixels automatically.
Left: line-height is 1.1 for the heading and 1.2 for the paragraph, which is roughly the default setting. Right: line-height is 1.25 for the headings and 1.5 for the paragraph.
  • Pay attention to how many characters are in a line of text and aim for 45 and 75 characters long (including punctuation and spaces). Doing so reduces reading fatigue for your users by limiting the eye and head movement needed to follow a line of text. With the variable nature of the web, it’s impossible to completely control line length, but you can use max-width values and breakpoints to prevent lines of text from getting too long. Generally speaking, the shorter the line of text, the faster it will be to scan for quick reading. And don’t worry too much about counting the characters in every line. Once you do it a few times, you’ll develop a sense for what looks right.
Top: line length of around 125 characters. Bottom: line length of around 60 characters.

Spacing

After looking at typography, you can take a step back and examine the layout, or spacing, of your content. Movement and proximity are two design principles that relate to spacing.

Movement is about content flow

Movement refers to how your eye moves through the page or the flow of the page. You can use movement to direct a user’s eye in order to tell a story, point to a main action item, or encourage them to scroll. This is done by structuring the content within individual components and then arranging those components to form the layout of the page. By paying attention to how your eye moves through content, you can help users know where to look as they scan the page.

Unlike books, which tend to have very linear structure, websites can be more creative with their layout—in literally endless ways. It is important to make sure you are intentional with how you layout content and do so in a way which guides users through your content as easily as possible.

Three potential ways to arrange a heading, image, and button.

Consider these three examples above. Which is the easiest to follow? The arrangement on the left draws your eye off the screen to the left due to how the image is positioned which makes it hard to find the button. In the center option, it’s easy to skip over the headline because the image is too large in comparison. On the right, the heading draws your attention first and the image is composed so that it points to the main action item—the button.

White space is a helpful tool for creating strong movement, but it’s easy to use too much or too little. Think about how you are using it to direct the user’s eye and divide your content. When used well, users won’t notice the whitespace itself but will be able to better focus on the content you are presenting. For example, you can use whitespace to separate content (instead of a colored box) which results in a less cluttered layout.

Left: Using a graphic element to separate content and aligning images in the center. Right: Using whitespace to separate content and aligning images on the left to let the whitespace flow better around groups of related content and create a cleaner layout.

Proximity establishes relationships

When objects are closer together, they are perceived as being related. By controlling spacing around elements, you can imply relationships between them. It can be helpful to create a system for spacing to help build consistency through repetition and avoid the use of random numbers. This system is based off the default browser font size (1rem or 16px) and uses distinct values that cover most scenarios:

  • 0.25rem (4px)
  • 0.5rem (8px)
  • 1rem (16px)
  • 2rem (32px)
  • 4rem (64px)

You can use Sass or CSS variables so that the values are kept consistent across the project. A system might look like this—but use whatever you’re comfortable with because naming things is hard:

  • $ space-sm
  • $ space-med
  • $ space-lg
  • $ space-xl
  • $ space-xxl
Left: A component with uneven spacing between elements. Right: A component that uses consistent spacing.

Color conveys personality and calls attention

Color greatly affects a website’s personality. When used well, it gives pages life and emotion; used poorly, it can distract from the content, or worse, make it inaccessible. Color goes hand in hand with most design principles. It can be used to create movement by directing users’ eyes and can be used to create emphasis by calling attention to the most important action items.

A note on choosing colors

With color, it can be hard to know where to start. To help, you can use a four-step process to guide your color choices and build a color palette for the site.

Step 1: Know your mood

You have to know the mood or attitude of your site and brand before choosing colors. Look at your content and decide what you are trying to communicate. Is it funny, informative, retro, loud, somber? Typically, you can boil down the mood of your site to a few adjectives. For example, you might summarize The North Face as adventurous and rugged while Apple would be minimalistic and beautiful.

Step 2: Find your main color

With your mood in mind, try to visualize a color that represents it. Start with the color’s saturation (how intense the color is) and brightness (how close the color is to white or black). If your mood is upbeat or flashy, a lighter (more saturated) color is probably best. If your mood is serious or reserved, a darker (less saturated) color is better.

Next, choose a hue. Hue refers to what most people think of as colors—where does is fall on the rotation of the color wheel? The hue of a color is what gives it the most meaning. People tend to associate hues with certain ideas. For instance, red is often associated with power or danger and green relates to money or nature. It can be helpful to look at similar websites or brands to see what colors they use—although you don’t need to follow their lead. Don’t be afraid to experiment!

Color wheel showing saturation and brightness versus hue.
Step 3: Add supporting colors

Sometimes, two or three main colors are needed, but this is not necessary. Think about the colors of different brands. Some use a single color, and others have a main color and one or two that support it. Coca-Cola uses its distinct red. IKEA is mostly blue with some yellow. Tide is orange with some blue and yellow. Depending on your site’s mood, you might need a few colors. Try using a tool like Adobe Color or Coolors), both of which allow you to add a main color and then try different color relationships, like complementary or monochromatic, to quickly see if any work well.

Step 4: Expand your palette

Now that you’ve narrowed things down and found your main color(s), it’s time to expand your scope with a palette that gives your project versatility and constraint—here’s a methodology I’ve found helpful. Tints and shades are the trick here. Tints are made by mixing your main color(s) with white, and shades are made by mixing with black. You can quickly create an organized system with Sass color functions:

$ main-color:          #9AE799;  $ main-color-lightest: lighten($ main-color, 20%); $ main-color-lighter:  lighten($ main-color, 15%); $ main-color-light:    lighten($ main-color, 10%);  $ main-color-dark:     darken($ main-color, 40%); $ main-color-darker:   darken($ main-color, 50%); $ main-color-darkest:  darken($ main-color, 60%);
A palette of color options created with Sass color functions. Make sure to use percent values for the functions that create distinct colors—not too similar to the main color.

To round out your palette, you’ll need a few more colors, like a white and black. Try creating a “rich black” using a dark, almost black shade of your main color and, on the other end of the spectrum, pick a few light grays that are tinted with your main color. Tinting the white and black adds a little more personality to your page and helps create a cohesive look and feel.

Top: Basic white, gray, and black. Bottom: Tinted white, grays, and black to match the main color.

Last but not least, if you are working on an interactive product, you should add colors for success, warning, and error states. Typically a green, yellow, and red work for these but consider how you can adjust the hue to make them fit better with your palette. For example, if your mood is friendly and your base color is green, you might want to desaturate the error state colors to make the red feel less negative.

You can do this with the mix Sass color function by giving it your base color, the default error color, and the percentage of base color that you want to mix in with the error color. Adding desaturate functions helps tone down the colors:

$ success: mix($ base-color, desaturate(green, 50%), 50%); $ warning: mix($ base-color, desaturate(yellow, 30%), 5%); $ error:   mix($ base-color, desaturate(red, 50%), 20%);
Top: Default colors for success, warning, and error states. Bottom: Tinted and desaturated colors for the success, warning and error states.

When it comes to the web, there’s one color principle that you have to pay extra attention to: contrast. That’s what we’ll cover next.

Contrast

Color contrast—the difference in saturation, brightness, and hue between two colors—is an important design principle for ensuring the web is accessible to those with low vision or color blindness. By ensuring there is enough contrast between your text and whatever is behind it on your site will be more accessible for all sighted users. When looking at accessibility, be sure to follow the color contrast guidelines provided by W3C’s Web Content Accessibility Guidelines (WCAG). There are many tools that can help you follow these guidelines, including the inspect panel in Chrome’s dev tools.

By clicking on the color property in the Chrome Inspect tool, you can see the contrast ratio and whether it is passing.

Now, it’s time to put these principles to practice! You can use these processes and CSS tips to help take the guesswork out of design and create better solutions. Start with what you are familiar with, and eventually, the design principles mentioned here will become second nature.

If you’re looking for even more practical tips, Adam Wathan and Steve Schoger wrote about some of their favorites.

The post Design Principles for Developers: Processes and CSS Tips for Better Web Design appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,
[Top]

10 Best UX Design Podcasts for Beginners

[Top]

8 Platforms to Find Project Jobs for Designers

[Top]

Using Immer for React State Management

We make use of state to keep track of application data. States change as users interact with an application. When this happens, we need to update the state that is displayed to the user, and we do this using React’s setState.

Since states are not meant to be updated directly (because React’s state has to be immutable), things can get really complicated as states become more complex. They become difficult to understand and follow.

This is where Immer comes in and that’s what we’re going to look at in this post. Using Immer, states can be simplified and much easier to follow. Immer makes use of something called “draft” which you can think of as the copy of your state, but not the state itself. It’s as though Immer hit CMD+C on the state and then cmd+V’d it somewhere else where it can be safely viewed without disturbing the original copy. Any updates you need to make happen on the draft, and the parts of the current state that change on the draft is updated.

Let’s say your application’s state looks like this;

this.state = {   name: 'Kunle',   age: 30,   city: 'Lagos,   country: 'Nigeria' }

This user happens to be celebrating his 31st birthday and which means we need to update the age value. With Immer running behind the scenes, a replica of this state will be made.

Now imagine the replica is made and handed over to a messenger, who gives the newly copied version of the state to Kunle. It means there are now two copies available — the current state and the draft copy that was handed over. Kunle then changes the age on the draft to 31. The messenger then returns to the application with the draft, compares both versions, and only updates the age since that’s the only part of the draft that changed.

It does not break the idea of an immutable state, as the current state does not get updated directly. Immer basically makes it convenient to work with immutable state.

Let’s look at an example of this at work

Say you want to build a traffic light for your community, you can give it a shot using Immer for your state updates.

See the Pen
Traffic Light Example with Reactjs
by CarterTsai (@CarterTsai)
on CodePen.

Using Immer, the component will look like this:

const {produce} = immer  class App extends React.Component {   state = {     red: 'red',      yellow: 'black',      green: 'black',     next: "yellow"   }    componentDidMount() {     this.interval = setInterval(() => this.changeHandle(), 3000);   }      componentWillUnmount()  {     clearInterval(this.interval);   }    handleRedLight = () => {     this.setState(       produce(draft => {         draft.red = 'red';         draft.yellow = 'black';         draft.green = 'black';         draft.next = 'yellow'       })     )   }      handleYellowLight = () => {     this.setState(       produce(draft => {         draft.red = 'black';         draft.yellow = 'yellow';         draft.green = 'black';         draft.next = 'green'       })     )   }      handleGreenLight = () => {     this.setState(       produce(draft => {         draft.red = 'black';         draft.yellow = 'black';         draft.green = 'green';         draft.next = 'red'       })     )   }    changeHandle = () => {     if (this.state.next === 'yellow') {       this.handleYellowLight()     } else if (this.state.next === 'green') {       this.handleGreenLight()     } else {       this.handleRedLight()     }        }    render() {     return (       <div className="box">         <div className="circle" style={{backgroundColor: this.state.red}}></div>         <div className="circle" style={{backgroundColor: this.state.yellow}}></div>         <div className="circle" style={{backgroundColor: this.state.green}}></div>       </div>   ); } };

produce is the default function we get from Immer. Here, we pass it as a value to the setState() method. The produce function takes a function which accepts draft as an argument. It is inside this function that we can then set the draft copy with which we want to update our state.

If that looks complicated, there is another way to write this. First, we create a function.

const handleLight = (state) => {   return produce(state, (draft) => {     draft.red = 'black';     draft.yellow = 'black';     draft.green = 'green';     draft.next = 'red'   }); }

We are passing the current state of the application, and the function which accepts draft as arguments to the produce function. To make use of this inside our component, we do this;

handleGreenLight = () => {   const nextState = handleLight(this.state)   this.setState(nextState) }

Another example: A shopping list

If you have been working with React for a while now, then you’re not a stranger to the spread operator. With Immer, you need not make use of the spread operator, especially when working with an array in your state.

Let’s explore that a little further by creating a shopping list application.

See the Pen
immer 2 – shopping list
by Kingsley Silas Chijioke (@kinsomicrote)
on CodePen.

Here’s the component we’re working with:

class App extends React.Component {   constructor(props) {       super(props)              this.state = {         item: "",         price: 0,         list: [           { id: 1, name: "Cereals", price: 12 },           { id: 2, name: "Rice", price: 10 }         ]       }     }      handleInputChange = e => {       this.setState(       produce(draft => {         draft[event.target.name] = event.target.value       }))     }      handleSubmit = (e) => {       e.preventDefault()       const newItem = {         id: uuid.v4(),         name: this.state.name,         price: this.state.price       }       this.setState(         produce(draft => {           draft.list = draft.list.concat(newItem)         })       )     };    render() {     return (       <React.Fragment>         <section className="section">           <div className="box">             <form onSubmit={this.handleSubmit}>               <h2>Create your shopping list</h2>               <div>                 <input                   type="text"                   placeholder="Item's Name"                   onChange={this.handleInputChange}                   name="name"                   className="input"                   />               </div>               <div>                 <input                   type="number"                   placeholder="Item's Price"                   onChange={this.handleInputChange}                   name="price"                   className="input"                   />               </div>               <button className="button is-grey">Submit</button>             </form>           </div>                      <div className="box">             {               this.state.list.length ? (                 this.state.list.map(item => (                   <ul>                     <li key={item.id}>                       <p>{item.name}</p>                       <p>$  {item.price}</p>                     </li>                     <hr />                   </ul>                 ))               ) : <p>Your list is empty</p>             }           </div>         </section>       </React.Fragment>     )   } }  ReactDOM.render(   <App />,   document.getElementById('root') );

As items are added to the list, we need to update the state of the list to reflect those new items. To update the state of list using setState(), we’ll have to do this:

handleSubmit = (e) => {   e.preventDefault()   const newItem = {     id: uuid.v4(),     name: this.state.name,     price: this.state.price   }   this.setState({ list: [...this.state.list, newItem] }) };

If you have to update multiple states in the application, you’ll have to do a ton of spreading to create a new state using the old state and the additional value. Which can look more complex as the number of changes increases. With Immer, it becomes very easy to do that, as we did in the example above.

What if we want to add a function that gets called as a callback after the state update?In this case, let’s say we are keeping a tally of the number of items in the list and the total price of all the items.

See the Pen
immer 3 – shopping list
by Kingsley Silas Chijioke (@kinsomicrote)
on CodePen.

Say we want to calculate the amount that will be spent based on the price of items in the list, we can have the handleSubmit function look like this:

handleSubmit = (e) => {   e.preventDefault()   const newItem = {     id: uuid.v4(),     name: this.state.name,     price: this.state.price   }      this.setState(     produce(draft => {       draft.list = draft.list.concat(newItem)     }), () => {       this.calculateAmount(this.state.list)     }   ) };

First, we create an object using the data entered by the user, which we then assign to newItem. To update our application’s state, we make use of .concat() which will return a new array that’s comprised of the previous items and the new item. This updated copy is now set as the value of draft.list, which can then be used by Immer to update the state of the application.

The callback function gets called after the state update. It’s important to note that it makes use of the updated state.

The function we want to call will look like this:

calculateAmount = (list) => {   let total = 0;     for (let i = 0; i < list.length; i++) {       total += parseInt(list[i].price, 10)     }   this.setState(     produce(draft => {       draft.totalAmount = total     })   ) }

Let’s look at Immer hooks

use-immer is a hook that allows you to manage state in your React application. Let’s see this in action using a classic counter example.

import React from "react"; import {useImmer} from "use-immer";  const Counter = () => {   const [count, updateCounter] = useImmer({     value: 0   });    function increment() {     updateCounter(draft => {       draft.value = draft.value +1;     });   }    return (     <div>       <h1>         Counter {count.value}       </h1>       <br />       <button onClick={increment}>Increment</button>     </div>   ); }  export default Counter;

useImmer is similar to useState. The function returns the state and an updater function. When the component loads at first, the value of the state (which is count in this example), is the same as the value passed to useImmer. Using the updater function which is returned, we can then create an increment function to increase the value of the count.

There is also a useReducer-like hook for Immer.

import React, { useRef } from "react"; import {useImmerReducer } from "use-immer"; import uuidv4 from "uuid/v4" const initialState = []; const reducer = (draft, action) => {   switch (action.type) {     case "ADD_ITEM":       draft.push(action.item);       return;     case "CLEAR_LIST":       return initialState;     default:       return draft;   } } const Todo = () => {   const inputEl = useRef(null);   const [state, dispatch] = useImmerReducer(reducer, initialState);      const handleSubmit = (e) => {     e.preventDefault()     const newItem = {       id: uuidv4(),       text: inputEl.current.value     };     dispatch({ type: "ADD_ITEM", item: newItem });     inputEl.current.value = "";     inputEl.current.focus();   }      const handleClear = () => {     dispatch({ type: 'CLEAR_LIST' })   }      return (     <div className='App'>       <header className='App-header'>         <ul>           {state.map(todo => {             return <li key={todo.id}>{todo.text}</li>;           })}         </ul>         <form onSubmit={handleSubmit}>           <input type='text' ref={inputEl} />           <button             type='submit'           >             Add Todo           </button>         </form>         <button           onClick={handleClear}         >           Clear Todos         </button>       </header>     </div>   ); } export default Todo;

useImmerReducer takes in a reducer function and the initial state, and it returns both state and the dispatch function. We can then loop through the state to display the items we have. We dispatch an action when submitting a todo item and clearing the list of them. The dispatched action has a type which we use in determining what to do in the reducer function.
In the reducer function, we make use of draft like we did before, instead of state. With that, we have a convenient way of manipulating the state of our application.

You can find the code used in the above example on GitHub.

That’s a look at Immer!

Going forward, you can begin to make use of Immer in your next project, or even slowly begin to use it in the current project you’re working on. It has proven to aid in making state management convenient.

The post Using Immer for React State Management appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Quick Gulp Cache Busting

You should for sure be setting far-out cache headers on your assets like CSS and JavaScript (and images and fonts and whatever else). That tells the browser “hang on to this file basically forever.” That way, when navigating from page to page on a site — or revisiting it, or refreshing the page — the browser doesn’t have to download it again which produces way faster page loads. It’s massively important for web performance, so do it!

But how do you force the browser to get a fresh version of the file? Well, there are a bunch of ways. Check out that blog post for more. But here’s one that I’ve used just recently that I wanted to document.

The trick is to change the query string

There was an era where the prevailing wisdom was that changing the query string wasn’t enough, but even then it, the reasons it wouldn’t work were pretty much edge cases. These days, changing the query string is fine (assuming you don’t change the default behavior, services like Cloudflare let you do it).

So, one day you ship it like this in your HTML:

<link rel="stylesheet" href="style.css?v=1" />

Then you change that query string to break the cache when you need to:

<link rel="stylesheet" href="style.css?v=2" />

The HTML, by the way, is either not cached or cached for a much shorter amount of time, so changes to HTML will be seen.

I sometimes do it by hand

For many years, I busted cache on this very site by setting a PHP variable and using it to break assets, like…

<?php $  ver = 1.0; ?>  <link rel="stylesheet" href="style.css?v=<?php echo $  ver; ?>" /> <link rel="stylesheet" href="some-other-asset.css?v=<?php echo $  ver; ?>" />

Hey that works, but it was me hand-manipulating that variable. I would sometimes forget to do it, and even if I did remember, I sort of resented having to do it.

Automating version busting with Gulp

I’m using a Gulp-powered build process at the moment on this site, which does all the classic stuff: Sass, Babel, file concatenation, live reloading…

It occurred to me I might as well have Gulp do the query-string changing whenever changes are made to CSS or JavaScript. JavaScript has a .replace() method, and that’s available in Node/Gulp easily with the gulp-replace plugin.

I make a task. When I call it, it looks in my header filer for the string cache_bust= plus some value, and replaces it with a new randomized string based on the date and time.

gulp.task("cache-bust-css", function() {   var cbString = new Date().getTime();   return gulp     .src(["header.php"])     .pipe(       replace(/cache_bust=\d+/g, function() {         return "cache_bust=" + cbString;       })     )     .pipe(gulp.dest(".")); });

I do the same thing in a separate task when JavaScript files are editing and compiled.

It’s still a little dumb

Notice that I’m changing the query string on all the CSS assets every time any of them changes. That’s not as efficient as it could be. I should probably be changing the query string only on the changed files.

I’ll get to it eventually. Sometimes you just gotta baby-step your way to better solutions over time.


This is just one way! There are other Gulp plugins just for this. Other build systems have different approaches. This approached happened to work well for me and my exact needs at the time. Feel free to share your strategy!

The post Quick Gulp Cache Busting appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Let’s Give Grunt Tasks the Marie Kondo Organization Treatment

We live in an era of webpack and npm scripts. Good or bad, they took the lead for bundling and task running, along with bits of Rollup, JSPM and Gulp. But let’s face it. Some of your older projects are still using good ol’ Grunt. While it no longer glimmers as brightly, it does the job well so there’s little reason to touch it.

Though, from time to time, you wonder if there’s a way to make those projects better, right? Then start from “Organizing Your Grunt Tasks” article and come back. I’ll wait. That’ll set the stage for this post and then we’ll take it further together to create a solid organization of Grunt tasks.

Automatic Speed Daemon task loading

It’s no fun writing loading declarations for each task, like this:

grunt.loadNpmTasks('grunt-contrib-clean') grunt.loadNpmTasks('grunt-contrib-watch') grunt.loadNpmTasks('grunt-csso') grunt.loadNpmTasks('grunt-postcss') grunt.loadNpmTasks('grunt-sass') grunt.loadNpmTasks('grunt-uncss')  grunt.initConfig({})

It’s common to use load-grunt-tasks to load all tasks automatically instead. But what if I tell you there is a faster way?

Try jit-grunt! Similar to load-grunt-tasks, but even faster than native grunt.loadNpmTasks.

The difference can be striking, especially in projects with large codebases.

Without jit-grunt

loading tasks     5.7s  ▇▇▇▇▇▇▇▇ 84% assemble:compile  1.1s  ▇▇ 16% Total 6.8s

With jit-grunt

loading tasks     111ms  ▇ 8% loading assemble  221ms  ▇▇ 16% assemble:compile   1.1s  ▇▇▇▇▇▇▇▇ 77% Total 1.4s

1.4 seconds doesn’t really make it a Speed Daemon… so I kinda lied. But still, it’s six times faster than the traditional way! If you’re curious how that’s possible, read about the original issue which led to the creation of jit-grunt.

How is jit-grunt used? First, install:

npm install jit-grunt --save

Then replace all tasks load statements with a single line:

module.exports = function (grunt) {   // Intead of this:   // grunt.loadNpmTasks('grunt-contrib-clean')   // grunt.loadNpmTasks('grunt-contrib-watch')   // grunt.loadNpmTasks('grunt-csso')   // grunt.loadNpmTasks('grunt-postcss')   // grunt.loadNpmTasks('grunt-sass')   // grunt.loadNpmTasks('grunt-uncss')    // Or instead of this, if you've used `load-grunt-tasks`   // require('load-grunt-tasks')(grunt, {   //   scope: ['devDependencies', 'dependencies']    // })    // Use this:   require('jit-grunt')(grunt)    grunt.initConfig({}) }

Done!

Better configs loading

In the last example, we told Grunt how to load tasks itself, but we didn’t quite finish the job. As “Organizing Your Grunt Tasks” suggests, one of the most useful things we’re trying to do here is split up a monolithic Gruntfile into smaller standalone files.

If you read the mentioned article, you’ll know it’s better to move all task configuration into external files. So, instead of a large single gruntfile.js file:

module.exports = function (grunt) {   require('jit-grunt')(grunt)    grunt.initConfig({     clean: {/* task configuration goes here */},     watch: {/* task configuration goes here */},     csso: {/* task configuration goes here */},     postcss: {/* task configuration goes here */},     sass: {/* task configuration goes here */},     uncss: {/* task configuration goes here */}   }) }

We want this:

tasks   ├─ postcss.js   ├─ concat.js   ├─ cssmin.js   ├─ jshint.js   ├─ jsvalidate.js   ├─ uglify.js   ├─ watch.js   └─ sass.js gruntfile.js

But that will force us to load each external configuration into gruntfile.js manually, and that takes time! We need a way to load our configuration files automatically.

We’ll use load-grunt-configs for that purpose. It takes a path, grabs all of the configuration files there and gives us a merged config object which we use for Grunt config initialization.

Here how it works:

module.exports = function (grunt) {   require('jit-grunt')(grunt)    const configs = require('load-grunt-configs')(grunt, {     config: { src: 'tasks/.js' }   })    grunt.initConfig(configs)   grunt.registerTask('default', ['cssmin']) }

Grunt can do the same thing natively! Take a look at grunt.task.loadTasks (or it’s alias grunt.loadTasks).

Use it like this:

module.exports = function (grunt) {   require('jit-grunt')(grunt)    grunt.initConfig({})    // Load all your external configs.   // It's important to use it _after_ Grunt config has been initialized,   // otherwise it will have nothing to work with.   grunt.loadTasks('tasks')    grunt.registerTask('default', ['cssmin']) }

Grunt will automatically load all js or coffee config files from the specified directory. Nice and clean! But, if you’ll try to use it, you’ll notice it does nothing. How is that? We still need to do one more thing.

Let’s look into our gruntfile.js code once again, this time without the comments:

module.exports = function (grunt) {   require('jit-grunt')(grunt)    grunt.initConfig({})    grunt.loadTasks('tasks')    grunt.registerTask('default', ['cssmin']) }

Notice that grunt.loadTasks loads files from tasks directory, but never assigns it to our actual Grunt config.

Compare it with a way load-grunt-configs works:

module.exports = function (grunt) {   require('jit-grunt')(grunt)    // 1. Load configs   const configs = require('load-grunt-configs')(grunt, {     config: { src: 'tasks/.js' }   })    // 2. Assign configs   grunt.initConfig(configs)    grunt.registerTask('default', ['cssmin']) }

We initialize our Grunt config before actually loadings tasks configuration. If you are getting a strong feeling that it will make us end up with empty Grunt config — you’re totally right. You see, on contrary to the load-grunt-configs, grunt.loadTasks just imports files into gruntfile.js. It does nothing more.

Woah! So, how do we make use of it? Let’s explore!

First, create a file inside directory tasks named test.js

module.exports = function () {   console.log("Hi! I'm an external task and I'm taking precious space in your console!") }

Let’s run Grunt now:

$   grunt

We’ll see printed to the console:

> Hi! I'm an external task and I'm taking precious space in your console!

So, upon importing grunt.loadTasks, every function is executed as it loads files. That’s nice, but what’s the use of it for us? We still can’t do a thing we actually want — to configure our tasks.

Hold my beer because there is a way to command Grunt from within external configuration files! Using grunt.loadTasks upon importing provides current Grunt instance as a function first argument and also binds it to this.

So, we can update our Gruntfile:

module.exports = function (grunt) {   require('jit-grunt')(grunt)    grunt.initConfig({     // Add some value to work with     testingValue: 123   })    grunt.loadTasks('tasks')    grunt.registerTask('default', ['cssmin']) }

…and change the external config file tasks/test.js:

// Add `grunt` as first function argument module.exports = function (grunt) {   // Now, use Grunt methods on `grunt` instance   grunt.log.error('I am a Grunt error!')    // Or use them on `this` which does the same   this.log.error('I am a Grunt error too, from the same instance, but from `this`!')    const config = grunt.config.get()    grunt.log.ok('And here goes current config:')   grunt.log.ok(config) }

Now, let’s run Grunt again:

$   grunt

And what we’ll get:

> I am Grunt error! > I am Grunt error too, from the same instance, but from `this`! > And here goes current config: > {     testingValue: 123   }

See how we accessed native Grunt methods from an external file and were even able to retrieve the current Grunt config? Are you thinking about that too? Yeah, the full power of Grunt is already there, right at our fingertips in each file!

If you are wondering why methods inside external files can affect our main Grunt instance, it is because of a referencing. grunt.loadTasks passing this and grunt to our current Grunt instance — not a copy of it. By invoking methods on that reference, we’re able to read and mutate our main Grunt configuration file.

Now, we need to actually configure something! One last thing…

This time, let’s make configuration loading work for real

Alright, we’ve come a long way. Our tasks are loaded automatically and faster. We learned how to load external configs with native Grunt method. But our task configs are still not quite there because they do not end up in Grunt config.

But we’re almost there! We learned that we can use any Grunt instance methods in imported files using grunt.loadTasks. They are available on grunt and this instances.

Among many other methods, there is a precious grunt.config method. It allows us to set a value in an existing Grunt config. The main one, which we initialized in our Gruntfile… remember that one?

What’s important is the way we can define tasks configurations. Exactly what we need!

// tasks/test.js  module.exports = function (grunt) {   grunt.config('csso', {     build: {       files: { 'style.css': 'styles.css' }     }   })    // same as   // this.config('csso', {   //   build: {   //     files: { 'style.css': 'styles.css' }   //   }   // }) }

Now let’s update Gruntfile to log the current config. We need to see what we did, after all:

module.exports = function (grunt) {   require('jit-grunt')(grunt)    grunt.initConfig({     testingValue: 123   })    grunt.loadTasks('tasks')    // Log our current config   console.log(grunt.config())    grunt.registerTask('default', ['cssmin']) }

Run Grunt:

$   grunt

…and here’s what we see:

> {     testingValue: 123,     csso: {       build: {         files: {           'style.css': 'styles.css'         }       }     }   }

grunt.config sets csso value when imported, so the CSSO task is now configured and ready to run when Grunt is invoked. Perfect.

Note that if you used load-grunt-configs previously, you had a code like that, where each file exports a configuration object:

// tasks/grunt-csso.js  module.exports = {   target: {     files: { 'style.css': 'styles.css' }   } }

That needs to be changed to a function, as described above:

// tasks/grunt-csso.js  module.exports = function (grunt) {   grunt.config('csso', {     build: {       files: { 'style.css': 'styles.css' }     }   }) }

OK, one more one more last thing… this time for real!

Taking external config files to the next level

We learned a lot. Load tasks, load external configuration files, define a configuration with Grunt methods… that’s fine, but where’s the profit?

Hold my beer again!

By this time, we’ve externalized all our task configuration files. So, the our project directory looks something like this:

tasks   ├─ grunt-browser-sync.js     ├─ grunt-cache-bust.js   ├─ grunt-contrib-clean.js    ├─ grunt-contrib-copy.js     ├─ grunt-contrib-htmlmin.js      ├─ grunt-contrib-uglify.js   ├─ grunt-contrib-watch.js    ├─ grunt-csso.js     ├─ grunt-nunjucks-2-html.js      ├─ grunt-postcss.js      ├─ grunt-processhtml.js   ├─ grunt-responsive-image.js     ├─ grunt-sass.js     ├─ grunt-shell.js    ├─ grunt-sitemap-xml.js      ├─ grunt-size-report.js      ├─ grunt-spritesmith-map.mustache    ├─ grunt-spritesmith.js      ├─ grunt-standard.js     ├─ grunt-stylelint.js    ├─ grunt-tinypng.js      ├─ grunt-uncss.js    └─ grunt-webfont.js gruntfile.js

That keeps Gruntfile relatively small and things seem to be well organized. But do you get a clear picture of the project just by glancing into this cold and lifeless list of tasks? What actually do they do? What’s the flow?

Can you tell that Sass files are going through grunt-sass, then grunt-postcss:autoprefixer, then grunt-uncss, and finally through grunt-csso? Is it obvious that the clean task is cleaning the CSS or that grunt-spritesmith is generating a Sass file which should be picked up too, as grunt-watch watches over changes?

Seems like things are all over the place. We may have gone too far with externalization!

So, finally… now what if tell you that there’s yet a better way would be group configs… based on features? Instead of a not-so-helpful list of tasks, we’ll get a sensible list of features. How about that?

tasks   ├─ data.js    ├─ fonts.js    ├─ icons.js    ├─ images.js    ├─ misc.js    ├─ scripts.js    ├─ sprites.js    ├─ styles.js    └─ templates.js gruntfile.js

That tells me a story! But how could we do that?

We already learned about grunt.config. And believe it or not, you can use it multiple times in a single external file to configure multiple tasks at once! Let’s see how it works:

// tasks/styles.js  module.exports = function (grunt) {   // Configuring Sass task   grunt.config('sass', {     build: {/* options */}   })      // Configuring PostCSS task   grunt.config('postcss', {     autoprefix: {/* options */}   }) }

One file, multiple configurations. Quite flexible! But there is an issue we missed.

How should we deal with tasks such as grunt-contrib-watch? Its configuration is a whole monolithic thing with definitions for each task that are unable to be split.

// tasks/grunt-contrib-watch.js  module.exports = function (grunt) {   grunt.config('watch', {     sprites: {/* options */},     styles: {/* options */},     templates: {/* options */}   }) }

We can’t simply use grunt.config to set watch configuration in each file, as it will override the same watch configuration in already imported files. And leaving it in a standalone file sounds like a bad option too — after all, we want to keep all related things close.

Fret not! grunt.config.merge to the rescue!

While grunt.config explicitly sets and overrides any existing values in Grunt config, grunt.config.merge recursively merges values with existing values in other Grunt config files giving us a single Grunt config. A simple, but effective way to keep related things together.

An example:

// tasks/styles.js  module.exports = function (grunt) {   grunt.config.merge({     watch: {       templates: {/* options */}     }   }) }
// tasks/templates.js  module.exports = function (grunt) {   grunt.config.merge({     watch: {       styles: {/* options */}     }   }) }

This will produce a single Grunt config:

{   watch: {     styles: {/* options */},     templates: {/* options */}   } }

Just what we needed! Let’s apply this to the real issue — our styles-related configuration files. Replace our three external task files:

tasks   ├─ grunt-sass.js   ├─ grunt-postcss.js      └─ grunt-contrib-watch.js

…with a single tasks/styles.js file that combines them all:

module.exports = function (grunt) {   grunt.config('sass', {     build: {       files: [         {           expand: true,           cwd: 'source/styles',           src: '{,**/}*.scss',           dest: 'build/assets/styles',           ext: '.compiled.css'         }       ]     }   })    grunt.config('postcss', {     autoprefix: {       files: [         {           expand: true,           cwd: 'build/assets/styles',           src: '{,**/}*.compiled.css',           dest: 'build/assets/styles',           ext: '.prefixed.css'         }       ]     }   })    // Note that we need to use `grunt.config.merge` here!   grunt.config.merge({     watch: {       styles: {         files: ['source/styles/{,**/}*.scss'],         tasks: ['sass', 'postcss:autoprefix']       }     }   }) }

Now it’s much easier to tell just by glancing into tasks/styles.js that styles have three related tasks. I’m sure you can imagine extending this concept to other grouped tasks, like all the things you might want to do with scripts, images, or anything else. That gives us a reasonable configuration organization. Finding things will be much easier, trust me.

And that’s it! The whole point of what we learned.

That’s a wrap

Grunt is no longer the new darling it once was when it first hit the scene. But to date, it is a straightforward and reliable tool that does its job well. With proper handling, it gives even fewer reasons to swap it for something newer.

Let’s recap what we can do to organize our tasks efficiently:

  1. Load tasks using jit-grunt instead of load-grunt-tasks. It’s same but insanely faster.
  2. Move specific task configurations out from Gruntfile and into external config files to keep things organized.
  3. Use native grunt.task.loadTasks to load external config files. It’s simple but powerful as it exposes all Grunt capabilities.
  4. Finally, think about a better way to organize your config files! Group them by feature or domain instead of the task itself. Use grunt.config.merge to split complex tasks like watch.

And, for sure, check Grunt documentation. It’s still worth a read after all these years.

If you’d like to see a real-world example, check out Kotsu, a Grunt-based starter kit and static website generator. You’ll find even more tricks in there.

Got better ideas about how to organize Grunt configs even better? Please share them in the comments!

The post Let’s Give Grunt Tasks the Marie Kondo Organization Treatment appeared first on CSS-Tricks.

CSS-Tricks

, , , , , , ,
[Top]

Using Your Domain with a Netlify-Hosted Site

Netlify has their own docs for Custom Domains, so if you’re looking for horse’s mouth technical docs on this stuff, that should be treated as the source of truth. But I’d like to take a crack at it from a slightly different angle, where we look at where you are and what you wanna do, and the point you in the right direction.

Do you NOT own the domain yet?

If that’s the case, you can buy it directly through Netlify if you want. There is a big advantage there in that it automatically gets set up to work perfectly, so it’s easier.

You don’t have to buy your domain through Netlify though, you can buy it wherever you like. There is nothing you can’t do with Netlify if you choose to buy a domain elsewhere.

Easiest possible method: register the domain with Netlify.

Alternative: If you anticipate some hosting/DNS churn, like you think you might ultimately need to host elsewhere, it probably makes more sense to manage to domain somewhere agnostic where you can re-point DNS stuff wherever you need to. It’s not that you can’t manage the DNS on Netlify and point it elsewhere, it just doesn’t make loads of sense. Also, there is something to be said (lower cognitive load) managing all your domains in one place if you can.

What if you already own the domain?

No problem. The rest of this article deals with that scenario.

Are you cool pointing the nameservers at Netlify?

If you are, this is the best way. It means you don’t have to fiddle with subdomains and the CDN features work the best. The requires you to go into the DNS administration area of wherever you bought the domain and change the nameservers there. Every domain registrant will be a bit different in where and how you do that.

Changing nameservers on GoDaddy to point to Netlify.

Can’t or don’t want to point nameservers at Netlify?

I would guess that the main reason you might have this preference is that you use Cloudflare, or perhaps something else similar that gives you fancy performance and security advantages by going through their proxy. Netlify actually says that you don’t need Cloudflare with them, because many of the main advantages of Cloudflare Netlify already provides.

Technology is a moving place though, and it’s entirely possible that you need or really want some feature that a proxy service like Cloudflare provides.

If you need to do this, you’ve got two options:

  • Use the www. version of your domain and a CNAME record to point to Netlify (you can “CNAME flatten” it to remove www. if you really want).
  • Point the A record to Netlify’s load balancer IP address. I’d list it here, but you’re better off getting it from their docs in case it changes.

Are you just dealing with a subdomain anyway?

This is actually a lot easier. If this is the case, you probably already own the domain name anyway, and you should stick with your existing DNS host. All you need to do is CNAME the subdomain to the Netlify domain. Here’s an example where the root domain is hosted elsewhere and uses Cloudflare for DNS, but the subdomain is Netlify hosted and points with a CNAME.

If you care about the Netlify domain sitting there with the same content on it, you can always redirect it. Also, you might need to “gray cloud” (turn off the Cloudflare proxy) for those subdomains so Netlify can issue SSL certificates for it.

The post Using Your Domain with a Netlify-Hosted Site appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

SSCCE

You know what a “reduced test case” is, right? We’ve talked about it here. I imagine the concept is useful in many walks of life, but in the world of front-end development, you can think of it like:

A reduced test case is a demo/example page you create which reproduces the problem you are having with the least amount of code possible. Only the HTML needed to show the problem content. Only CSS that is related to that reduced HTML. Only the JavaScript related to the problem functionality at hand.

The point of making these is typically troubleshooting. It’s both for you and for anyone else looking at the trouble. The less unrelated code anyone has to wade through to understand the problem, the better. The secret trick is that while making a reduced test case, you often figure out the problem in the process. 😉

I recently found out another acronym for all this: SSCCE.

That stands for “Short, Self Contained, Correct (Compilable), Example.” Sleuthing the meta tags, it looks like the credit is to Andrew Thompson and last updated in 2014. That landing page describes them wonderfully and explains what you need to do to create one.

It covers this classic situation where you discover the problem isn’t where you think it is:

If trimming a very large amount if code for others to see, you might trim out a part of it early on that you think is not related to the problem, yet the problem is fixed.

…and closes with the most important thing:

We are not proposing that every single problem needs a SSCCE in order to be solved. It will, however, make people much more likely to help, and will therefore increase the chance of finding a solution.

I’d say it’s a dramatic difference. The chances of me trying to help on a small bug where the bug is buried within a giant pile of unfamiliar code? Very low. The chances of me trying to help on a small bug with a SSCCE? High.

However, I think I still prefer “reduced test case” since the term is more self-explanatory.

The post SSCCE appeared first on CSS-Tricks.

CSS-Tricks

[Top]