Tag: Three

Three Buggy React Code Examples and How to Fix Them

There’s usually more than one way to code a thing in React. And while it’s possible to create the same thing different ways, there may be one or two approaches that technically work “better” than others. I actually run into plenty of examples where the code used to build a React component is technically “correct” but opens up issues that are totally avoidable.

So, let’s look at some of those examples. I’m going to provide three instances of “buggy” React code that technically gets the job done for a particular situation, and ways it can be improved to be more maintainable, resilient, and ultimately functional.

This article assumes some knowledge of React hooks. It isn’t an introduction to hooks—you can find a good introduction from Kingsley Silas on CSS Tricks, or take a look at the React docs to get acquainted with them. We also won’t be looking at any of that exciting new stuff coming up in React 18. Instead, we’re going to look at some subtle problems that won’t completely break your application, but might creep into your codebase and can cause strange or unexpected behavior if you’re not careful.

Buggy code #1: Mutating state and props

It’s a big anti-pattern to mutate state or props in React. Don’t do this!

This is not a revolutionary piece of advice—it’s usually one of the first things you learn if you’re getting started with React. But you might think you can get away with it (because it seems like you can in some cases).

I’m going to show you how bugs might creep into your code if you’re mutating props. Sometimes you’ll want a component that will show a transformed version of some data. Let’s create a parent component that holds a count in state and a button that will increment it. We’ll also make a child component that receives the count via props and shows what the count would look like with 5 added to it.

Here’s a Pen that demonstrates a naïve approach:

This example works. It does what we want it to do: we click the increment button and it adds one to the count. Then the child component is re-rendered to show what the count would look like with 5 added on. We changed the props in the child here and it works fine! Why has everybody been telling us mutating props is so bad?

Well, what if later we refactor the code and need to hold the count in an object? This might happen if we need to store more properties in the same useState hook as our codebase grows larger.

Instead of incrementing the number held in state, we increment the count property of an object held in state. In our child component, we receive the object through props and add to the count property to show what the count would look like if we added 5.

Let’s see how this goes. Try incrementing the state a few times in this pen:

Oh no! Now when we increment the count it seems to add 6 on every click! Why is this happening? The only thing that changed between these two examples is that we used an object instead of a number!

More experienced JavaScript programmers will know that the big difference here is that primitive types such as numbers, booleans and strings are immutable and passed by value, whereas objects are passed by reference.

This means that:

  • If you put a number in a variable, assign another variable to it, then change the second variable, the first variable will not be changed.
  • If you if you put an object in a variable, assign another variable to it, then change the second variable, the first variable will get changed.

When the child component changes a property of the state object, it’s adding 5 to the same object React uses when updating the state. This means that when our increment function fires after a click, React uses the same object after it has been manipulated by our child component, which shows as adding 6 on every click.

The solution

There are multiple ways to avoid these problems. For a situation as simple as this, you could avoid any mutation and express the change in a render function:

function Child({state}){   return <div><p>count + 5 = {state.count + 5} </p></div> }

However, in a more complicated case, you might need to reuse state.count + 5 multiple times or pass the transformed data to multiple children.

One way to do this is to create a copy of the prop in the child, then transform the properties on the cloned data. There’s a couple of different ways to clone objects in JavaScript with various tradeoffs. You can use object literal and spread syntax:

function Child({state}){ const copy = {...state};   return <div><p>count + 5 = {copy.count + 5} </p></div> }

But if there are nested objects, they will still reference the old version. Instead, you could convert the object to JSON then immediately parse it:

JSON.parse(JSON.stringify(myobject)) 

This will work for most simple object types. But if your data uses more exotic types, you might want to use a library. A popular method would be to use lodash’s deepClone. Here’s a Pen that shows a fixed version using object literal and spread syntax to clone the object:

One more option is to use a library like Immutable.js. If you have a rule to only use immutable data structures, you’ll be able to trust that your data won’t get unexpectedly mutated. Here’s one more example using the immutable Map class to represent the state of the counter app:

Buggy code #2: Derived state

Let’s say we have a parent and a child component. They both have useState hooks holding a count. And let’s say the parent passes its state down as prop down to the child, which the child uses to initialize its count.

function Parent(){   const [parentCount,setParentCount] = useState(0);   return <div>     <p>Parent count: {parentCount}</p>     <button onClick={()=>setParentCount(c=>c+1)}>Increment Parent</button>     <Child parentCount={parentCount}/>   </div>; }  function Child({parentCount}){  const [childCount,setChildCount] = useState(parentCount);   return <div>     <p>Child count: {childCount}</p>     <button onClick={()=>setChildCount(c=>c+1)}>Increment Child</button>   </div>; }

What happens to the child’s state when the parent’s state changes, and the child is re-rendered with different props? Will the child state remain the same or will it change to reflect the new count that was passed to it?

We’re dealing with a function, so the child state should get blown away and replaced right? Wrong! The child’s state trumps the new prop from the parent. After the child component’s state is initialized in the first render, it’s completely independent from any props it receives.

React stores component state for each component in the tree and the state only gets blown away when the component is removed. Otherwise, the state won’t be affected by new props.

Using props to initialize state is called “derived state” and it is a bit of an anti-pattern. It removes the benefit of a component having a single source of truth for its data.

Using the key prop

But what if we have a collection of items we want to edit using the same type of child component, and we want the child to hold a draft of the item we’re editing? We’d need to reset the state of the child component each time we switch items from the collection.

Here’s an example: Let’s write an app where we can write a daily list of five thing’s we’re thankful for each day. We’ll use a parent with state initialized as an empty array which we’re going to fill up with five string statements.

Then we’ll have a a child component with a text input to enter our statement.

We’re about to use a criminal level of over-engineering in our tiny app, but it’s to illustrate a pattern you might need in a more complicated project: We’re going to hold the draft state of the text input in the child component.

Lowering the state to the child component can be a performance optimization to prevent the parent re-rendering when the input state changes. Otherwise the parent component will re-render every time there is a change in the text input.

We’ll also pass down an example statement as a default value for each of the five notes we’ll write.

Here’s a buggy way to do this:

// These are going to be our default values for each of the five notes // To give the user an idea of what they might write const ideaList = ["I'm thankful for my friends",                   "I'm thankful for my family",                   "I'm thankful for my health",                   "I'm thankful for my hobbies",                   "I'm thankful for CSS Tricks Articles"]  const maxStatements = 5;  function Parent(){   const [list,setList] = useState([]);      // Handler function for when the statement is completed   // Sets state providing a new array combining the current list and the new item    function onStatementComplete(payload){     setList(list=>[...list,payload]);   }   // Function to reset the list back to an empty array    function reset(){     setList([]);   }   return <div>     <h1>Your thankful list</h1>     <p>A five point list of things you're thankful for:</p>      {/* First we list the statements that have been completed*/}     {list.map((item,index)=>{return <p>Item {index+1}: {item}</p>})}      {/* If the length of the list is under our max statements length, we render      the statement form for the user to enter a new statement.     We grab an example statement from the idealist and pass down the onStatementComplete function.     Note: This implementation won't work as expected*/}     {list.length<maxStatements ?        <StatementForm initialStatement={ideaList[list.length]} onStatementComplete={onStatementComplete}/>       :<button onClick={reset}>Reset</button>     }   </div>; }  // Our child StatementForm component This accepts the example statement for it's initial state and the on complete function function StatementForm({initialStatement,onStatementComplete}){    // We hold the current state of the input, and set the default using initialStatement prop  const [statement,setStatement] = useState(initialStatement);    return <div>     {/*On submit we prevent default and fire the onStatementComplete function received via props*/}     <form onSubmit={(e)=>{e.preventDefault(); onStatementComplete(statement)}}>     <label htmlFor="statement-input">What are you thankful for today?</label><br/>     {/* Our controlled input below*/}     <input id="statement-input" onChange={(e)=>setStatement(e.target.value)} value={statement} type="text"/>     <input type="submit"/>       </form>   </div> }

There’s a problem with this: each time we submit a completed statement, the input incorrectly holds onto the submitted note in the textbox. We want to replace it with an example statement from our list.

Even though we’re passing down a different example string every time, the child remembers the old state and our newer prop is ignored. You could potentially check whether the props have changed on every render in a useEffect, and then reset the state if they have. But that can cause bugs when different parts of your data use the same values and you want to force the child state to reset even though the prop remains the same.

The solution

If you need a child component where the parent needs the ability to reset the child on demand, there is a way to do it: it’s by changing the key prop on the child.

You might have seen this special key prop from when you’re rendering elements based on an array and React throws a warning asking you to provide a key for each element. Changing the key of a child element ensures React creates a brand new version of the element. It’s a way of telling React that you are rendering a conceptually different item using the same component.

Let’s add a key prop to our child component. The value is the index we’re about to fill with our statement:

<StatementForm key={list.length} initialStatement={ideaList[list.length]} onStatementComplte={onStatementComplete}/>

Here’s what this looks like in our list app:

Note the only thing that changed here is that the child component now has a key prop based on the array index we’re about to fill. Yet, the behavior of the component has completely changed.

Now each time we submit and finish writing out statement, the old state in the child component gets thrown away and replaced with the example statement.

Buggy code #3: Stale closure bugs

This is a common issue with React hooks. There’s previously been a CSS-Tricks article about dealing with stale props and states in React’s functional components.

Let’s take a look at a few situations where you might run into trouble. The first crops up is when using useEffect. If we’re doing anything asynchronous inside of useEffect we can get into trouble using old state or props.

Here’s an example. We need to increment a count every second. We set it up on the first render with a useEffect, providing a closure that increments the count as the first argument, and an empty array as the second argument. We’ll give it the empty array as we don’t want React to restart the interval on every render.

function Counter() {    let [count, setCount] = useState(0);    useEffect(() => {     let id = setInterval(() => {       setCount(count + 1);     }, 1000);     return () => clearInterval(id);   },[]);    return <h1>{count}</h1>; }

Oh no! The count gets incremented to 1 but never changes after that! Why is this happening?

It’s to do with two things:

Having a look at the MDN docs on closures, we can see:

A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time the closure was created.

The “lexical environment” in which our useEffect closure is declared is inside our Counter React component. The local variable we’re interested is count, which is zero at the time of the declaration (the first render).

The problem is, this closure is never declared again. If the count is zero at the time declaration, it will always be zero. Each time the interval fires, it’s running a function that starts with a count of zero and increments it to 1.

So how might we get the function declared again? This is where the second argument of the useEffect call comes in. We thought we were extremely clever only starting off the interval once by using the empty array, but in doing so we shot ourselves in the foot. If we had left out this argument, the closure inside useEffect would get declared again with a new count every time.

The way I like to think about it is that the useEffect dependency array does two things:

  • It will fire the useEffect function when the dependency changes.
  • It will also redeclare the closure with the updated dependency, keeping the closure safe from stale state or props.

In fact, there’s even a lint rule to keep your useEffect instances safe from stale state and props by making sure you add the right dependencies to the second argument.

But we don’t actually want to reset our interval every time the component gets rendered either. How do we solve this problem then?

The solution

Again, there are multiple solutions to our problem here. Let’s start with the easiest: not using the count state at all and instead passing a function into our setState call:

function Counter() {    let [count, setCount] = useState(0);    useEffect(() => {     let id = setInterval(() => {       setCount(prevCount => prevCount+ 1);     }, 1000);     return () => clearInterval(id);   },[]);    return <h1>{count}</h1>; }

That was easy. Another option is to use the useRef hook like this to keep a mutable reference of the count:

function Counter() {   let [count, setCount] = useState(0);   const countRef = useRef(count)      function updateCount(newCount){     setCount(newCount);     countRef.current = newCount;   }    useEffect(() => {     let id = setInterval(() => {       updateCount(countRef.current + 1);     }, 1000);     return () => clearInterval(id);   },[]);    return <h1>{count}</h1>; }  ReactDOM.render(<Counter/>,document.getElementById("root"))

To go more in depth on using intervals and hooks you can take a look at this article about creating a useInterval in React by Dan Abramov, who is one of the React core team members. He takes a different route where, instead of holding the count in a ref, he places the entire closure in a ref.

To go more in depth on useEffect you can have a look at his post on useEffect.

More stale closure bugs

But stale closures won’t just appear in useEffect. They can also turn up in event handlers and other closures inside your React components. Let’s have a look at a React component with a stale event handler; we’ll create a scroll progress bar that does the following:

  • increases its width along the screen as the user scrolls
  • starts transparent and becomes more and more opaque as the user scrolls
  • provides the user with a button that randomizes the color of the scroll bar

We’re going to leave the progress bar outside of the React tree and update it in the event handler. Here’s our buggy implementation:

<body> <div id="root"></div> <div id="progress"></div> </body>
function Scroller(){    // We'll hold the scroll position in one state   const [scrollPosition, setScrollPosition] = useState(window.scrollY);   // And the current color in another   const [color,setColor] = useState({r:200,g:100,b:100});      // We assign out scroll listener on the first render   useEffect(()=>{    document.addEventListener("scroll",handleScroll);     return ()=>{document.removeEventListener("scroll",handleScroll);}   },[]);      // A function to generate a random color. To make sure the contrast is strong enough   // each value has a minimum value of 100   function onColorChange(){     setColor({r:100+Math.random()*155,g:100+Math.random()*155,b:100+Math.random()*155});   }      // This function gets called on the scroll event   function handleScroll(e){     // First we get the value of how far down we've scrolled     const scrollDistance = document.body.scrollTop || document.documentElement.scrollTop;     // Now we grab the height of the entire document     const documentHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;      // And use these two values to figure out how far down the document we are     const percentAlong =  (scrollDistance / documentHeight);     // And use these two values to figure out how far down the document we are     const progress = document.getElementById("progress");     progress.style.width = `$  {percentAlong*100}%`;     // Here's where our bug is. Resetting the color here will mean the color will always      // be using the original state and never get updated     progress.style.backgroundColor = `rgba($  {color.r},$  {color.g},$  {color.b},$  {percentAlong})`;     setScrollPosition(percentAlong);   }      return <div className="scroller" style={{backgroundColor:`rgb($  {color.r},$  {color.g},$  {color.b})`}}>     <button onClick={onColorChange}>Change color</button>     <span class="percent">{Math.round(scrollPosition* 100)}%</span>   </div> }  ReactDOM.render(<Scroller/>,document.getElementById("root"))

Our bar gets wider and increasingly more opaque as the page scrolls. But if you click the change color button, our randomized colors are not affecting the progress bar. We’re getting this bug because the closure is affected by component state, and this closure is never being re-declared so we only get the original value of the state and no updates.

You can see how setting up closures that call external APIs using React state, or component props might give you grief if you’re not careful.

The solution

Again, there are multiple ways to fix this problem. We could keep the color state in a mutable ref which we could later use in our event handler:

const [color,setColor] = useState({r:200,g:100,b:100}); const colorRef = useRef(color);  function onColorChange(){   const newColor = {r:100+Math.random()*155,g:100+Math.random()*155,b:100+Math.random()*155};   setColor(newColor);   colorRef.current=newColor;   progress.style.backgroundColor = `rgba($  {newColor.r},$  {newColor.g},$  {newColor.b},$  {scrollPosition})`; }

This works well enough but it doesn’t feel ideal. You may need to write code like this if you’re dealing with third-party libraries and you can’t find a way to pull their API into your React tree. But by keeping one of our elements out of the React tree and updating it inside of our event handler, we’re swimming against the tide.

This is a simple fix though, as we’re only dealing with the DOM API. An easy way to refactor this is to include the progress bar in our React tree and render it in JSX allowing it to reference the component’s state. Now we can use the event handling function purely for updating state.

function Scroller(){   const [scrollPosition, setScrollPosition] = useState(window.scrollY);   const [color,setColor] = useState({r:200,g:100,b:100});      useEffect(()=>{    document.addEventListener("scroll",handleScroll);     return ()=>{document.removeEventListener("scroll",handleScroll);}   },[]);      function onColorChange(){     const newColor = {r:100+Math.random()*155,g:100+Math.random()*155,b:100+Math.random()*155};     setColor(newColor);   }    function handleScroll(e){     const scrollDistance = document.body.scrollTop || document.documentElement.scrollTop;     const documentHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;     const percentAlong =  (scrollDistance / documentHeight);     setScrollPosition(percentAlong);   }   return <>     <div class="progress" id="progress"    style={{backgroundColor:`rgba($  {color.r},$  {color.g},$  {color.b},$  {scrollPosition})`,width: `$  {scrollPosition*100}%`}}></div>     <div className="scroller" style={{backgroundColor:`rgb($  {color.r},$  {color.g},$  {color.b})`}}>     <button onClick={onColorChange}>Change color</button>     <span class="percent">{Math.round(scrollPosition * 100)}%</span>   </div>   </> }

That feels better. Not only have we removed the chance for our event handler to get stale, we’ve also converted our progress bar into a self contained component which takes advantage of the declarative nature of React.

Also, for a scroll indicator like this, you might not even need JavaScript — have take a look at the up-and-coming @scroll-timeline CSS function or an approach using a gradient from Chris’ book on the greatest CSS tricks!

Wrapping up

We’ve had a look at three different ways you can create bugs in your React applications and some ways to fix them. It can be easy to look at counter examples which follow a happy path and don’t show subtleties in the APIs that might cause problems.

If you still find yourself needing to build a stronger mental model of what your React code is doing, here’s a list of resources which can help:


The post Three Buggy React Code Examples and How to Fix Them appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , , ,

Three Ways to Blob with CSS and SVG

Blobs are the smooth, random, jelly-like shapes that have a whimsical quality and are just plain fun. They can be used as illustration elements and background effects on the web.

So, how are they made? Just crack open an illustration app and go for it, right? Sure, that’s cool. But we’re in a post here on CSS-Tricks, and it would be much more fun to look at the possibilities we have to do this with CSS and SVG — two of our favorite ingredients!

We actually have a few ways to go about blobs. Let’s check them out.

Drawing circles in SVG

Let’s start easy. We can draw SVG in something like Illustrator, Sketch, Figma or whatever, but we’re going to draw in SVG code instead.

SVG makes it pretty trivial to draw a circle, thanks to the appropriately named <circle> element:

<circle cx="100" cy="100" r="40" fill="red" />

Those funky attributes? They make sense once you break them down:

  • cx defines the x-coordinate of center of circle.
  • cy defines the y-coordinate.
  • r is the radius.
  • fill is used to fill the shape with color.

That snippet creates a circle with a 40px radius with its center at 100px on the x-axis and 100px on the y-axis. The coordinates start from the upper-left corner of the parent container.

Let’s create multiple overlapping circles like this:

<svg height="300" width="300">   <circle cx="80" cy="80" r="40" fill="red" />   <circle cx="120" cy="80" r="40" fill="red" />   <circle cx="150" cy="80" r="40" fill="red" />   <circle cx="150" cy="120" r="40" fill="red" />   <circle cx="100" cy="100" r="40" fill="red" /> </svg> 

<svg> acts as the art board where all the different shapes and figures are drawn. So, its height and width indicates the size in which the whole drawing needs to be enclosed. If some part of figure is out of bounds of the SVG’s size, then that part will be truncated.

But blobs aren’t always so perfectly… round. We can mix things up by using <ellipse> instead of <circle>:

<ellipse cx="200" cy="80" rx="100" ry="50" fill="red" />

This is nearly identical to the circle except the change in tag name and two radii values to define the horizontal (rx) and vertical (ry) radii separately. The funny thing is that we can still get a perfect circle if we want if the radii values are the same. So, in a sense, <ellipse> is a little more versatile.

And, if all you need is a circle, we could probably lean on CSS without SVG at all. Any box element can become a circle or ellipse with border-radius.

.circle {   border-radius: 50%;   height: 50px;   width: 50px; }

…but more on that later.

Freestyling with SVG paths

Thanks to SVG’s <path> tag, we can create any kind of shape. It is like drawing with a pencil or pen. You start from a point and draw lines, curves, shapes and close the loop.

There are many data parameters in path for different tasks like:

  • M – Moving to the point
  • L – Drawing line
  • C – Drawing a curve
  • Q – Bézier curve
  • Z – Closing the path

Chris has a super thorough guide that explains these parameters in great detail.

We just need the curve (C) parameter for the actual drawing. But we’ll also be moving the starting point and closing the path, so we’ll reach for the M and Z parameters as well.

A green blob with four edges that vary in size and shape.
This is a random blobby shape I put together using SVG’s <path> element.

Ready to break this down? Coordinates play a big role in <path> so what we’re about to look at will look like Google Maps data barfed inside our code. But it makes a lot more sense when we know what they’re doing.

Take this…

<svg xmlns="http://www.w3.org/2000/svg">   <path     fill="#24A148"     d=""   /> </svg>

Here, the d attribute stores the path data. It holds information containing where the drawing starts, what direction it moves, what shape it follows, and where it ends. For example:

<path d="M 10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent"/>

It shows that our path starts from coordinates 10 10, indicated by the M that precedes them. Then, it establishes a Cubic Bézier curve (C) with two control points. Bézier curves are like handles on the both ends of a path that control the curviness between them. We have two Bézier “handles”: one for starting position (20 20) of the curve and another for ending position (40 20).

Show to end points for a black path line with light red lines extended from each endpoint indicating the amount of curve on each point.

Let’s use this knowledge to design our blob. The blob I drew is actually a bit complex, with a number of curves and control points. It doesn’t help that many of the coordinates aren’t full integers. But, still, now that we know what the <path> ‘s d parameter does and the attributes it uses to draw points along the path, it doesn’t look quite as scary.

But, hey, I get it. That’s a lot of code to not only write by hand, but get exactly right as well. I wouldn’t fault you for using something like this tool to generate the code for you.

Gooey effects with CSS and SVG filters

SVG path is complex. Right? What if I present you a way to convert many custom shapes (which you can create through divs) into gooey blobs? Here’s the idea. We’re going to create two rectangles that intersect. They’re the same color, but have a little transparency to darken where they intersect.

Then we’re going to leverage SVG’s blurring features to smudge the rectangles, creating an extra gooey blob with softer edges. The two intersecting rectangles will turn into this –

A bright red blob with four corners of varying shape and size, like in a reverse L shape.

Let’s first understand how filters work in SVG. They are declared using <filter> on HTML elements or other SVG elements, like circle.

circle {   filter: url("#id_of_filter"); }

<filter> is basically a wrapper for the actual filter effects, that include:

  • <feGaussianBlur>
  • <feImage>
  • <feMerge>
  • <feColorMatrix>
  • Many more… Get the complete list here.

Our blob is blurred and colored, so that’s why we’re going to put <feGaussianBlur> and <feColorMatrix> to use.

<feGaussianBlur> takes multiple attributes, but we are only interested in two of them: how much blur we want and where we want it. The standard deviation (stdDeviation) and in properties align with those needs, respectively.

in accepts one of two values:

  • SourceGraphic – Blurs the entire shape
  • SourceAlpha – Blurs the alpha value, and is used to create shadow effects

After playing around a bit, here’s where I landed on the <feGaussianBlur> effect:

<feGaussianBlur in="SourceGraphic" stdDeviation="30" />

This goes right in the HTML markup with an ID that we call on the parent element of our blob:

<!-- The SVG filter --> <svg style="position: absolute; width: 0; height: 0;">   <filter id="goo">     <feGaussianBlur in="SourceGraphic" stdDeviation="30" />   </filter> </svg>  <!-- The blob --> <div class="hooks-main">   <div></div>   <div></div> </div>

The filter doesn’t actually render, even though it’s in the markup. Instead, we reference it as a CSS filter on the blob’s parent element:

/* Blob parent element */ .hooks-main {   position: absolute;   width: 100%;   height: 100%;   filter: url("#goo&amp");   overflow: hidden; }

This isn’t done just yet. The blur is scattered and the element’s shape lost its boundary and color. We need a bulging effect with blur on the boundaries and a solid color to fill the shape. This is where our next SVG filter, <feColorMatrix>, comes into play.

There are two <feColorMatrix> attributes we want:

  • in – Indicates where the effect is applied, just like <feGaussianBlur>.
  • values – A matrix of four rows and five columns.

The values attribute bears a little more nuance. It holds a matrix that gets multiplied with the color and alpha values of each pixel and generates a new color value for that pixel. Mathematically speaking:

new pixel color value = ( values matrix ) × ( current pixel color value )

Let’s get a little numbers nerdy here. In that equation, values matrix is equal to:

[F-red1 F-green1 F-blue1 F-alpha1 F-constant1  F-red2 F-green2 F-blue2 F-alpha2 F-constant2  F-red3 F-green3 F-blue3 F-alpha3 F-constant3  F-red4 F-green4 F-blue4 F-alpha4 F-constant4]

Here, F-red means a fraction of red in pixels, with a value ranging from 0 to 1. F-constant is some constant value to add (or subtract) from color value.

Breaking this down further… We have a color pixel with an RGBA value of rgba(214, 232, 250, 1). To convert it into a new color, we will multiply it with our values matrix.

Values Matrix Color Pixel (RGBA) New Color (RGBA)
[1 0 0 0 0
 0 1 0 0 0
 0 0 1 0 0
 0 0 0 1 0
 0 0 0 0 1]
× [214
 232
 250
 1
 1]
= [ 214x1 + 232x0 + 250x0 + 1x0 + 1x1
      214x0 + 232x1 + 250x0 + 1x0 + 1x1
      214x0 + 232x0 + 250x1 + 1x0 + 1x1
      214x0 + 232x0 + 250x0 + 1x1 + 1x1
      214x0 + 232x0 + 250x0 + 1x0 + 1x1 ]
= [214
  232
  250
 1
  1]

The pixel value didn’t change because we multiplied it by the identity matrix, but if you change the values of the matrix, then its pixel value will change too. Learn more about values matrix from MDN documentation.

In our case, these values seem to work pretty well:

<filter id="goo">   <feGaussianBlur in="SourceGraphic" stdDeviation="30" />   <feColorMatrix     in="blur"     values="1 0 0 0 0              0 1 0 0 0              0 0 1 0 0              0 0 0 30 -7"   /> </filter>

I’ve added few more styles in the blob to stretch it from the corner.

Try to use these filter values in other shapes and let me know how they work out for you in the comments.

Using CSS border-radius

We teased this earlier, but now let’s get to the CSS border-radius property. It can also create blob-like shape, thanks to it’s ability to smooth out the corners of an element. This is possible because each corner radius is divided into two radii, one for each edge. That’s why we can have more shapes apart from circle and ellipse.

Each corner has two radii, one for each edge. For example, the top-left corder of a box has two radii, one for its left edge and one for its top edge.

You might be used to using border-radius as a shorthand for all four corners of an element:

.rounded {   border-radius: 25%; }

That’s a nice way to get uniformity for all of the corners. But blobs aren’t so uniform. We want some corners to be rounder than others to get some that looks gooey. That’s why we go for the constituent properties of border-radius, like:

.element {   border-top-left-radius: 70% 60%;   border-top-right-radius: 30% 40%;   border-bottom-right-radius: 30% 60%;   border-bottom-left-radius: 70% 40%; }

And see how each properties takes two values? That’s one for each edge of the corner, giving us a lot of flexibility to curve an element into interesting shapes. Then we can drop in a background color, fill it up with a gradient, or even set a box-shadow on it to get a neat effect.


The post Three Ways to Blob with CSS and SVG appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, ,
[Top]

A Calendar in Three Lines of CSS

This article has no byline and is on a website that is even more weirdly specific than this one is, but I appreciate the trick here. A seven-column grid makes for a calendar layout pretty quick. You can let the days (grid items) fall onto it naturally, except kick the first day over to the correct first column with grid-column-start.

Thoughts:

  • I’d go with an <ol> rather than a <ul> just because it seems like days are definitely ordered.
  • The days as-a-list don’t really bother me since maybe that makes semantic sense to the content of the calendar (assuming it has some)
  • But… seeing the titles of the days-of-the-week as the first items in the same list feels weird. Almost like that should be a separate list or something.
  • Or maybe it should all just be a <table> since it’s sort of tabular data (it stands to reason you might want to cross-reference and look at all Thursdays or whatever).

Anyway, the placement trickery is fun.

Here’s another (similar) approach from our collection of CSS Grid starter templates.

Direct Link to ArticlePermalink


The post A Calendar in Three Lines of CSS appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, ,
[Top]

Three Ways to Distinguish a Site From the Norm

In an age where so much web design is already neat, clean, and simple, I can think of three ways to distinguish your site from the norm:

  1. Stunning visuals that cannot be created in UI vector editors, like Figma and Sketch
  2. Beautifully-animated interactions that cannot be dreamt in the language of Stacks of Rectangles
  3. Typography

The third is the most accessible, and an awesome place to differentiate your brand. Accordingly, look for a renaissance of type — a flourishing of serifs, throwbacks, quirky fonts, and genre-bending typefaces. Expect that font pairing will become an even more important skill, and picking great fonts for your brand will carry even more weight in the near future.

After all, it’s basically a design cheat code.


The post Three Ways to Distinguish a Site From the Norm appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , , ,
[Top]

Three Things You Didn’t Know About AVIF

AVIF, the file format based on the AV1 video codec, is the latest addition to the next-gen image formats. Early reports and comparisons show good results compared to JPEG and WebP. However, even if browser support is good, AVIF is still on the bleeding edge in regards to encoding and decoding. Encoding, decoding, settings and parameters has been well discussed elsewhere. 

No doubt, AVIF images generate a smaller payload and are nice looking. In this post, we’ll take a closer look at issues to be aware or before you go all in on AVIF.

1. WebP is Better for Thumbnails

One interesting observation is that for small dimension images, WebP will produce lighter payload images than AVIF.

It’s probably possible to explain why, and tune the encoder to address this case. However, that is not an option for most people. Most people would probably rely on an image optimizer like squoosh.app or an image CDN like ImageEngine. The below comparison uses exactly these two alternatives for AVIF conversion. 

We see that WebP will generally produce images with a higher file size than AVIF. On larger dimension images, ImageEngine performs significantly better than squoosh.app.

Now, to the interesting observation. On images around 100px × 100px squoosh.app passes ImageEngine on effectiveness, but then also WebP catches up and for a 80px x 80px image. WebP is actually the most effective image measured in file size. 

The test performs relatively consistently on different types of images. For this illustration, this image from Picsum is used.

Pixels Original JPEG (bytes) Optimized WebP (bytes) ImageEngine AVIF (bytes) squoosh.app AVIF (bytes)
50 1,475 598 888 687
80 2,090 1,076 1,234 1,070
110 3,022 1,716 1,592 1,580
150 4,457 2,808 2,153 2,275
170 5,300 3,224 2,450 2,670
230 7,792 4,886 3,189 3,900
290 10,895 6,774 4,056 5,130

2. AVIF Might Not Be the Best for Product Images with High Entropy

Typically, a product page consists of images of the product, and when a user’s mouse hovers over or clicks on the product image, it zooms in to offer a closer look at the details.

It is worth noting that AVIF will in certain cases reduce the level of detail, or perceived sharpness, of the image when zoomed in. Especially on a typical product image where the background is blurred or has low entropy while foreground, and product, has more detail and possibly higher entropy.

Below is a zoomed in portion of a bigger product image (JPEG, AVIF) which clearly illustrates the difference between a regularly optimized JPEG versus an AVIF image optimized by squoosh.app.

The AVIF is indeed much lighter than the JPEG, but in this case the trade off between visual quality and lower file size has gone too far. This effect will not be as perceptible for all types of images, and therefore will be difficult to proactively troubleshoot in an automated build process that relies on responsive images syntax for format selection.

Moreover, unlike JPEG, AVIF does not support progressive rendering. For a typical product detail page, progressive rendering might provide a killer feature to improve key metrics like Largest Contentful Paint and other Core Web Vitals metrics. Even if a JPEG takes a little bit longer time to download due to its larger file size compared to AVIF, chances are that it will start rendering sooner than an AVIF thanks to its progressive rendering mechanism. This case is well illustrated by this video from Jake Achibald.

3. JPEG 2000 is Giving AVIF Tough Competition

The key selling point of AVIF is its extremely low file size relative to an acceptable visual image quality. Early blogs and reports have been focusing on this. However, JPEG2000 (or JP2) may in some cases be a better tool for the job. JPEG2000 is a relatively old file format and does not get the same level of attention as AVIF, even if the Apple side of the universe already supports JPEG2000.

To illustrate, let’s look at this adorable puppy. The AVIF file size optimized by squoosh.app is 27.9 KB with default settings. Converting the image to JPEG2000, again using ImageEngine, the file size is 26.7 KB. Not much difference, but enough to illustrate the case.

What about the visual quality? DSSIM is a popular way to compare how visually similar an image is to the original image. The DSSIM metric compares the original image to a converted file, with a lower value indicating better quality. Losslessly converting the AVIF and JPEG2000 version to PNG, the DSSIM score is like this:

DSSIM (0 = equal to original) Bytes
JPEG2000 0.019 26.7 KB
AVIF 0.012 27.9 KB

AVIF has slightly better DSSIM but hardly visible to the human eye.

Right Tool for the Job

The key takeaway from this article is that AVIF is hardly the “silver bullet,” or the one image format to rule them all. First of all, it is still very early in the development of both encoders and decoders. In addition, AVIF is yet another format to manage. Like Jake Archibald also concludes in his article, offering 3+ versions of each image on your webpage is a bit of a pain unless the entire workflow (resize, compress, convert, select, deliver) is all automated.

Also, like we’ve seen, just because a browser supports AVIF, it doesn’t mean that it is the best choice for your users.

Using responsive images and adding AVIF to the list of image formats to pre-create is better than not considering AVIF at all. A potential challenge is that the browser will then pick AVIF if it’s supported regardless of whether AVIF is the right tool or not.

However, using an image CDN like ImageEngine, will to a greater extent be able to dynamically choose between supported formats and make a qualified guess whether WEBP, JPEG2000 or AVIF will give the best user experience. Using an image CDN to automate the image optimization process will take into account browser compatibility, image payload size and visual quality.


The post Three Things You Didn’t Know About AVIF appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , , ,
[Top]

Three CSS Alternatives to JavaScript Navigation

Hey quick! You’ve gotta create the navigation for the site and you start working on the mobile behavior. What pattern do you choose? If you’re like most folks, it’s probably the “hamburger” menu that, when clicked, uses a little JavaScript to expand a vertical list of navigation links.

But that’s not the only option.

Depending on the context and contents of the navigation, there may be a JavaScript-free method that gets the job done while providing a more accessible experience.

It is considered best practice to use a progressive enhancement approach, building webpages for users with the oldest and least capable technology first, then introducing additional enhancements as support allows. If you can provide a quality experience for users with basic technology, then you might consider whether or not your webpage even requires JavaScript functionality at all. Leaving JavaScript out of the navigation can ensure that users are able to navigate your website even if JavaScript is disabled or network issues prevent scripts from loading — which are definitely wins.

Let’s look at three alternative patterns to the JavaScript-powered hamburger menu.

Alternative 1: Put the menu on a separate page

Who said navigation has to be in the header of every page? If your front end is extremely lightweight or if you have a long list of menu items to display in your navigation, the most practical method might be to create a separate page to list them all. The lightweight WordPress theme Susty utilizes this method for its navigation.

This pattern is especially useful for static websites that use filesystem routing. If the project is built using a static site generator, the page load might be imperceptible to the user and have the added benefit of keeping your templates as modular as possible.

All this takes is basically replacing the “Menu” button with a close button instead when the user is on the menu page. When clicked, we can take the user back to the last page they were on in a couple of ways. If we are using a server-side CMS, like WordPress, then we can grab the last URL using $ _SERVER['HTTP_REFERER'] and set it as the “close” button URL.

But if we’re not using a server-side setup then, yeah, we might need a few lines of JavaScript to get that last URL.

<a href="https://MyHomePage.com" onclick="handleClick(event)">×</a> 
 <script>   function handleClick(event) {     // Don't follow the link     event.preventDefault();     // Go back to last visited page       window.history.back();      // Bail out of the function     return false;   } </script>

So, while I like this method and pattern, it might require JavaScript depending on the project.

Alternative 2: The horizontal scroller

This approach is perfect for shorter link lists and allows users to access all of the navigation items without opening anything or clicking away from where they are. GitHub uses this approach for sub-menus.

Using flexbox combined with a scrolling overflow in CSS will do the trick! 

Alternative 3: The CSS-only hamburger menu

Just because the hamburger menu pattern is often done with JavaScript doesn’t mean we have to use JavaScript. Using CSS pseudo-selectors and an HTML <input>, we can create a rich mobile menu and save JavaScript for other functionality that actually requires it.


See? Just because a convention is popular doesn’t mean it is the only way to do things. There are often simpler, more accessible methods, especially when it comes to navigation. It’s not much work to create functional, lightweight, immersive navigation without JavaScript and we get some nice benefits along the way. If you’ve created any interesting CSS-only navigation patterns, I’d love to see them — please share in the comments!


The post Three CSS Alternatives to JavaScript Navigation appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , ,
[Top]

The Three Types of Code

Every time I start a new project, I organize the code I’m looking at into three types, or categories if you like. And I think these types can be applied to any codebase, any language, any technology or open source project. Whether I’m writing HTML or CSS or building a React component, thinking about these different categories has helped me figure out what to refactor and prioritize, and what to leave alone for now.

Those categories: Boring Code, Salt Mine Code, and Radioactive Code.

Let me explain.

Boring Code

Boring code is when it makes perfect sense when you read it. There’s no need to refactor it, and it performs its function in a way that doesn’t make you want to throw yourself into a river. Boring code is good code. It doesn’t do a kick-flip and it’s not trying to impress you. You can use it without having to write even more code or engineer hacks on top of it. Boring code does exactly what it says on the tin and never causes any surprises.

This function makes sense, this prop is clearly named, this React component is straightforward. There are no loops within loops, no mental gymnastics required here.

However, boring code is near impossible to write because our understanding of it is almost always incomplete when we start tackling a problem. Just look at how many considerations can go into a styling a simple paragraph for contrast. To write boring code, we must be diligent, we must endlessly refactor, and we must care for the codebase beyond a paycheck at the end of the month.

Boring code is good because boring code is kind.

Salt Mine Code

This is the type of code that’s bonkers and makes not a lick of sense. It’s the sort of code that we can barely read but it’s buried so deep in the codebase that it’s near impossible to change anyway. However! It’s not leaking into other parts of our code, so we can mostly ignore it. It might not be pretty, and we probably don’t want to ever look at it so long as we live, but it’s not actively causing any damage.

It’s this type of code that we can mostly forget about,. It’s the type of code that is dangerous if opened up and tampered with, but for now, everything is okay.

The trouble is buried deep.

Radioactive Code

Radioactive code is the real problem at the heart of every engineering team. It’s the let’s-not-go-to-work-today sort of code. It’s the stuff that is not only bad but is actively poisoning our codebase and making everything worse over time. Imagine a codebase as a nuclear reactor; radioactive code is the stuff that’s breached the container and is now leaking into every part of our codebase.

An example? For us at Gusto and on the design systems team, I would consider our form components to be radioactive. Each component causes more problems because we can never use the component as is; we have to hack it to get what we want. Each time anyone uses this code they have to write even more code on top of it, making things worse over time, and it encourages everyone on the team to do the same.

In our design system, when we want to add a class name to the div that wraps a form element, we must use the formFieldClass prop in one component, and wrapperClass in another. There is a propType called isDefaultLayout and everyone sets it to false and writes custom CSS classes on top of it. In other words, not only does radioactive code make it hard for us to understand all this nonsense code, it makes it increasingly difficult to understand other parts of the codebase, too. Because the file we’re looking at right now has dependencies on eight different things that we cannot see. The result of removing this radioactive code means changing everything else that depends upon it.

In other words, radioactive code — like our form components — makes it impossible for the codebase to be trusted.

Radioactive code is not only bad for us and our codebase, but it is also bad for our team. It encourages bad habits, cruelty in Slack threads, not to mention that it causes friction between team members that is hard to measure. Radioactive code also encourages other teams in a company to go rogue and introduce new technologies into a codebase when the problem of radioactive code is not the tech itself. Anyone can write this type of code, regardless of the language or the system or the linting when they’re not paying enough attention to the problem. Or when they’re trying to be a little too smart. Or when they’re trying to impress someone.

How do we fix radioactive code? Well, we must draw a circle around it and contain the madness that’s leaking into other parts of the codebase. Then we must do something utterly heroic: we must make it boring.

The post The Three Types of Code appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Two-Value Display Syntax (and Sometimes Three)

You know the single-value syntax: .thing { display: block; }. The value “block” being a single value. There are lots of single values for display. For example, inline-flex, which is like flex in that it becomse a flex container, but behaves like an inline-level element rather than a block-level element. Somewhat intuitive, but much better served by a two-value system that can apply that same concept more broadly and just as intuitively.

For a deep look, you should read Rachel Andrew’s blog post The two-value syntax of the CSS Display property. The spec is also a decent read, as is this video from Miriam:

This is how it maps in my brain

Choose block or inline, then choose flow, flow-root, flex, grid, or table. If it’s a list-item that’s a third thing.

You essentially pick one from each column to describe the layout you want. So the existing values we use all the time map out something like this:

Another way to think about those two columns I have there is “outside” and “inside” display values. Outside, as in, how it flows with other elements around it. Inside, as in, how layout happens inside those elements.

Can you actually use it?

Not really. Firefox 70 is first out of the gate with it, and there are no other signals for support from Chrome-land or Safari-land that I know about. It’s a great evolution of CSS, but as far as day-to-day usage, it’ll be years out. Something as vital as layout isn’t something you wanna let fail just for this somewhat minor descriptive benefit. Nor is it probably worth the trouble to progressively enhance with @supports and such.

Weirdnesses

  • You can’t block flow because that doesn’t really make sense. It’ll be reset to block flow-root.
  • There is implied shorthand. Like if you inline list-item, that’s really inline flow list-item whereas list-item is block flow list-item. Looks all fairly intuitive.
  • You still use stuff like table-row and table-header-group. Those are single-value deals, as is contents and none.
  • Column one technically includes run-in too, but as far as I know, no browser has ever supported run-in display.
  • Column two technically includes ruby, but I have never understood what that even is.

How we talk about CSS

I like how Rachel ties this change to a more rational mental and teaching model:

… They properly explain the interaction of boxes with other boxes, in terms of whether they are block or inline, plus the behavior of the children. For understanding what display is and does, I think they make for a very useful clarification. As a result, I’ve started to teach display using these two values to help explain what is going on when you change formatting contexts.

It is always exciting to see new features being implemented, I hope that other browsers will also implement these two-value versions soon. And then, in the not too distant future we’ll be able to write CSS in the same way as we now explain it, clearly demonstrating the relationship between boxes and the behavior of their children.

The post Two-Value Display Syntax (and Sometimes Three) appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Three Predictions From the State of CSS 2019 Survey

Running a developer survey like the State of CSS is a multi-stage process. First, you need to collect the data. Then, you process it into a usable shape. Finally, you come up with nifty ways to visualize it and release it to the world.

But then, once the dust settles and the traffic dies down comes my favorite part: actually thinking about the data. By taking a deeper look at our data, as well as observing how the community discussed our findings, three unexpected trends ended up coming into focus.

But first, some background for those not already familiar with the project.

I first started the State of JavaScript survey three years ago in 2016 as a way to answer my own uncertainties about the future of web development. At the time, JavaScript fatigue was running wild and I thought a comprehensive developer survey could prove itself the antidote.

The original State of JavaScript 2016 edition

Turns out I hit a nerve: that first survey turned out to be very popular, and our audience has grown each year since, along with the scope of the survey. (I was also joined by Raphael Benitte, creator of the Nivo.js dataviz library, to help me with data processing and visualization.) This year marks the first time we’re pivoting out into a new dimension, namely the not-so-simple world of CSS.

Taking on CSS

Prediction 1: CSS still has a lot of unexplored territory

One of the things we wanted to quantify with the survey was how much of CSS was still left “unexplored.” In other words, what CSS features are developers either unfamiliar with, or else hadn’t yet used. For that reason we decided early-on to focus our Features section on new CSS properties, like shapes, masking, or scroll-snap rather than “boring” floats or tables.

The resulting data paints an interesting picture: it turns out that when you look at it this way, CSS morphs from a familiar landscape to a wild, unexplored jungle.

A look at comparing Flexbox vs. CSS Grid provides a good illustration of this trend. While nearly everybody who’s heard of Flexbox has also used it, only 55% of developers who are aware of CSS Grid have actually tried it. That’s a big gap, especially for a technology as important as CSS Grid!

Layout Features

Or take CSS Shapes: 68% of developers are aware of them, only 31% of that group has actually used the feature.

CSS Shapes

This all points at a big gap between what we collectively want to learn and what we actually know. It’s that potential for growth that is exactly what makes CSS so exciting in 2019.

Prediction 2: Functional CSS will keep rising

If you’re old enough to remember the CSS Zen Garden — or to have actually learned CSS through it (in which case I know how you feel, my back hurts when I get up in the morning as well) — then this next trend might seem weird, or even downright wrong.

CSS Zen Garden: one page, many themes.

Functional CSS rejects the platonic ideal of pure, untainted markup free from any styling concerns and embraces “functional” (aka “atomic” or “utility”) classes. Think <div class="text-red text-medium border-1">...</div>.

Adopting this approach means you can’t magically update your stylesheet and change your entire design without modifying a single line of markup. But be honest, how often does this happen anyway? Compared to the often theoretical elegance of the Zen Garden philosophy, libraries like Tailwind and Tachyons provide tangible, real-world benefits, which explains why they’re so highly regarded. In fact, those take the #1 and #4 spots, respectively, in terms of satisfaction ratio in the CSS Framework category.

Awareness, interest, and satisfaction ratio rankings for CSS frameworks.

Tailwind especially seems to be picking up speed, at least judging by the Twitter engagement from its community in response to the survey results. Having just hit version 1.0, it’s definitely a project to keep an eye on!

Prediction 3: The battle for CSS has just begun

Looking at our data, I can’t help but wonder if “JavaScript fatigue” will soon be replaced by “CSS fatigue.”

When evaluating technologies, it’s important to look not just at raw usage numbers, but also at user satisfaction. After all, you don’t want to jump on the latest bandwagon just to find out its current occupants can’t wait to hop off it.

This scatterplot chart that’s divided into quadrants is perfect for this. It plots usage against satisfaction, making it easy to isolate popular, high-satisfaction tools into their own quadrant.

Usage vs. Satisfaction

What’s apparent in this chart is that the most densely populated area is the “Assess” quadrant. In other words, the low-usage, high-satisfaction technologies that are still battling it out for supremacy. This is exactly the state that the JavaScript ecosystem finds itself in as well. Many contenders, but few decisive winners as of today.

This is not necessarily a bad thing: yes, it does make the average developer’s life harder when it comes to picking the right tool, but hey, this is why we do what we do! Additionally, competition can only be good for the ecosystem as a whole. Once the dust settles, we’ll hopefully end up with the best possible options having survived!

CSS in 2019

Overall, the State of CSS survey shows that this is not your grandpa’s CSS anymore. For years, we developers have loved to complain about the inadequacies of CSS and its lack of powerful features. But in 2019, CSS is challenging us to put our money where our mouthes are: here’s all the features you’ve always wanted. Now what are you going to do about it?

I, for one, am very excited to dive even deeper into this new world of styling. And, of course, to tune back in 2020 to see what new trends we find then!

The post Three Predictions From the State of CSS 2019 Survey appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,
[Top]