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.

Why monday.com is the Universal Team Management Tool for Your Team

This platform is perfect for teams sized at 2-to-200 — and gives every employee the same level of transparency.

Every project management tool seeks to do the same instrumental thing: keep teams connected, on task and on deadline to get major initiatives done. But the market is getting pretty crowded, and for good reason — no platform seems to have gotten the right feel for what people need to see, and how that information should be displayed so that it’s both actionable/relevant and contextualized.

That’s why monday.com is worth a shot. The platform is based off a simple, but powerful idea: that as humans, we like to feel like we’re contributing to part of a greater/effort good — an idea that sometimes gets lost in the shuffle as we focus on the details of getting stuff done. So projects are put onto a task board (think of it like a digital whiteboard), where everyone can have the same level of visibility into anyone else who’s contributing a set of tasks. That transparency breaks down the silos between teams that cause communication errors and costly project mistakes — and it’s a beautiful, simple way to connect people to the processes that drive forward big business initiatives.

Whether you’re part of a tech-forward team or not, monday.com is a welcome relief to cumbersome Excel files, messy (physical) whiteboards, or meetings that waste time when actual work could be completed. The scalable, intuitive structure can effectively work for a team of two, or an international team of 2,000+ — and a beautiful, color-coded board lays out tasks you can cleanly see and tag for various stages of completion. That way, employees can see exactly what needs to be done (and who needs to do it), while managers can optimize their time re-allocating resources as necessary to optimize processes. It’s a win-win.

monday.com also allows teams to communicate within the platform, cutting down on the amount of laborious sifting through various email threads to figure out a workflow. Messages can be sent inside of tasks — so all the communication is contextualized before meeting resolution or seeking it. The platform also supports uploads, so documents and videos can be added to facilitate more collaboration, and integration with other productivity apps. So if your team is already using tools like Slack, Google Calendar, Dropbox, Microsoft Excel, Trello, and Jira, there’s specific, clean shortcuts to integrate the information from those platforms into monday.com. And even beyond team communication and management, you can use monday.com for client-facing exchanges, so all your messages are consolidated into a single place.

The platform recently raised $50M in funding, and received nods from the likes of Forbes, Entrepreneur, Business Insider, and more for its ability to empower international teams to do better work together. Best of all, unlike other team management software, which can be pricey and time-intensive to scope, test and run, you can try monday.com today — for free.

What can this app do?

  • Creating and managing a project’s milestones
  • Creating and assigning tasks
  • Attaching files to any project’s table projects on the go.
  • Using mobile applications to manage projects
  • Communicating with your team members
  • Updating team using the news feed
  • Keeping clients in the loop
  • Organizing the organization into teams
  • Creating detailed project charts and reports
  • Tracking the time your team members spend on tasks
  • Managing a project’s financials
  • Website as well as a desktop app for Mac and Windows

monday.com to make every user feel empowered and part of something bigger than their own individual tasks, and as a result, to boost collective productivity and transparency.

The post Why monday.com is the Universal Team Management Tool for Your Team 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.

CSS and Network Performance

JavaScript and images tend to get the bulk of the blame for slow websites, but Harry explains very clearly why CSS is equally to blame and harder to deal with:

  1. A browser can’t render a page until it has built the Render Tree;
  2. the Render Tree is the combined result of the DOM and the CSSOM;
  3. the DOM is HTML plus any blocking JavaScript that needs to act upon it;
  4. the CSSOM is all CSS rules applied against the DOM;
  5. it’s easy to make JavaScript non-blocking with async and defer
    attributes;
  6. making CSS asynchronous is much more difficult;
  7. so a good rule of thumb to remember is that your page will only render as quickly as your slowest stylesheet.

There are lots of options to do better with this, including some interesting things that HTTP/2 unlocks.

Check out Šime Vidas’s takeaways as well. It’s all fascinating, but the progressive rendering stuff is particularly cool. I suspect many CSS-in-JS libraries could/should help with doing things this way.

Direct Link to ArticlePermalink

The post CSS and Network Performance 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.

Why Browsers Download Stylesheets with Non-Matching Media Queries

Say you have a stylesheet linked up like this:

<link href="mobile.css" rel="stylesheet" media="screen and (max-width: 600px)">

But as the page loads, you’re on a desktop browser where the screen is 1753px wide. The browser should just skip loading that stylesheet entirely, right? It doesn’t. Thomas Steiner explains:

it turns out that the CSS spec writers and browser implementors are actually pretty darn smart about this:

The thing is, the user could always decide to resize their window (impacting width, height, aspect ratio), to print the document, etc., and even things that at first sight seem static (like the resolution) can change when a user with a multi-screen setup moves a window from say a Retina laptop screen to a bigger desktop monitor, or the user can unplug their mouse, and so on.

What browsers do do (heh, 💩) is apply a Lowest download priority.

Direct Link to ArticlePermalink

The post Why Browsers Download Stylesheets with Non-Matching Media Queries appeared first on CSS-Tricks.