An Overview of Render Props in React

An Overview of Render Props in React

Using render props in React is a technique for efficiently re-using code. According to the React documentation, “a component with a render prop takes a function that returns a React element and calls it instead of implementing its own render logic.” To understand what that means, let’s take a look at the render props pattern and then apply it to a couple of light examples.

The render props pattern

In working with render props, you pass a render function to a component that, in turn, returns a React element. This render function is defined by another component, and the receiving component shares what is passed through the render function.

This is what this looks like:

class BaseComponent extends Component { render() { return <Fragment>{this.props.render()}</Fragment>; }
}

Imagine, if you will, that our App is a gift box where App itself is the bow on top. If the box is the component we are creating and we open it, we’ll expose the props, states, functions and methods needed to make the component work once it’s called by render().

The render function of a component normally has all the JSX and such that form the DOM for that component. Instead, this component has a render function, this.props.render(), that will display a component that gets passed in via props.

Example: Creating a counter

See the Pen React Render Props by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.

Let’s make a simple counter example that increases and decreases a value depending on the button that is clicked.

First, we start by creating a component that will be used to wrap the initial state, methods and rendering. Creatively, we’ll call this Wrapper:

class Wrapper extends Component { state = { count: 0 }; // Increase count increment = () => { const { count } = this.state; return this.setState({ count: count + 1 }); }; // Decrease count decrement = () => { const { count } = this.state; return this.setState({ count: count - 1 }); }; render() { const { count } = this.state; return ( <div> {this.props.render({ increment: this.increment, decrement: this.decrement, count: count })} </div> ); }
}

In the Wrapper component, we specify the methods and state what gets exposed to the wrapped component. For this example, we need the increment and decrement methods. We have our default count set as 0. The logic is to either increment or decrement count depending on the method that is triggered, starting with a zero value.

If you take a look at the return() method, you’ll see that we are making use of this.props.render(). It is through this function that we pass methods and state from the Wrapper component so that the component that is being wrapped by it will make use of it.

To use it for our App component, the component will look like this:

class App extends React.Component { render() { return ( <Wrapper render={({ increment, decrement, count }) => ( <div> <div> <h3>Render Props Counter</h3> </div> <div> <p>{count}</p> <button onClick={() => increment()}>Increment</button> <button onClick={() => decrement()}>Decrement</button> </div> </div> )} /> ); }
}

Example: Creating a data list

The gain lies in the reusable power of render props, let’s create a component that can be used to handle a list of data which is obtainable from an API.

See the Pen React Render Props 2 by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.

What do we want from the wrapper component this time? We want to pass the source link for the data we want to render to it, then make a GET request to obtain the data. When the data is obtained we then set it as the new state of the component and render it for display.

class Wrapper extends React.Component { state = { isLoading: true, error: null, list: [] }; fetchData() { axios.get(this.props.link) .then((response) => { this.setState({ list: response.data, isLoading: false }); }) .catch(error => this.setState({ error, isLoading: false })); } componentDidMount() { this.setState({ isLoading: true }, this.fetchData); } render() { return this.props.render(this.state); }
}

The data link will be passed as props to the Wrapper component. When we get the response from the server, we update list using what is returned from the server. The request is made to the server after the component mounts.

Here is how the Wrapper gets used:

class App extends React.Component { render() { return ( <Wrapper link="https://jsonplaceholder.typicode.com/users" render={({ list, isLoading, error }) => ( <div> <h2>Random Users</h2> {error ? <p>{error.message}</p> : null} {isLoading ? ( <h2>Loading...</h2> ) : ( <ul>{list.map(user => <li key={user.id}>{user.name}</li>)}</ul> )} </div> )} /> ); }
}

You can see that we pass the link as a prop, then we use ES6 de-structuring to get the state of the Wrapper component which is then rendered. The first time the component loads, we display loading text, which is replaced by the list of items once we get a response and data from the server.

The App component here is a class component since it does not manage state. We can transform it into a functional stateless component.

const App = () => { return ( <Wrapper link="https://jsonplaceholder.typicode.com/users" render={({ list, isLoading, error }) => ( <div> <h2>Random Users</h2> {error ? <p>{error.message}</p> : null} {isLoading ? ( <h2>Loading...</h2> ) : ( <ul>{list.map(user => <li key={user.id}>{user.name}</li>)}</ul> )} </div> )} /> );
}

That’s a wrap!

People often compare render props with higher-order components. If you want to go down that path, I suggest you check out this post as well as this insightful talk on the topic by Michael Jackson.

The post An Overview of Render Props in React appeared first on CSS-Tricks.

Scaling CSS: Two Sides of a Spectrum

The subject of scaling CSS came up a lot in a recent ShopTalk Show with Ben Frain. Ben has put a lot of thought into the subject, even writing a complete book on it, Enduring CSS, which is centered around a whole ECSS methodology.

He talked about how there are essentially two solutions for styling at scale:

  1. Total isolation
  2. Total abstraction

Total isolation is some version of writing styles scoped to some boundary that you’ve set up (like a component) in which those styles don’t leak in or out.

Total abstraction is some version of writing styles that are global, yet so generic and re-usable, that they have no unintended side effects.

Total isolation might come from <style scoped> in a .vue file, CSS modules in which CSS class selectors and HTML class attributes are dynamically generated gibberish, or a CSS-in-JS project, like glamerous. Even strictly-followed naming conventions like BEM can be a form of total isolation.

Total abstraction might come from a project, like Tachyons, that gives you a fixed set of class names to use for styling (Tailwind is like a configurable version of that), or a programmatic tool (like Atomizer) that turns specially named HTML class attributes into a stylesheet with exactly what it needs.

It’s the middle ground that has problems. It’s using a naming methodology, but not holding strictly to it. It’s using some styles in components, but also having a global stylesheet that does random other things. Or, it’s having lots of developers contributing to a styling system that has no strict rules and mixes global and scoped styles. Any stylesheet that grows and grows and grows. Fighting it by removing some unused styles isn’t a real solution (and here’s why).

Note that the web is a big place and not all projects need a scaling solution. A huge codebase with hundreds of developers that needs to be maintained for decades absolutely does. My personal site does not. I’ve had my fair share of styling problems, but I’ve never been so crippled by them that I’ve needed to implement something as strict as Atomic CSS (et al.) to get work done. Nor at at any job I’ve had so far. I see the benefits though.

Imagine the scale of Twitter.com over a decade! Nicolas has a great thread where he compares Twitter’s PWA against Twitter’s legacy desktop website.

The legacy site’s CSS is what happens when hundreds of people directly write CSS over many years. Specificity wars, redundancy, a house of cards that can’t be fixed. The result is extremely inefficient and error-prone styling that punishes users and developers alike.

The post Scaling CSS: Two Sides of a Spectrum appeared first on CSS-Tricks.

Keyboard-Only Focus Styles

Like Eric Bailey says, if it’s interactive, it needs a focus style. Perhaps your best bet? Don’t remove the dang outlines that focusable elements have by default. If you’re going to rock a button { outline: 0; }, for example, then you’d better do a button:focus { /* something else very obvious visually */ }. I handled a ticket just today where a missing focus style was harming a user who relies on visual focus styles to navigate the web.

But those focus styles are most useful when tabbing or otherwise navigating with a keyboard, and less so when they are triggered by a mouse click. Now we’ve got :focus-visible! Nelo writes:

TLDR; :focus-visible is the keyboard-only version of :focus.

Also, the W3C proposal mentions that :focus-visible should be preferred over :focus except on elements that expect a keyboard input (e.g. text field, contenteditable).

(Also see his article for a good demo on why mouse clicking and focus styles can be at odds, beyond a general dislike of fuzzy blue outlines.)

Browser support for :focus-visible is pretty rough:

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

Chrome Opera Firefox IE Edge Safari
No No 4* No No No

Mobile / Tablet

iOS Safari Opera Mobile Opera Mini Android Android Chrome Android Firefox
No No No No No 62*

But it does have Firefox support, and as Lea Verou says:

… once Chrome ships its implementation it will explode in a matter of 1-2 months.

That’s generally how things go these days. Once two major browsers have support — and one of them is Chrome — that’s a huge enough slice of the web that can start using it. Especially when it can be done as safely as this property.

Safely, as in, there is an official polyfill, meaning you can nuke default focus styles and just use :focus-visible styles:

/* Remove outline for non-keyboard :focus */
*:focus:not(.focus-visible) { outline: none;
} /* Optional: Customize .focus-visible */
.focus-visible { outline: lightgreen solid 2px;
}

But, as Patrick H. Lauke documented, you can do it even without the polyfill, using careful selector usage and un-doing styles as needed:

button:focus { /* Some exciting button focus styles */ }
button:focus:not(:focus-visible) { /* Undo all the above focused button styles if the button has focus but the browser wouldn't normally show default focus styles */
}
button:focus-visible { /* Some even *more* exciting button focus styles */ }

Seems like a nice improvement for the web.

The post Keyboard-Only Focus Styles appeared first on CSS-Tricks.

Dark modes with CSS

With the introduction of dark mode in macOS, Safari Technology Preview 68 has released a new feature called prefers-color-scheme which lets us detect whether the user has dark mode enabled with a media query.

That’s right. If this becomes a little bit more supported in other browsers, then we might potentially soon have a way to toggle on night modes with a few lines of CSS!

Recently Mark Otto described how we can start using prefers-color-scheme today in order to create themes that dynamically adjust to the new user setting. And the neat thing about this post is that Mark sort of frames it as an accessibility issue and shows how he uses it on his own website to adjust images so that they’re not too bright for the user:

@media (prefers-color-scheme: dark) { img { opacity: .75; transition: opacity .5s ease-in-out; } img:hover { opacity: 1; }
}

In the code above, Mark detects whether the user has dark mode enabled with the media query and then makes the images darker so that they match a dark background. This reminds me of an excellent post by Marcin Wichary where he explores a similar technique and goes one step further by adding all sorts of filters to make sure they have a much higher contrast.

Andy Clarke also wrote up some thoughts about how to take this fancy new CSS feature and how we might apply a dark theme across our website. He describes how to pick colors so our light/dark themes are consistent in terms of branding and how we might want to use a lighter font-weight for darker backgrounds. He writes:

Designing for dark mode shouldn’t stop with choosing darker colours. You should also consider altering typography styles to maintain readability for people who use dark mode. Light text against dark backgrounds appears higher in contrast than when the same colours are used in reverse, so to make your dark mode designs easier to read you’ll need to add more white/dark space to your text.

If your fonts offer a lighter weight, using that for your dark mode design will open up the letterforms and make them appear further apart…

What was that? It sure sounded like the joyous applause of typography nerds and designers everywhere!

The post Dark modes with CSS appeared first on CSS-Tricks.

The “C” in CSS: The Cascade

Following up from Geoff’s intro article on The Second “S” in CSS, let’s now move the spotlight to the “C” in CSS — what we call the Cascade. It’s where things start to get messy, and even confusing at times.

Have you ever written a CSS property and the value doesn’t seem to work? Maybe you had to turn to using !important to get it going. Or perhaps you resorted to writing the CSS inline on the element in the HTML file.

<div style="background:orange; height:100px; width:100px;"> Ack, inline!
</div>

Speaking of inline styles, have you wondered why SVG editors use them instead of a separate CSS file? That seems kinda weird, right?

<svg id="icon-logo-star" viewBox="0 0 362.62 388.52" width="100%" height="100%"> <style> .logo { fill: #ff9800; } </style> <title>CSS Tricks Logo</title> <path class="logo" d="M156.58 239l-88.3 64.75c-10.59 7.06-18.84 11.77-29.43 11.77-21.19 0-38.85-18.84-38.85-40 0-17.69 14.13-30.64 27.08-36.52l103.6-44.74-103.6-45.92C13 142.46 0 129.51 0 111.85 0 90.66 18.84 73 40 73c10.6 0 17.66 3.53 28.25 11.77l88.3 64.75-11.74-104.78C141.28 20 157.76 0 181.31 0s40 18.84 36.5 43.56L206 149.52l88.3-64.75C304.93 76.53 313.17 73 323.77 73a39.2 39.2 0 0 1 38.85 38.85c0 18.84-12.95 30.61-27.08 36.5l-103.61 45.91L335.54 239c14.13 5.88 27.08 18.83 27.08 37.67 0 21.19-18.84 38.85-40 38.85-9.42 0-17.66-4.71-28.26-11.77L206 239l11.77 104.78c3.53 24.72-12.95 44.74-36.5 44.74s-40-18.84-36.5-43.56z"></path>
</svg>

Well, the cascade has a lot to do with this. Read on to find out how styling methods affect what’s being applied to your elements and how to use the cascade to your advantage because, believe me, it’s a wonderful thing when you get the hang of it.

TL;DR: Jump right to the CSS order diagram for a visual of how everything works.

The cascade cares about how and where styles are written

There are a myriad of ways you can apply CSS rules to an element. Below is an example of how stroke: red; can be applied to the same element. The examples are ordered in ascending priority, where the highest priority is at the bottom:

<!-- Inheritance -->
<g style="stroke: red"> <rect x="1" y="1" width="10" height="10" /> <!-- inherits stroke: red -->
</g> <!-- Inline attributes -->
<rect x="1" y="1" width="10" height="10" stroke="red" /> <!-- External style sheet -->
<link rel="stylesheet" href="/path/to/stylesheet.css"> <!-- Embedded styles -->
<style> rect { stroke: red; }
</style> <!-- Different specificity or selectors -->
rect { stroke: red; }
.myClass { stroke: red; }
#myID { stroke: red; } <!-- Inline style -->
<g style="stroke: red"></g> <!-- Important keyword -->
<g style="stroke: red !important"></g>

Inheritance? Embedded? External? Inline? Specificity? Important? Yeah, lots of terms being thrown around. Let’s break those down a bit because each one determines what the browser ends up using when a web page loads.

Elements can inherit styles from other elements

Both HTML and SVG elements can inherit CSS rules that are applied to other elements. We call this a parent-child relationship, where the element the CSS is applied to is the parent and the element contained inside the parent is the child.

<div class="parent"> <div class="child">I'm the child because the parent is wrapped around me.</div>
</div>

If we set the text color of the parent and do not declare a text color on the child, then the child will look up to the parent to know what color its text should be. We call that inheritance and it’s a prime example of how a style cascades down to an element it matches… or “bubbles up” the chain to the next matched style.

However, inheritance has the lowest priority among styling methods. In other words, if a child has a rule that is specific to it, then the inherited value will be ignored, even though the inherited value may have an important keyword. The following is an example:

<div class="parent" style="color: red !important;"> <div class="child">I'm the child because the parent is wrapped around me.</div>
</div>

See the Pen Child ignores inline inheritance with !important by Geoff Graham (@geoffgraham) on CodePen.

SVG inline attributes

For SVG elements, we can also apply styles using inline attributes, where those have the second lowest priority in the cascade. This means the CSS rules in a stylesheet will be able to override them.

<rect x="1" y="1" width="10" height="10" stroke="red" />
rect { stroke: blue;
}

See the Pen Stylesheet overrides SVG inline attributes by Geoff Graham (@geoffgraham) on CodePen.

Most SVG editors use inline attributes for portability; that is, the ability to copy some elements and paste them elsewhere without losing the attributes. Users can then use the resultant SVG and style its elements using an external stylesheet.

Stylesheets

Stylesheets are divided into two flavors: external and embedded:

<!-- External style sheet -->
<link rel="stylesheet" href="/path/to/stylesheet.css"> <!-- Embedded styles -->
<style> div { border: 1px solid red }
</style>

Embedded styles have the same priority as external stylesheets. Therefore, if you have the same CSS rules, ordering rules applies.

See the Pen Embedded styles override stylesheet rules by Geoff Graham (@geoffgraham) on CodePen.

All stylesheets follow ordering rules, where files that are defined later, will have higher priority than those defined earlier. In this example, stylesheet-2.css will take precedence over the stylesheet-1.css file because it is defined last.

<link rel="stylesheet" href="/path/to/stylesheet-1.css">
<link rel="stylesheet" href="/path/to/stylesheet-2.css">

Specificity or selectors

How you select your elements will also determine which rules are applied, whereby tags (e.g. <p>, <div>), classes (e.g. .my-class) and IDs (e.g. #myI-id) have ascending priorities.

See the Pen Specificity by selectors by Geoff Graham (@geoffgraham) on CodePen.

In the example above, if you have a div element with both .my-class and #my-id, the border will be red because IDs have higher priority than classes and tags.

*Specificity has higher priority than ordering rules, therefore, irrespective if your rule is at the top or bottom. Specificity still has higher priority and will be applied.

Ordering

CSS rules always prioritize from left-to-right, then from top-to-bottom.

<!-- Blue will be applied because it is on the right -->
<div style="border: 1px solid red; border: 1px solid blue;"></div> <style> div { border: 1px solid red; border: 1px solid blue; /* This will be applied because it is at the bottom */ }
</style>

Inline styles

Inline styles have the second highest priority, just below the !important keyword. This means that inline styles are only overridden by the important keyword and nothing else. Within inline styles, normal ordering rules applies, from left-to-right and top-to-bottom.

<div style="1px solid red;"></div>

The important keyword

Speaking of the !important keyword, it is used to override ordering, specificity and inline rules. In other words, it wields incredible powers.

Overriding inline rules

<style> div { /* This beats inline styling */ border: 1px solid orange !important; /* These do not */ height: 200px; width: 200px; }
</style> <div style="border: 1px solid red; height: 100px; width: 100px;"></div>

In the example above, without the important keyword, the div would have a red border because inline styling has higher priority than embedded styles. But, with the important keyword, the div border becomes orange, because the important keyword has higher priority than inline styling.

Using !important can be super useful, but should be used with caution. Chris has some thoughts on situations where it makes sense to use it.

Overriding specificity rules

Without the important keyword, this div border will be blue, because classes have higher priority than tags in specificity.

<style> /* Classes have higher priority than tags */ .my-class { border: 1px solid blue; height: 100px; width: 100px; } div { border: 1px solid red; height: 200px; width: 200px; }
</style> <div class="my-class"></div>

See the Pen Classes beat tags by Geoff Graham (@geoffgraham) on CodePen.

But! Adding the important keyword to the tag rules tells the element to ignore the cascade and take precedence over the class rules.

<style> .my-class { border: 1px solid red; } /* The important keyword overrides specificity priority */ .my-class { border: 1px solid blue !important; }
</style> <div class="my-class"></div>

See the Pen !important ignores the cascade by Geoff Graham (@geoffgraham) on CodePen.

Overriding ordering rules

OK, so we’ve already talked about how the order of rules affects specificity: bottom beats top and right beats left. The surefire way to override that is to put !important into use once again.

In this example, the div will take the red border, even though the blue border is the bottom rule. You can thank !important for that handiwork.

<style> div { border: 1px solid red !important; } /* This wins, despite the ordering */ div { border: 1px solid blue; }
</style> <div></div>

See the Pen Important wins over ordering by Geoff Graham (@geoffgraham) on CodePen.

Visualizing the cascade

Who knew there was so much meaning in the “C” of CSS? We covered a ton of ground here and hopefully it helps clarify the way styles are affected and applied by how we write them. The cascade is a powerful feature. There are opinions galore about how to use it properly, but you can see the various ways properties are passed and inherited by elements.

More of a visual learner? Here’s a chart that pulls it all together.

Download chart

The post The “C” in CSS: The Cascade appeared first on CSS-Tricks.

A Bunch of Options for Looping Over querySelectorAll NodeLists

A common need when writing vanilla JavaScript is to find a selection of elements in the DOM and loop over them. For example, finding instances of a button and attaching a click handler to them.

const buttons = document.querySelectorAll(".js-do-thing");
// There could be any number of these! // I need to loop over them and attach a click handler.

There are SO MANY ways to go about it. Let’s go through them.

forEach

forEach is normally for arrays, and interestingly, what comes back from querySelectorAll is not an array but a NodeList. Fortunately, most modern browsers support using forEach on NodeLists anyway.

buttons.forEach((button) => { button.addEventListener('click', () => { console.log("forEach worked"); });
});

If you’re worried that forEach might not work on your NodeList, you could spread it into an array first:

[...buttons].forEach((button) => { button.addEventListener('click', () => { console.log("spread forEach worked"); });
});

But I’m not actually sure if that helps anything since it seems a bit unlikely there are browsers that support spreads but not forEach on NodeLists. Maybe it gets weird when transpiling gets involved, though I dunno. Either way, spreading is nice in case you want to use anything else array-specific, like .map(), .filter(), or .reduce().

A slightly older method is to jack into the array’s natural forEach with this little hack:

[].forEach.call(buttons, (button) => { button.addEventListener('click', () => { console.log("array forEach worked"); });
});

Todd Motto once called out this method pretty hard though, so be advised. He recommended building your own method (updated for ES6):

const forEach = (array, callback, scope) => { for (var i = 0; i < array.length; i++) { callback.call(scope, i, array[i]); }
};

…which we would use like this:

forEach(buttons, (index, button) => { console.log("our own function worked");
});

for .. of

Browser support for for .. of loops looks pretty good and this seems like a super clean syntax to me:

for (const button of buttons) { button.addEventListener('click', () => { console.log("for .. of worked"); });
}

Make an array right away

const buttons = Array.prototype.slice.apply( document.querySelectorAll(".js-do-thing")
);

Now you can use all the normal array functions.

buttons.forEach((button) => { console.log("apply worked");
});

Old for loop

If you need maximum possible browser support, there is no shame in an ancient classic for loop:

for (let i = 0; i < buttons.length; ++i) { buttons[i].addEventListener('click', () => { console.log("for loop worked"); });
}

Libraries

If you’re using jQuery, you don’t even have to bother….

$(".buttons").on("click", () => { console.log("jQuery works");
});

If you’re using a React/JSX setup, you don’t need think about this kind of binding at all.

Lodash has a _.forEach as well, which presumably helps with older browsers.

_.forEach(buttons, (button, key) => { console.log("lodash worked");
});

Poll

Twitter peeps:

Also here’s a Pen with all these options in it.

The post A Bunch of Options for Looping Over querySelectorAll NodeLists appeared first on CSS-Tricks.

Fun Tip: Use calc() to Change the Height of a Hero Component

The concept of Fluid Typography was tossed around a couple of years ago. The main idea is that if you know what size your font is at two different viewport sizes, then you can have the font scaling smoothly between the two sizes. We had a jQuery solution for this in FitText (meant of headings, of course) until the calc() function was shipped giving us a pure CSS solution.

p { font-size: calc(16px + (24 - 16)*(100vw - 400px)/(800 - 400));
}

See the Pen Fluid Typography by Martino Stenta (@martinostenta) on CodePen.

The important numbers here are 24px (the larger font up to 800px viewports) and 16px (the smaller font size down to 400px viewports). I wouldn’t use the terms “minimum” or “maximum” to describe font sizes and viewports in this context because it is a little misleading. In fact, you still need to provide a default font size for viewports smaller than 400px and bigger than 800px — otherwise, the font will keep getting smaller (or bigger) with the same scale of the equation. Or, if you are fancy, you could define another scale for bigger screen sizes.

See the Pen Fluid Typography with reset size by Martino Stenta (@martinostenta) on CodePen.

It works really well and you should definitely check the math behind this.

Padding and line height?

I liked the concept of Fluid Typography so much that I asked myself if it could work with other properties. And it does! You can’t use a percentage, but as long as you stick with px, em or rem units, then it’s OK. I’m a pixel guy, so all my experiments have used those, but there is this neat generatorthat helps you with conversions if you need it.

So, back to padding and line-height. Using the same calc() logic, we can achieve a fully fluid *layout* with fixed values for defined screen sizes.

See the Pen Pure CSS Variable Padding, Font Size and Line Height by Martino Stenta (@martinostenta) on CodePen.

I implemented this idea on this website, but kept it to font-size and line-height. And, yes, it gets easier to look past all that math and put to use the more you work with it.

See the Pen Working Example of calc() on font-size and line-hieght by Martino Stenta (@martinostenta) on CodePen.

A digression about “Hero” components

If you’re like me, then you might take issue with what we all have come to know as the hero component. It’s ubiquitous to the extent that it’s become a staple in design systems (like Bootstrap) and you may have even seen it satirized on sites like this.

My main gripe concerns the best way to make them responsive. If it’s not a *full screen* hero (i.e. takes over the entire viewport at any size), then I usually ask the designer how the page should behave. There’s often a proportion of the hero page that works fine, so that allows me to use padding-bottom in % with absolute positioning of the inner content. That tactic works most of the time,

This is fun and it works fine especially on the desktop version of a website. You end up with a neat hero section, the proportion is good and the content is centered.

See the Pen Standard hero section with ‘padding-bottom’ by Martino Stenta (@martinostenta) on CodePen.

But what happens when you start shrinking the viewport? The hero remains readable up to a point, you really need to change the proportion.

Assuming we are working with a desktop-first responsive approach, we could start with a horizontal rectangle that scales down to the point where we’re left with a vertical rectangle on small screens.

Hero component with different proportions based on device

This is a PITA because you could end up with many lines of CSS to have a nice and readable hero section at various breakpoints.

There has to be a better way, right? What if the hero could increase its height while the page width gets narrower?

Back to fluidity!

So, I turned back to the calc() function that worked in those other situations, like making the browser handle the math and scale things accordingly as the viewport changes.

Here’s the CSS from the Fluid Typography example we started with:

p { width: 100%; max-width: 1200px; margin: 0 auto; font-family: 'Open Sans', sans-serif; font-size: calc(24px + (18 - 24)*(100vw - 400px)/(1200 - 400)); line-height: 1.5; padding: 10px;
}

Here’s what we want: a hero component that gets bigger while you shrink the page. I used pixel units for the fluid part and percentages everywhere else.

Here’s a screencast of how the solution I landed on:

Live Demo

This is pretty useful when you want to give more vertical space to the text. Shrinking the viewport width from large to small will end up having more lines for the same text, since the font size can’t be too small.

See the Pen Hero section with calc() by Martino Stenta (@martinostenta) on CodePen.

Pretty nice, right? Yet another way calc() proved it could solve a scenario for me.

Yes, there are some caveats

Browser support is very good, tallying almost 93% of the users (at the time of writing), with the main exception being Opera mini.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

Chrome Opera Firefox IE Edge Safari
19* 15 4* 10 12 6*

Mobile / Tablet

iOS Safari Opera Mobile Opera Mini Android Android Chrome Android Firefox
6.0-6.1* 46 No 67 69 62

Also, remember that this calc() technique supports only px, em, and rem units. But the examples we covered here are pretty easy to convert units for things like padding-bottom percentages to pixels since the hero is typically 100% in width.

Oh! And remember to reset your values before and after the breakpoints in the calc() function. Otherwise you’ll end up with either very big or very small values for the target properties.

What say you?

This is probably just one way we can handle the situation and it was primarily driven by my interest in the calc() function. So, that begs the question: how have you handled scaling hero component height? Have you put calc() to use for it? Do you prefer wrangling breakpoints at various widths? Is there something else you use? Light up the comments!

The post Fun Tip: Use calc() to Change the Height of a Hero Component appeared first on CSS-Tricks.

Rocking California’s “I Voted” Sticker in CSS for Election Day 2018

Oh hey, so tomorrow (tomorrow!) is Election Day here in the United States. We’re not in the business of making political endorsements or anything like that at CSS-Tricks, though we do endorse that everyone exercise their right to vote.

I did exactly that two years ago and posted a CSS rendition of the “I Voted” sticker that came with my California mail-in ballot.

See the Pen I Voted Sticker by Geoff Graham (@geoffgraham) on CodePen.

Fast forward to today, and I received a new sticker in the ballot sporting a fresh design:

Credit: Los Angeles Magazine (source)

I have a little time, so I’m going to try to re-create this sticker in CSS and walk through my thought process as I do it. Feel free to follow along if you’d like!

Breaking down the elements

Anytime I’m given a design of any kind, I like to pretend that my eyes have the superpower of X-ray vision and can see through the design as if it were a skeleton. This helps me start to think through how many elements I might use in the HTML.

OK, I think I’m going to start with something like this:

<!-- Main Circle -->
<div class="sticker"> <div class="sticker__top"> <!-- Will use ::before and ::after to create halves --> <h1>I Voted</h1> </div> <div class="sticker__bottom"> <!-- The list of languages --> <ul> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> </ul> </div>
</div>

I’m also going to throw in some base styles on the <body> so I can jump right into the rest of the sticker.

See the Pen “I Voted” Sticker HTML by Geoff Graham (@geoffgraham) on CodePen.

OK, nothing fancy so far. Really just looks like an unordered list with a heading with some terrible contrast between the content and background.

Working on the main sticker container

I think I’ll set up the container, which is the main circle. I’m going to use a fixed width and height, then use border-radius to round it out and into the shape of a circle.

Oh, and I ought to take care of that dark text and also add a border while I’m at it, so I can see what I’m doing.

.sticker { border: 20px solid #fff; border-radius: 100%; color: #fff; height: 400px; width: 400px; }

See the Pen “I Voted” Sticker HTML 2 by Geoff Graham (@geoffgraham) on CodePen.

The alignment is all off. Seems like a good spot to drop in some flexbox. This will allow me to center our elements horizontally. I think going with a single-column layout will take care of the vertical alignment.

.sticker { display: flex; flex-flow: column; align-items: center; border: 20px solid #fff; border-radius: 100%; color: #fff; height: 400px; width: 400px;
}

Yep, that helps.

See the Pen “I Voted” Sticker HTML 3 by Geoff Graham (@geoffgraham) on CodePen.

The last thing I want to do with the sticker for now is split it up into two halves — a top and a bottom. OK, so yeah, I have explicit elements for those in the HTML (.sticker__top and .sticker__bottom). I could use background-color on each element to make the top half blue and bottom half red, but I actually like the idea of using a linear gradient instead with a hard stop at the halfway mark.

.sticker { background-image: linear-gradient( to bottom, #080968, #080968 50%, #080968 50%, #F81616 50% ); border: 20px solid #fff; border-radius: 100%; color: #fff; display: flex; flex-flow: column; align-items: center; height: 400px; width: 400px;
}

Hey now, looking much sharper already!

See the Pen “I Voted” Sticker HTML 4 by Geoff Graham (@geoffgraham) on CodePen.

Time to deal with the top half

The top and bottom halves both occupy 50% of the sticker’s height, so the selectors can be combined to hit them both at once. Plus, I’m using flexbox, so I can simply flex those items.

.sticker__top,
.sticker-bottom { flex: 0 50%;
}

The top half is super weird. The way I see it, there’s two rows: one that contains the stars and stripes and the other that contains the heading. I’m going to turn to flexbox again to draw that layout.

.sticker__top { display: flex; flex-flow: row wrap; position: relative;
}

That’s not really going to change much at the moment because, well, I haven’t done anything to define elements for the stars and stripes in the HTML. I’m thinking of using the ::before and ::after pseudo elements on .sticker__top to make those. Again, they can be combined since they share some common properties and values.

.sticker__top::before,
.sticker__top::after { content: ""; height: 45%; /* Had to play with this a bit */ margin-top: 2em; /* Move away from the top edge of the sticker */
}

I’m going to cheat and use SVG for the stars. I mean, I guess that’s not cheating but it sorta feels like a deviation from a “pure” CSS way of doing things. Oh well.

That said, the stripes can definitely be made in CSS, again, with the same linear gradient background technique that’s used to split the sticker up into blue and red halves.

.sticker__top::before { background-image: url("/path/to/star/image.svg"); background-size: 35px; /* Magic number, depends on the image used. */
} .sticker__top::after { background-image: linear-gradient( to bottom, #F81616, #F81616 14%, transparent 14%, transparent 28%, #F81616 28%, #F81616 42%, transparent 42%, transparent 56%, #F81616 56%, #F81616 70%, transparent 70%, transparent 84%, #F81616 84%, #F81616 98%, transparent 100% );
}

That’s cool but, crap, things are out of order.

See the Pen “I Voted” Sticker HTML 5 by Geoff Graham (@geoffgraham) on CodePen.

I’m so thankful flexbox has an order property. I’m going to order the stars, stripes and heading at 1, 2 and 3, respectively,

.sticker__top::before { /* Same as before... */ order: 1;
} .sticker__top::after { /* Same as before... */ order: 2;
} .sticker__top h1 { order: 3;
}

If I stop here, the shape of the stars and stripes would be all off and the heading font would be sloppy.

border-radius is still a good way to get the stars and stripes to follow the same circular path as the sticker. The rub is that the bottoms of them have to maintain a flat edge. Since border-radius is a shorthand property, I’m going to drop border-top-left-radius on the stars and border-top-right-radius on the stripes.

It’s also worth noting that the stripes are a little wider than the stars. Maybe a 55-45 split? I don’t know. I’ll go with that and also use relative positioning on the stripes so I can push them to the right a bit to add separation between them and the stars.

.sticker__top::before { /* Same as before... */ flex: 45%;
} .sticker__top::after { /* Same as before... */ flex: 55%; position: relative; left: 10px;
}

The stars and stripes should flex with the size and width of the heading. I had to play with the font family, font size, letter spacing, and text transform to get something that looks pretty nice. In case you’re wondering, I wound up using Raleway for the font. It’s not precise, but close enough… at least to my untrained typographical eye.

.sticker__top h1 { font-family: 'Raleway', sans-serif; font-size: 4em; letter-spacing: 3px; line-height: 0; text-transform: uppercase; order: 3;
}

See the Pen “I Voted” Sticker HTML 6 by Geoff Graham (@geoffgraham) on CodePen.

Alright, so now the bottom half is making my skin crawl. Gotta tackle that.

Style up the bottom half

So much has already been done. The element for bottom half is already there in the HTML and is sized and positioned the way it should be. I think stripping out the bullet points of the list items and removing the left padding from the unordered list will clean things up a lot.

.sticker__bottom ul { list-style: none; padding: 0; width: 100%; /* Gotta take up the all of the bottom half */
}

But, that’s not going to cut it completely. I want that list to run horizontally, wrap lines, and to allow the list items to occupy open space. Yep, that sounds like flexbox again.

.sticker__bottom ul { display: flex; flex-flow: row wrap; align-items: flex-start; justify-content: flex-start; /* same as before... */
} .sticker__bottom li { flex: auto; /* Flex as much as you need, guys */ margin: .75em; /* A liiiiitle breathing room between items */
}

See the Pen “I Voted” Sticker HTML 7 by Geoff Graham (@geoffgraham) on CodePen.

Now I have to make a few tweaks to .sticker__bottom. Specifically, I’m going to make it a little narrower (80% of the full sticker width) to get it off the edge of the sticker and then round its edges… though it might not actually need rounded corners since content is not going to overflow.

.sticker__bottom { border-bottom-right-radius: 100%; border-bottom-left-radius: 100%; width: 80%;
}

And, now center the text. I guess that can go on the parent .sticker element since nothing on the sticker is technically left-justified.

.sticker { /* same as before... */ text-align: center;
}

Finally, I’m going to do my best to replace the dummy content with the “I Voted” translations. Let me go look those up.

(Heads over to Google Translate.)

Meh, I couldn’t find everything I needed. I’m sure it’s my lack of patience, but I wound up using some alternatives:

<ul> <li>Yo voté</li> <li>我投票</li> <li>나는 투표했다</li> <li>Bumoto ako</li> <li>Я проголосував</li> <li>मैने मतदान किया</li> <li>أنا صوتت</li> <li>Ik stemde</li> <li>Szavaztam</li> <li>ฉันโหวตแล้ว</li> <li>Anigu waxaan codsaday</li> <li>Tôi đã bầu chọn</li>
</ul>

I’m going to have to play around with the font size and to get the same sort of alignment as the IRL sticker, which has rows of: 4 items, 3 items, 3 items, 1 item, 1 item.

Here’s where I landed:

.sticker__bottom ul { display: flex; flex-flow: row wrap; font-size: .75em; align-items: flex-start; justify-content: flex-start; list-style: none; padding: 0; width: 100%;
}

To get the last two items off the same line, I’m going to single out the second-to-last one using :last-child() so that both of them always flex 100%:

.sticker__bottom li:nth-child(11) { flex: 100%;
}

See the Pen “I Voted” Sticker HTML 8 by Geoff Graham (@geoffgraham) on CodePen.

Ding, ready!

I’m going to call this one baked. I know, I know. I should cross-browser test. It would also be wise to find graceful fallbacks for older browsers that do not support flexbox. And, some responsiveness would be nice to have. Maybe someone would like to take those up and share. 😉

Is this the best way to make the sticker? Probably not. For example, I bet there are some interesting things that can be done with clip-path instead of the way I fumbled through background gradients. And, if I had to do it again, I might even consider going with a CSS Grid layout on the parent because there are clearly opportunities to work in two directions instead of one.

But that’s the beauty of CSS. There’s more than one way to accomplish something.

Happy Election Day, friends. 🇺🇸

The post Rocking California’s “I Voted” Sticker in CSS for Election Day 2018 appeared first on CSS-Tricks.

Simple Named Grid Areas

I think of named grid areas in CSS Grids as bring-your-own syntactic sugar. You don’t absolutely need them (you could express grid placement in other ways), but it can make that placement more intuitive. And, hey, if I’m wrong about that, correct me in the comments.

Say you set up a 3-column grid:

.grid { display: grid; grid-gap: 1rem; grid-template-columns: 200px 1fr 1fr;
}

No rows defined there; those are implicit and will appear as needed. We could define them, we just aren’t, because like most situations in web design, we don’t care how tall the items are — the height will grow as needed to accomodate the content.

Now, how do we place something in that very top-left position in the grid? We could tell the grid to place it there like this:

.item { grid-column: 1 / 2; /* start at the first grid column line and end at the second */
}

That works, although that .item better be the first child of .grid. Otherwise, something else may implicitly be placed there and .item will kick down to the next open row. If we wanted to be super sure to place it in the top-left, we could do the row as well:

.item { grid-column: 1 / 2; grid-row: 1 / 2;
}

Now it will be in the top-left for sure, even if other items are explicitly placed there (they’ll just overlap). We can even shorten things up with the grid-area property:

.item { grid-area: 1 / 1 / 2 / 2;
}

All those 1’s and 2’s might be intuitive enough for now, but the numbers become a bit much in more complex grids involving both column and row placement.

Check this. While we are defining the columns, we can name them with a separate property:

.grid { display: grid; grid-gap: 1rem; grid-template-columns: 200px 1fr 1fr; grid-template-areas: "pro a b" "pro c d";
}

Every quoted group in grid-template-areas is a row. Inside are names I just made up. Could be just about anything, as long as it makes sense to you. See how the word “pro” is repeated twice there on two rows? That’s important, as it’s saying that we could place a grid item where that value “pro” is and it will be in the first of three columns and span two rows. Pretty intuitive, yeah?

We place it like this:

.pro-features { /* rather than */ grid-area: 1 / 1 / 2 / 3; /* we can now do */ grid-area: pro;
}

Here’s that simple example:

See the Pen Simple Named Grid Areas by Chris Coyier (@chriscoyier) on CodePen.

Want to get even more descriptive with a grid? Try drawing it in your CSS comments.

The post Simple Named Grid Areas appeared first on CSS-Tricks.