Short note on the accessibility of styled form controls

Styling and accessibility are often at odds with each other. Scott O’Hara has this repo that shows how the two can work really well together in the context of form controls.

The trade-offs between native and styled controls reminds me of Eric Bailey’s case study on focus styles:

A common misconception is that the focus style can only use the outline property. It’s worth noting that :focus is a selector like any other, meaning that it accepts the full range of CSS properties. I like to play with background color, underlining, and other techniques that don’t adjust the component’s current size, so as to not shift page layout when the selector is activated.

The nice thing about Scott’s repo is that it serves as a baseline that can be pulled into a project and customized from there. Sort of like WTF, forms? but with a clear—ahem—focus on accessibility. Styles are considered, but less the point.

While we’re on the topic, let’s not let Dave Rupert’s “Nutrition Cards for Accessible Components” go unnoticed. It also shipped recently and—aside from being a clever idea—is a truly useful thing to reference the accessibility expectations of specific components. Definitely worth a bookmark. 🔖

Direct Link to Article — Permalink

The post Short note on the accessibility of styled form controls appeared first on CSS-Tricks.

Let’s make a form that puts current location to use in a map!

I love shopping online. I can find what I need and get most things for a decent price. I am Nigerian currently working and studying in India, and two things I dread when shopping online are:

  1. Filling out a credit card form
  2. Filling out shipping and billing address forms

Maybe I’m just lazy, but these things are not without challenges! For the first one, thanks to payment processing services like PayPal and e-wallets, I neither have to type in my 12-digit credit card number for every new e-commerce site I visit, nor have to save my credit card details with them.

For the second, the only time-saving option given by most shopping websites is to save your shipping address, but you still have to fill the form (arrghh!). This is where the challenge is. I’ve had most of my orders returned because my address (which I thought was the right address) could not be located or confirmed by the app for one reason or another.

Address inputs are challenging

Getting a user’s address through an input form is a clean solution but can also be a herculean task to the user. Here’s why:

  • If the user is new in a particular city, they might not know their full address
  • If the user wants to ship to a new address which isn’t saved (e.g shipping to a workplace or a friend’s address instead of the saved home address)
  • If the user resides in a city with very difficult address systems
  • If the user is plain lazy like me

A potential solution: get the address automatically

Getting the user’s address by the tap/click of a button. Yup, that’s easy! The UX is great as it saves the user both the time and effort of filling out some form. It will also save the store owner time, effort, and even money in some cases, as there’ll likely be a reduction in the number of incorrectly placed orders or shipments.

Let’s build a mini app that gets a user’s address and shows it on a Google Map interface using vanilla JavaScript. The concept is as follows:

  1. Get the HTML button and listen for a click event
  2. Get the user’s location (latitude and longitude) on a button click
  3. Show the user’s location on a Google map
  4. Pass the latitude and longitude to the Google Maps Geocode API URL
  5. Display the returned address (or list of addresses) on the UI for the user to select one
  6. Listen for map events and repeat steps 4 and 5
  7. Pre-fill the form with the address data the user selects

Getting started and setting up

To build this app, we’re going to use the Materialize CSS framework to save us some time fussing with styles. Materialize is a modern responsive front-end framework based on Google’s Material Design system. The beta version works with vanilla JavaScript.

A basic setup using Materialize’s CSS and JavaScript files in a document is like this:

<!DOCTYPE html>
<html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Address Locator</title> <link rel="stylesheet" href=""> <link rel="stylesheet" href="css/main.css">
<body> <script src=""></script> <script src="js/main.js"></script>

We’re also going to use the Google Maps API for displaying the map and getting the user’s human-readable address. We’ll need an API key to do this. Here’s how to get one:

  1. Sign in to your Google Developer’s Console Account
  2. Create a new project or select an existing one
  3. Click on “Enable APIs and Services”
  4. Select the “Maps Javascript API” option
  5. Click “Enable” on the new page that comes up. Go back to the previous page and do a search for “Geocoding API,” click on it and enable it as well
  6. Then, on the right nav of the page, click on Credentials, copy the API key on the page and save it to a file

Now, let’s update our document to show the map and let the user know it can be used to get their current location as the address. Also, we will add a form that’s pre-filled with the address the user selects.

... <body> <div class="container"> <h3>Shipping Address</h3> <p>You can click the button below to use your current location as your shipping address</p> <div id="map"> </div> <button id="showMe" class="btn">Use My Location</button> <form id="shippingAddress"> <div id="locationList"></div> <br> <div class="input-field"> <textarea class="input_fields materialize-textarea" id="address" type="text"></textarea> <label class="active" for="address">Address (Area and Street)</label> </div> <div class="input-field"> <input class="input_fields" id="locality" type="text"> <label class="active" for="locality">Locality</label> </div> <div class="input-field"> <input class="input_fields" id="city" type="text"> <label class="active" for="city">City/District/Town</label> </div> <div class="input-field"> <input class="input_fields" id="postal_code" type="text"> <label class="active" for="pin_code">Pin Code</label> </div> <div class="input-field"> <input class="input_fields" id="landmark" type="text"> <label class="active" for="landmark">Landmark</label> </div> <div class="input-field"> <input class="input_fields" id="state" type="text"> <label class="active" for="State">State</label> </div> </form> <!-- You could add a fallback address gathering form here --> </div> <script src=""></script> <script src=""></script> <script src="js/main.js"></script>
</body> </html>

While we are here, let’s style things a bit to make this look a little better:

.container { width: 50%; max-width: 800px;
} #map { height: 50vh; margin-bottom: 10px; display: none;
} #locationList .card { padding: 10px;
} #toast-container { top: 50%; bottom: unset;
} .toast { background-color: rgba(0, 0, 0, 0.8);
} @media only screen and (max-width: 768px) { .container { width: 80%; }

This CSS hides the map until we are ready to view it. Our app should look like this:

Let’s plan this out

Our app will be making use of the HTML5 Geolocation API to determine our user’s current location as well as Google’s Geocode API with a technique called Reverse Geocoding. The Geocode API takes a human-readable address and changes it into geographical (latitudinal and longitudinal) coordinates and marks the spot in the map.

Reverse Geocoding does the reverse. It takes the latitude and longitude and converts them to human-readable addresses. Geocoding and Reverse Geocoding are well documented.

Here’s how our app will work:

  1. The user clicks on the “Use My Location” button
  2. The user is located with the HTML5 Geolocation API (navigator.geolocation)
  3. We get the user’s geographic coordinates
  4. We pass the coordinates to the geocode request API
  5. We display the resulting addresses to the user

Most times, the geocode returns more than one address, so we would have to show the user all the returned addresses and let them choose the most accurate one.

Phew! Finally, we can get to the fun part of actually writing the JavaScript. Let’s go through each of the steps we outlined.

Step 1: Clicking the button

In our main.js file, let’s get a reference to the HTML button. While we are at it, we’ll set up some other variables we’ll need, like our API key.

//This div will display Google map
const mapArea = document.getElementById('map'); //This button will set everything into motion when clicked
const actionBtn = document.getElementById('showMe'); //This will display all the available addresses returned by Google's Geocode Api
const locationsAvailable = document.getElementById('locationList'); //Let's bring in our API_KEY
const __KEY = 'YOUR_API_KEY'; //Let's declare our Gmap and Gmarker variables that will hold the Map and Marker Objects later on
let Gmap;
let Gmarker; //Now we listen for a click event on our button
actionBtn.addEventListener('click', e => { // hide the button = "none"; // call Materialize toast to update user M.toast({ html: 'fetching your current location', classes: 'rounded' }); // get the user's position getLocation();

When the click handler for our button runs, it:

  1. Hides the button
  2. Alerts the user that we are getting their current location (a “toast” in Materialize is like a popup notification)
  3. Calls the getLocation function

Step 2: Get the user’s location (latitude and longitude)

When our getLocation function is invoked, we need to do some more work. First, let’s check if we can even use the Geolocation API:

getLocation = () => { // check if user's browser supports Navigator.geolocation if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(displayLocation, showError, options); } else { M.toast({ html: "Sorry, your browser does not support this feature... Please Update your Browser to enjoy it", classes: "rounded" }); }

When we have support, it calls geolocation’s getCurrentPosition method. If it doesn’t have support, then the user is alerted that there’s no browser support.

If there is support, then the getCurrentLocation method is used to get the current location of the device. The syntax is like this:

navigator.geolocation.getCurrentPosition(*success, error, [options]*)
  • success : This is a callback function that takes a position as its only parameter. For us, our success callback function is the displayLocation function.
  • error : [optional] This is a callback function that takes a PositionError as its sole input parameter. You can read more about this here. Our error callback function is the showError function.
  • options : [optional] This is an object which describes the options property to be passed to the getCurrentPosition method. You can read more about this here. Our options parameter is the options object.

Before writing our displayLocation function, let’s handle the showError function and options object:

// Displays the different error messages
showError = (error) => { = "block" switch (error.code) { case error.PERMISSION_DENIED: mapArea.innerHTML = "You denied the request for your location." break; case error.POSITION_UNAVAILABLE: mapArea.innerHTML = "Your Location information is unavailable." break; case error.TIMEOUT: mapArea.innerHTML = "Your request timed out. Please try again" break; case error.UNKNOWN_ERROR: mapArea.innerHTML = "An unknown error occurred please try again after some time." break; }
//Makes sure location accuracy is high
const options = { enableHighAccuracy: true

Now, let’s write the code for our displayLocation function inside our main.js file:

displayLocation = (position) => { const lat = position.coords.latitude; const lng = position.coords.longitude;

We now have our user’s latitude and longitude and we can view them in the console by writing the code below inside displayLocation:

console.log( `Current Latitude is ${lat} and your longitude is ${lng}` );

Step 3: Show the user’s current location on a Google Map

To do this, we will be adding these lines of code to our displayLocation function.

const latlng = {lat, lng}
createMarker(latlng); = "block";

The first line takes our lat and lng values and encapsulates it in the latlng object literal. This makes it easy for us to use in our app.

The second line of code calls a showMap function which accepts a latlng argument. In here, we get to instantiate our Google map and render it in our UI.

The third line invokes a createMarker function which also accepts our object literal (latlng) as its argument and uses it to create a Google Maps Marker for us.

The fourth line makes the mapArea visible so that our user can now see the location.

displayLocation = (position) => { const lat = position.coords.latitude; const lng = position.coords.longitude; const latlng = { lat, lng } showMap(latlng); createMarker(latlng); = "block";

Now, let’s get to creating our functions. We will start with the showMap function.

showMap = (latlng) => { let mapOptions = { center: latlng, zoom: 17 }; Gmap = new google.maps.Map(mapArea, mapOptions);

The showMap function creates a mapOptions objects that contain the map center (which is the lat and lng coordinates we got from displayLocation) and the zoom level of the map. Finally, we create an instance of the Google Maps class and pass it on to our map. In fewer words, we instantiate the Google Maps class.

To create a map instance, we specify two parameters in the constructor: the div the map will be displayed and the mapOptions. In our case, our div is called mapArea and our mapOptions is called mapOptions. After this, our created map will show up, but without a marker. We need a marker so the user can identify their current position on the map.

Let’s create our marker using the createMarker function:

createMarker = (latlng) => { let markerOptions = { position: latlng, map: Gmap, animation: google.maps.Animation.BOUNCE, clickable: true }; Gmarker = new google.maps.Marker(markerOptions);

A few things to note in this code:

  1. The position property positions the marker at the specified latlng
  2. The map property specifies the map instance where the marker should be rendered (in our case, it’s Gmap)
  3. The animation property adds a little BOUNCE to our marker
  4. The clickable property set to true means our marker can be clicked
  5. Finally, we instantiate the Marker class in our Gmarker instance variable

So far, our user’s location has been fetched, the map has rendered and the user can see their current location on the map. Things are looking good! 🕺

Step 4: Pass the latitude and longitude to the Geocode API

Google’s Geocoding API will be used to convert our user’s numeric geographical coordinates to a formatted, human-readable address using the reverse geocoding process we covered earlier.

The URL takes this form:

…where the outputFormat may either be a json or xml which determines the the format used to deliver the data. The parameters part is a list of parameters needed for the request.

Our request URL will look like this:${latlng}&key=${__KEY}

Let’s go ahead and connect to the API. We would do this in a function called getGeolocation.

getGeolocation = (lat, lng) => { const latlng = lat + "," + lng; fetch( `${latlng}&key=${__KEY}` ) .then(res => res.json()) .then(data => console.log(data.results));

The getGeolocation function takes two arguments ( lat and lng } concatenates them to form a new latlng variable that is passed to the URL.

Using the Fetch API (more on this here), we add the new latlng and __KEY into the Geocode request URL. Then, on the response object we get back, we pass the .json method to resolve the promise with JSON. Finally, we log the response in our console.

To make use of our newly created function, we have to call it in the displayLocation function. So let’s update our displayLocation function to contain the getGeolocation function call:

displayLocation = (position) => { const lat = position.coords.latitude; const lng = position.coords.longitude; const latlng = { lat, lng } showMap(latlng); createMarker(latlng); = "block"; getGeolocation(lat, lng)// our new function call

The returned data should look something like this:

{ "results" : { "address_components": { "long_name": "1600", "short_name": "1600", "types": ["street_number"] }, { "long_name": "Amphitheatre Pkwy", "short_name": "Amphitheatre Pkwy", "types": ["route"] }, { "long_name": "Mountain View", "short_name": "Mountain View", "types": ["locality", "political"] }, { "long_name": "Santa Clara County", "short_name": "Santa Clara County", "types": ["administrative_area_level_2", "political"] }, { "long_name": "California", "short_name": "CA", "types": ["administrative_area_level_1", "political"] }, { "long_name": "United States", "short_name": "US", "types": ["country", "political"] }, { "long_name": "94043", "short_name": "94043", "types": ["postal_code"] } ], "formatted_address": "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA", "geometry": { "location": { "lat": 37.4224764, "lng": -122.0842499 }, "location_type": "ROOFTOP", "viewport": { "northeast": { "lat": 37.4238253802915, "lng": -122.0829009197085 }, "southwest": { "lat": 37.4211274197085, "lng": -122.0855988802915 } } }, "place_id": "ChIJ2eUgeAK6j4ARbn5u_wAGqWA", "types": ["street_address"] } ], "status" : "OK"

Step 5: Display the returned address(es) for the user to select

At this stage, we have made a request to Google’s Geocoding API and have gotten our result logged in the console. Now, we have to display the results in a UI for our user. This requires two things:

  1. Create a new function that handles creating HTML elements
  2. Update our getGeolocation function to make the function call

Let’s create the function that would take care of creating the HTML elements and updating the DOM.

populateCard = (geoResults) => { => { // first create the input div container const addressCard = document.createElement('div'); // then create the input and label elements const input = document.createElement('input'); const label = document.createElement('label'); // then add materialize classes to the div and input addressCard.classList.add("card"); input.classList.add("with-gap"); // add attributes to them label.setAttribute("for", geoResult.place_id); label.innerHTML = geoResult.formatted_address; input.setAttribute("name", "address"); input.setAttribute("type", "radio"); input.setAttribute("value", geoResult.formatted_address); input.setAttribute("id", geoResult.place_id); addressCard.appendChild(input); addressCard.appendChild(label) return ( // append the created div to the locationsAvailable div locationsAvailable.appendChild(addressCard) ); })

In this function, we iterate through our results and create some HTML elements (div , input and a label), append the input and the label to the div and finally append the new div to a parent div (which is locationsAvailable). Once we get the result from our API call, our DOM will be created and displayed to the user.

Next, we update our getGeolocation function to call our populateCard function by replacing the last line of getGeolocation with this:

.then(data => populateCard(data.results));

…which means our updated function should look this:

getGeolocation = (lat, lng) => { const latlng = lat + "," + lng; fetch( `${latlng}&key=${__KEY}` ) .then(res => res.json()) .then(data => populateCard(data.results));

At this point, everything should be working fine. Our user clicks a button, gets a location displayed on the map along with a list of addresses that match the current location.

Step 6: Listen for map events and repeat steps 4 and 5

If our user decides to move the map or marker, nothing happens to the UI — new addresses aren’t not displayed and everything remains static. We’ve got to fix this, so let’s make our app dynamic by listening for map events. You can read all about Google Map Events here.

There are three events we want to listen for:

  1. drag: This is fired once the user starts dragging and continues to drag the map
  2. dragend: This is fired once the user stops dragging the map
  3. idle: This is fired once every event has been fired and the map is idle

Quick Question: Why are these events best suited for our app?

Quick Answer: The first two events will make sure that our map marker stays in the center of the map during the drag event while the idle event will make a geocoding request with the new coordinates.

To listen for these events we have to update the showMap function with the following:

Gmap.addListener('drag', function () { Gmarker.setPosition(this.getCenter()); // set marker position to map center
Gmap.addListener('dragend', function () { Gmarker.setPosition(this.getCenter()); // set marker position to map center
Gmap.addListener('idle', function () { Gmarker.setPosition(this.getCenter()); // set marker position to map center if (Gmarker.getPosition().lat() !== lat || Gmarker.getPosition().lng() !== lng) { setTimeout(() => { updatePosition(this.getCenter().lat(), this.getCenter().lng()); // update position display }, 2000); }

As explained above, the first two event listeners simply ensure that the marker remains in the center of our map. Pay closer attention to the idle event listener because that is where the action is.

Once the idle event is fired, the marker goes to the center, then a check is done to find out if the current position of the marker is the same with the lat or lng values received by the displayLocation function. If it is not the same, then we call the updatePosition function after two seconds of idleness.

Having said that, we have to make a few updates to the showMap function. First, on the function header, we have to include more parameters and on the showMap function call. We need to add the new arguments there, too. Our showMap function should look like this:

showMap = (latlng, lat, lng) => { let mapOptions = { center: latlng, zoom: 17 }; Gmap = new google.maps.Map(mapArea, mapOptions); Gmap.addListener('drag', function () { Gmarker.setPosition(this.getCenter()); // set marker position to map center }); Gmap.addListener('dragend', function () { Gmarker.setPosition(this.getCenter()); // set marker position to map center }); Gmap.addListener('idle', function () { Gmarker.setPosition(this.getCenter()); // set marker position to map center if (Gmarker.getPosition().lat() !== lat || Gmarker.getPosition().lng() !== lng) { setTimeout(() => { updatePosition(this.getCenter().lat(), this.getCenter().lng()); // update position display }, 2000); } });

And our displayLocation function should look like this:

displayLocation = (position) => { const lat = position.coords.latitude; const lng = position.coords.longitude; const latlng = { lat, lng } showMap(latlng, lat, lng); //passed lat and lng as the new arguments to the function createMarker(latlng); = "block"; getGeolocation(lat, lng);

Having listened for the map events, let’s repeat Step 4 and Step 5.

We start by writing our updatePosition function. This function will perform only one action for now, which is to pass the new lat and lng values to the getGeolocation function:

updatePosition = (lat, lng) => { getGeolocation(lat, lng);

After getting the new position and fetching addresses, our DOM should re-render for the user, right? Well, it doesn’t. And to fix that, we create a function that will force the DOM to re-render:

// check if the container has a child node to force re-render of dom
function removeAddressCards(){ if (locationsAvailable.hasChildNodes()) { while (locationsAvailable.firstChild) { locationsAvailable.removeChild(locationsAvailable.firstChild); } }

It checks if the locationsAvailable div has any childNodes, and if it does, it deletes them before creating new address cards. The populateCard function is now updated to this:

populateCard = (geoResults) => { // check if a the container has a child node to force re-render of dom removeAddressCards(); => { // first create the input div container const addressCard = document.createElement('div'); // then create the input and label elements const input = document.createElement('input'); const label = document.createElement('label'); // then add materialize classes to the div and input addressCard.classList.add("card"); input.classList.add("with-gap"); // add attributes to them label.setAttribute("for", geoResult.place_id); label.innerHTML = geoResult.formatted_address; input.setAttribute("name", "address"); input.setAttribute("type", "radio"); input.setAttribute("value", geoResult.formatted_address); input.setAttribute("id", geoResult.place_id); addressCard.appendChild(input); addressCard.appendChild(label); return ( locationsAvailable.appendChild(addressCard); ); })

We are done and are now able to fully get and display the user’s address!

Step 7: Pre-fill the form with the address data the user selects

The final step is to fill the form with the address the user selects. We need to add a click event listener to the address card and pass the address as argument to the callback function.

Here’s how we add the event listener in the populateCard function:

input.addEventListener('click', () => inputClicked(geoResult));

You should note that the geoResult argument in the above callback is the selected address object from the results array. That said, update the populateCard function to accommodate our new line of code.

The inputClicked function uses a series of if statements to assign values to our form elements. so before working on it, let’s bring our form elements into the equation:

const inputAddress = document.getElementById('address'), inputLocality = document.getElementById('locality'), inputPostalCode = document.getElementById('postal_code'), inputLandmark = document.getElementById('landmark'), inputCity = document.getElementById('city'), inputState = document.getElementById('state');

Having done this, let us now work on pre-filling the form with the address_components in the inputClicked function.

inputClicked = result => { => { const types = component.types if (types.includes('postal_code')) { inputPostalCode.value = component.long_name } if (types.includes('locality')) { inputLocality.value = component.long_name } if (types.includes('administrative_area_level_2')) { inputCity.value = component.long_name } if (types.includes('administrative_area_level_1')) { inputState.value = component.long_name } if (types.includes('point_of_interest')) { inputLandmark.value = component.long_name } }); inputAddress.value = result.formatted_address; // to avoid labels overlapping pre-filled input contents M.updateTextFields(); // removes the address cards from the UI removeAddressCards();

The above block of code iterates over the clicked (or selected) address component, checks the types of components and finally assigns them to the input fields if they match.

M.updateTextFields() function is from Materialize and it ensures that the label does not overlap with the input fields values and the removeAddressCards() function removes the address cards from the UI.

With this, we are done with our app and have saved our users lots of typing and headaches! Surely they will thank us for implementing such a hassle free solution.

This whole UX experiment can be seen as a shortcut that will help the user pre-fill the shipping address form. We should clearly state here that the returned addresses isn’t always 100% accurate. But that’s why we allow the address to be manually edited in the UI.


See the Pen Prefill Address Form with Geolocation and Google Maps by CSS-Tricks (@css-tricks) on CodePen.

The post Let’s make a form that puts current location to use in a map! appeared first on CSS-Tricks.

Using data in React with the Fetch API and axios

If you are new to React, and perhaps have only played with building to-do and counter apps, you may not yet have run across a need to pull in data for your app. There will likely come a time when you’ll need to do this, as React apps are most well suited for situations where you’re handling both data and state.

The first set of data you may need to handle might be hard-coded into your React application, like we did for this demo from our Error Boundary tutorial:

See the Pen error boundary 0 by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.

What if you want to handle data from an API? That’s the purpose of this tutorial. Specifically, we’ll make use of the Fetch API and axios as examples for how to request and use data.

The Fetch API

The Fetch API provides an interface for fetching resources. We’ll use it to fetch data from a third-party API and see how to use it when fetching data from an API built in-house.

Using Fetch with a third-party API

See the Pen React Fetch API Pen 1 by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.

We will be fetching random users from JSONPlaceholder, a fake online REST API for testing. Let’s start by creating our component and declaring some default state.

class App extends React.Component { state = { isLoading: true, users: [], error: null } render() { <React.Fragment> </React.Fragment> }

There is bound to be a delay when data is being requested by the network. It could be a few seconds or maybe a few milliseconds. Either way, during this delay, it’s good practice to let users know that something is happening while the request is processing.

To do that we’ll make use of isLoading to either display the loading message or the requested data. The data will be displayed when isLoading is false, else a loading message will be shown on the screen. So the render() method will look like this:

render() { const { isLoading, users, error } = this.state; return ( <React.Fragment> <h1>Random User</h1> // Display a message if we encounter an error {error ? <p>{error.message}</p> : null} // Here's our data check {!isLoading ? ( => { const { username, name, email } = user; return ( <div key={username}> <p>Name: {name}</p> <p>Email Address: {email}</p> <hr /> </div> ); }) // If there is a delay in data, let's let the user know it's loading ) : ( <h3>Loading...</h3> )} </React.Fragment> );

The code is basically doing this:

  1. De-structures isLoading, users and error from the application state so we don’t have to keep typing this.state.
  2. Prints a message if the application encounters an error establishing a connection
  3. Checks to see if data is loading
  4. If loading is not happening, then we must have the data, so we display it
  5. If loading is happening, then we must still be working on it and display “Loading…” while the app is working

For Steps 3-5 to work, we need to make the request to fetch data from an API. This is where the JSONplaceholder API will come in handy for our example.

fetchUsers() { // Where we're fetching data from fetch(``) // We get the API response and receive data in JSON format... .then(response => response.json()) // ...then we update the users state .then(data => this.setState({ users: data, isLoading: false, }) ) // Catch any errors we hit and update the app .catch(error => this.setState({ error, isLoading: false }));

We create a method called fetchUser() and use it to do exactly what you might think: request user data from the API endpoint and fetch it for our app. Fetch is a promise-based API which returns a response object. So, we make use of the json() method to get the response object which is stored in data and used to update the state of users in our application. We also need to change the state of isLoading to false so that our application knows that loading has completed and all is clear to render the data.

The fact that Fetch is promise-based means we can also catch errors using the .catch() method. Any error encountered is used a value to update our error’s state. Handy!

The first time the application renders, the data won’t have been received — it can take seconds. We want to trigger the method to fetch the users when the application state can be accessed for an update and the application re-rendered. React’s componentDidMount() is the best place for this, so we’ll place the fetchUsers() method in it.

componentDidMount() { this.fetchUsers();

Using Fetch With Self-Owned API

So far, we’ve looked at how to put someone else’s data to use in an application. But what if we’re working with our own data in our own API? That’s what we’re going to cover right now.

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

I built an API which is available on GitHub. The JSON response you get has been placed on AWS — that’s what we will use for this tutorial.

As we did before, let’s create our component and set up some default state.

class App extends React.Component { state = { isLoading: true, posts: [], error: null } render() { <React.Fragment> </React.Fragment> }

Our method for looping through the data will be different from the one we used before but only because of the data’s structure, which is going to be different. You can see the difference between our data structure here and the one we obtained from JSONPlaceholder.

Here is how the render() method will look like for our API:

render() { const { isLoading, posts, error } = this.state; return ( <React.Fragment> <h1>React Fetch - Blog</h1> <hr /> {!isLoading ? Object.keys(posts).map(key => <Post key={key} body={posts[key]} />) : <h3>Loading...</h3>} </React.Fragment> );

Let’s break down the logic

{ !isLoading ? Object.keys(posts).map(key => <Post key={key} body={posts[key]} />) : <h3>Loading...</h3>

When isLoading is not true, we return an array, map through it and pass the information to the Post component as props. Otherwise, we display a “Loading…” message while the application is at work. Very similar to before.

The method to fetch posts will look like the one used in the first part.

fetchPosts() { // The API where we're fetching data from fetch(``) // We get a response and receive the data in JSON format... .then(response => response.json()) // ...then we update the state of our application .then( data => this.setState({ posts: data, isLoading: false, }) ) // If we catch errors instead of a response, let's update the app .catch(error => this.setState({ error, isLoading: false }));

Now we can call the fetchPosts method inside a componentDidMount() method

componentDidMount() { this.fetchPosts();

In the Post component, we map through the props we received and render the title and content for each post:

const Post = ({ body }) => { return ( <div> { => { const { _id, title, content } = post; return ( <div key={_id}> <h2>{title}</h2> <p>{content}</p> <hr /> </div> ); })} </div> );

There we have it! Now we know how to use the Fetch API to request data from different sources and put it to use in an application. High fives. ✋


OK, so we’ve spent a good amount of time looking at the Fetch API and now we’re going to turn our attention to axios.

Like the Fetch API, axios is a way we can make a request for data to use in our application. Where axios shines is how it allows you to send an asynchronous request to REST endpoints. This comes in handy when working with the REST API in a React project, say a headless WordPress CMS.

There’s ongoing debate about whether Fetch is better than axios and vice versa. We’re not going to dive into that here because, well, you can pick the right tool for the right job. If you’re curious about the points from each side, you can read here and here.

Using axios with a third-party API

See the Pen React Axios 1 Pen by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.

Like we did with the Fetch API, let’s start by requesting data from an API. For this one, we’ll fetch random users from the Random User API.

First, we create the App component like we’ve done it each time before:

class App extends React.Component { state = { users: [], isLoading: true, errors: null }; render() { return ( <React.Fragment> </React.Fragment> ); }

The idea is still the same: check to see if loading is in process and either render the data we get back or let the user know things are still loading.

To make the request to the API, we’ll need to create a function. We’ll call the function getUsers(). Inside it, we’ll make the request to the API using axios. Let’s see how that looks like before explaining further.

getUsers() { // We're using axios instead of Fetch axios // The API we're requesting data from .get("") // Once we get a response, we'll map the API endpoints to our props .then(response => => ({ name: `${} ${}`, username: `${user.login.username}`, email: `${}`, image: `${user.picture.thumbnail}` })) ) // Let's make sure to change the loading state to display the data .then(users => { this.setState({ users, isLoading: false }); }) // We can still use the `.catch()` method since axios is promise-based .catch(error => this.setState({ error, isLoading: false }));

Quite different from the Fetch examples, right? The basic structure is actually pretty similar, but now we’re in the business of mapping data between endpoints.

The GET request is passed from the API URL as a parameter. The response we get from the API contains an object called data and that contains other objects. The information we want is available in data.results, which is an array of objects containing the data of individual users.

Here we go again with calling our method inside of the componentDidMount() method:

componentDidMount() { this.getUsers();

Alternatively, you can do this instead and basically combine these first two steps:

componentDidMount() { axios .get("") .then(response => => ({ name: `${} ${}`, username: `${user.login.username}`, email: `${}`, image: `${user.picture.thumbnail}` })) ) .then(users => { this.setState({ users, isLoading: false }); }) .catch(error => this.setState({ error, isLoading: false }));

If you are coding locally from your machine, you can temporarily edit the getUsers() function to look like this:

getUsers() { axios .get("") .then(response => console.log(response)) .catch(error => this.setState({ error, isLoading: false }));

Your console should get something similar to this:

We map through the results array to obtain the information we need for each user. The array of users is then used to set a new value for our users state. With that done, we can then change the value of isLoading.

By default, isLoading is set to true. When the state of users is updated, we want to change the value of isLoading to false since this is the cue our app is looking for to make the switch from “Loading…” to rendered data.

render() { const { isLoading, users } = this.state; return ( <React.Fragment> <h2>Random User</h2> <div> {!isLoading ? ( => { const { username, name, email, image } = user; return ( <div key={username}> <p>{name}</p> <div> <img src={image} alt={name} /> </div> <p>{email}</p> <hr /> </div> ); }) ) : ( <p>Loading...</p> )} </div> </React.Fragment> );

If you log the users state to the console, you will see that it is an array of objects:

The empty array shows the value before the data was obtained. The returned data contains only the name, username, email address and image of individual users because those are the endpoints we mapped out. There is a lot more data available from the API, of course, but we’d have to add those to our getUsers method.

Using axios with your own API

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

You have seen how to use axios with a third-party API but we can look at what it’s like to request data from our own API, just like we did with the Fetch API. In fact, let’s use same JSON file we used for Fetch so we can see the difference between the two approaches.

Here is everything put together:

class App extends React.Component { // State will apply to the posts object which is set to loading by default state = { posts: [], isLoading: true, errors: null }; // Now we're going to make a request for data using axios getPosts() { axios // This is where the data is hosted .get("") // Once we get a response and store data, let's change the loading state .then(response => { this.setState({ posts:, isLoading: false }); }) // If we catch any errors connecting, let's update accordingly .catch(error => this.setState({ error, isLoading: false })); } // Let's our app know we're ready to render the data componentDidMount() { this.getPosts(); } // Putting that data to use render() { const { isLoading, posts } = this.state; return ( <React.Fragment> <h2>Random Post</h2> <div> {!isLoading ? ( => { const { _id, title, content } = post; return ( <div key={_id}> <h2>{title}</h2> <p>{content}</p> <hr /> </div> ); }) ) : ( <p>Loading...</p> )} </div> </React.Fragment> ); }

The main difference between this method and using axios to fetch from a third-party is how the data is formatted. We’re getting straight-up JSON this way rather than mapping endpoints.

The posts data we get from the API is used to update the value of the component’s posts state. With this, we can map through the array of posts in render(). We then obtain the id, title and content of each post using ES6 de-structuring, which is then rendered to the user.

Like we did before, what is displayed depends on the value of isLoading. When we set a new state for posts using the data obtained from the API, we had to set a new state for isLoading, too. Then we can finally let the user know data is loading or render the data we’ve received.

async and await

Another thing the promise-based nate of axios allows us to do is take advantage of is async and await . Using this, the getPosts() function will look like this.

async getPosts() { const response = await axios.get(""); try { this.setState({ posts:, isLoading: false }); } catch (error) { this.setState({ error, isLoading: false }); }

Base instance

With axios, it’s possible to create a base instance where we drop in the URL for our API like so:

const api = axios.create({ baseURL: ""

…then make use of it like this:

async getPosts() { const response = await api.get(); try { this.setState({ posts:, isLoading: false }); } catch (error) { this.setState({ error, isLoading: false }); }

Simply a nice way of abstracting the API URL.

Now, data all the things!

As you build React applications, you will run into lots of scenarios where you want to handle data from an API. Hopefully you know feel armed and ready to roll with data from a variety of sources with options for how to request it.

Want to play with more data? Sarah recently wrote up the steps for creating your own serverless API from a list of public APIs.

The post Using data in React with the Fetch API and axios appeared first on CSS-Tricks.

VS Code extensions for the discerning developer palate

I am a VS Code extension snob. I like to hunt down the most obscure extensions for VS Code — the ones that nobody knows about — and impress people at parties with my knowledge of finely aged and little-known VS Code capabilities… then watch as they look around desperately for someone else to talk to. It’s like the “Sideways” of VS Code.

In my endless pursuit of the perfect VS Code setup, I reached out to my colleagues here on the Azure team and asked them to share their favorite extension in their own words. So clear your pallet and breathe in the aromatic flavors of productivity; I am your VS Code Extension Sommelier.

Christina Warren – Settings Sync

I cannot live without this extension. If you use multiple machines (especially on multiple platforms, where a sym-linked Dropbox folder won’t really work), this extension is for you. It syncs your extensions, settings file, keybinding file, launch file, snippets folder, extension settings, and workspaces folder. This means that when you login to a new machine, you can quickly get back to work with your own settings and workflow tools in just a few minutes.

👉 Get Settings SyncExtension

Shayne Boyer – Paste JSON as Code

Consuming an endpoint that produces JSON is like breathing, but no one wants to choke on the hand cranking of an object by looking back and forth between JSON and the target language. This is a long loved feature in Visual Studio for .NET developers, but now you too can copy the JSON and paste that class into the editor as your target language and save a ton of time. Currently supports C#, Go, C++, Java, TypeScript, Swift, Elm, and JSON Schema.

👉 Get Paste JSON as Code Extension

Jeremy Likness – Spell Right

I find myself authoring blog posts, articles, and documentation almost every day. After embracing the power of Markdown (it is, after all, what is used to drive our own, I began writing my content in Visual Studio Code. It has a built-in preview window so I can edit the Markdown source and see the rendered result side-by-side. As much as I’ve written over the years, mastering the fine art of spelling still eludes me. Maybe it’s because I’m lazy, and this extension doesn’t help at all. With Spell Right, I get to reunite with my same favorite red squiggly lines that I first met in Word. It does a great job of catching spelling mistakes in real time, then illuminates my mistakes with a handy light bulb with alternative suggestions that give me single-click corrections. It enables me to be highly productive and look like I know what I’m doing. I recommend this for anyone who uses Code to write.

👉 Get Spell Right Extension

Aaron Wislang – Go

I live in VS Code and use it for everything from code and content to its integrated terminal. This extension enables first-class support for IntelliSense, testing, refactoring and more, making Code the best place to me to write Go. And it turns out I’m not the only one who thinks so; it helped to make Code the most popular editor amongst Gophers, just ahead of vim-go, as of the Go 2017 Survey!

👉 Get Go Extension

Cecil Phillip – C# Extensions

This extension was created by one of our community members, and it’s a great companion to the official C# extension from Microsoft. The “New Class|Interface” actions make it easy to add new types, and takes some of the hassle out of fixing up the namespaces. It also comes with a few interesting refactorings like “Initialize fields from constructors,” which I use pretty often. Whenever I’m teaching a C# course, I always have my students that are using Visual Studio Code install this extension.

👉 Get C# Extension

Brian Clark – VS Live Share

Pair programming just got way better. Gone are the days where I need to set up screen sharing to review code with coworkers. Instead I fire up a live share session, invite the other party and we can all view and edit code directly from our editors. I’ve used it in a situations where I review someone else’s C# code on my machine while it runs on THEIR machine! I didn’t have anything installed on my Mac for C# and yet I could debug their code!

👉 Get VS Live Share Extension

David Smith – Rewrap

I write a lot of text, and sometimes I just want (or need) to write in a plain-text environment. Easy reflowing of text is essential. (Surprised this isn’t built in, in fact.)

👉 Get Rewrap Extension

Anthony Chu – Git Lens

At a glance, GitLens shows me contextual information from Git about the line of code and the file I’m working in. It adds some useful commands to view history and diffs, search commits, and browse local and remote branches… all without leaving VS Code.

👉 Get Git Lens Extension

Asim Hussain – AsciiDoc

I used to write with Markdown, we all make mistakes. The solution to my Markdown mistake is AsciiDoc, especially if you write a lot of code snippets as I do. Out of the box it let’s you add line numbers, annotate and highlight lines and provides an incredible amount of customization. Plus, as a bonus it also can convert your blog posts into PDFs, ePubs, Mobis which is perfect for ebooks.

Once you start with AsciiDoc it’s hard to go back to Markdown and this plugin lets you preview your AsciiDoc right inside the editor.

👉 Get AsciiDoctor Extension

Seth Juarez) – VS Code Tools For AI

With Visual Studio Code Tools for AI, I can finally use machines I need but might never have access to in order to build the next Skynet — all within the comfort of my favorite lightweight editor. We live in amazing times, friends…

👉 Get VS Code Tools For AI Extension

Alena Hall – Ionide

Ionide is an awesome Visual Studio Code extension for cross-platform F# development. It’s open-source and it was created by the F# Community. I use it every day on multiple machines I have. It runs perfectly on both my Mac and Linux machines. Ionide conveniently integrates with Paket, Project Scaffold, and you can experiment away as much as you want in F# Interactive!

👉 Get Ionide Extension

Matt Soucoup – VSCodeVim

There’s an old joke that goes: “How do you know if a developer uses vim? They’ll tell you.” Well, I use vim! But… I want more. I want to tell everybody I use vim and I want to use all the great features and extensions that VS Code offers. (I mean, look at the list here!) So that’s where VSCodeVim saves the day for me. It puts a full-featured vim emulator into my VS Code editor, letting me edit files super fast by typing esoteric commands like h, 10 k, i, and u (lots and lots of u) and I still get to use all the awesome features of VS Code.

👉 Get VSCodeVim Extension

John Papa – Docker

If you like it put a container on it. Yeah, containers are the latest craze, but in a constantly evolving containerization world, it’s nice to have great tooling make it easy to use containers. Enter the Docker extension for VS Code. It handles the complete container development and deployment lifecycle! Start by generating docker files to your project, create an image, run it, and even push it to a container registry. If you’re like me, you like to make sure you still have complete control over your code and your app, even when they are inside of containers. Accessing the files, showing logs, and debugging the running container are all essential tools for development. This extension puts all of this within your reach without having to learn the docker command line!

👉 Get Docker Extension

Suz Hinton – Arduino

My favorite extension for VS Code is Arduino. I’m pretty sure anyone who knows me wouldn’t be surprised about that. Traditionally, developing programs for Arduino-compatible micro-controller boards has been done in the Arduino IDE. It’s a powerful program which smooths over the compilation and uploading experiences for dozens of boards. It is, however, not a full code IDE. It’s missing some of the features you love, such as autocomplete, a file tree, and fine-grained tuning of the editor itself.

The good news is that the Arduino extension allows you to finally develop freely for all of your favorite micro-controller boards without leaving VS Code!

Here are some of my favorite things about the extension:

  1. It’s open source! So reporting bugs and contributing improvements is a straightforward experience.
  2. The Command Palette integration is so handy. Compile and upload your code to an Arduino with one simple shortcut.
  3. Access all the great tools from the Arduino IDE right in VS Code. Yes, that even means board / library management and the serial monitor!
  4. Scaffolding brand new Arduino projects is a command away. No more copy + pasting older project directories to get set up.

👉 Get Arduino Extension

Burke Holland – Azure Functions

Serverless is like Hansel — so hot right now. But Serverless shouldn’t be a black box. The Azure Functions extensions for VS Code puts Serverless right inside of the editor. I love it because it lets me create new Serverless projects, new functions for all of the available trigger types (http, timer, blob storage, etc.), and most importantly, I can run them locally and debug them. Not that I would ever need to debug. My code is always perfect.

👉 Get Azure Functions Extension

The post VS Code extensions for the discerning developer palate appeared first on CSS-Tricks.

​Experience a Simpler Cloud Computing Platform with DigitalOcean

(This is a sponsored post.)

From deploying static sites and blogging platforms to managing multiple client websites, DigitalOcean provides a flexible platform for developers and their teams to deliver an unparalleled end-user experience with a lightning-fast network, pre-configured applications, and a 99.99% uptime SLA. Simply let us know your needs and our solutions engineers will provide the best options available.

Direct Link to Article — Permalink

The post ​Experience a Simpler Cloud Computing Platform with DigitalOcean appeared first on CSS-Tricks.

On Switching Code Editors

I’m sure a lot of you are like me and have switched code editors a number of times. I think my first major editor was Coda. Then I moved to TextMate when I started working primarily on local. Then Sublime Text. And, most recently, VS Code. I bet your journey was different. I know lots of folks that quite love Atom, Brackets, WebStorm, and even BBedit. You do you!

For me, that’s four changes in a dozen years, or a change every three years. Moving isn’t something I do quickly. Here’s a collection of thoughts around the idea of changing editors.

When moving, I have to take time to make sure it works pretty much like the old one.

Otherwise, I’ll just end up disliking it to the point that I switch back a day or two later. It’s happened to me every time I switch. I have little false-starts after a switch where I go back to the old editor because something bugged me too much or it affected my productivity and I gave up. (Now that I know I do this, I don’t let a single false-start make me feel like the editor I’m trying is never a possibility.)

My latest switch was from Sublime Text to VS Code. I’d become become very used to the key bindings (e.g. CMD+Shift+d to duplicate a line) in Sublime Text, so thankfully VS Code has that covered.

I was amazed to find even my VIM friends happy and comfortable in VS Code. (Fun fact: we have key bindings choices in CodePen, too.)

Nothing can be too obnoxious.

In one of my first attempts at switching, I found the UI in VS code to be too cluttered and the find-in-project feature to be a little slow and awkward. Those things bugged me to the point they caused false-starts and I went back to Sublime Text.

On this last switch attempt (my 3rd or 4th maybe?) I finally have a theme I quite like (customized a smidge), found some settings to clean up the UI (I removed the whitespace indicators which were overwhelming to me, and overrode that intense blue footer with something more chill).

In working with find-in-project a bit more, I’ve grown to get used to it. I finally might even like it more than Sublime, as the sidebar approach is more consistent than opening a new tab of results. I find the jump-to-line feature works more consistently and search feels more the first-class citizen it should be.

Another factor would be Emmet. I’m quite sure that I’d be too annoyed writing HTML and CSS in an editor without Emmet, and I’d just give up and use something else that had it. Emmet isn’t even an extension in VS Code, it’s built in.

I’m cool with making small changes after a successful switch.

Once I’ve actually done it, and made the switch to full-time use, then I can make some changes. Maybe I’ll learn some new key commands. Maybe I’ll add an extension that adds functionality I’ve never had before. Maybe the editor affects some workflow thing in a way I’m now willing to try.

The new editor better have some killer feature that incentivizes me to switch.

If it’s exactly the same, why bother?

The new editor needs to be faster (or feel just as fast). Or should look better. Or it should have some awesome package that is only available on it. Ideally all of that.

In this recent switch for me, it was GitLens.

How cool is that?

It ought to have a plugin architecture.

Meaning that anyone can write code to extend the editor. I’m fairly certain that having a plugin architecture (plus a healthy amount of community momentum) is what is key to any editor’s success. Sublime’s package manager, and the subsequent built-in packages feature of VS Code, seem crucial. Not only for functionality but even just for the look of the editor. I wouldn’t use an editor with a look I hate, but I’d be tempted to if the functionality was awesome. That’s a non-issue with a plugin-based editor. Open source seems smart as well.

Careful for those GOTCHAs.

One of those was spell-checking for me. In Sublime Text, it was an option under the View menu. I had it checked all the time, and it spell-checked all the time.

This is not a thing in VS Code. That was dangerous after switching because, who knows, I may have been committing typos all over the place. Fortunately, this extension seems to be doing the trick. Thank jeepers for extensions!

Your thoughts!

I thought it might be interesting to ask what y’all think about when switching code editors. There were lots of responses. I picked out as many as I could here and focused on one thing that you mentioned.

  • Jani Hartikainen cares about VIM key bindings.
  • Morgon wants version control integration.
  • Stu Robson wants it to not crash when you open huge files.
  • Gabriel Vaquer doesn’t want it to be Electron.
  • gryzzly wants it to start up fast.
  • Josh Betz wants a human-readable config file.
  • Dan Finlay wants it to be mouse-free.
  • Frank Spin cares about GitHub stars.
  • Elijah Manor wants it to support extensions.
  • Max Sandelin wants visual git controls.
  • Matt Obee wants speed.
  • Kuldar wants less UI.
  • Devon wants something that his old editor doesn’t have.
  • Brett Jankord wants it to be actively developed.
  • Jordan Koschei wants it to be used by people he trusts.
  • PaulMDev wants night mode.
  • Brad Frost wants reliability.
  • Will Browar wants multiple cursors.
  • Umar Taufiq wants code hinting.
  • Thomas Faller wants community and support.
  • code witch sam wants community engagement.
  • Steve Gardner wants speed.
  • Nathan Knowler is concerned about screen real estate.
  • hearsay wants a live preview.
  • Keith Grant cares about syntax highlighting themes.
  • Mike Reithmuller cares about speed.
  • Nori Code cares about RAM usage.
  • droan cares about ligatures.

The post On Switching Code Editors appeared first on CSS-Tricks.

Getting to Know a Legacy Codebase

Harry Roberts talks about some methods for getting comfy with a new (“specifically CSS”) code base. Harry’s done this a lot as someone who parachutes into new code bases regularly as a consultant. But I think this is also quite interesting for people starting a new job. So much web development work is working on existing sites, not green fielding new ones.

Direct Link to Article — Permalink

The post Getting to Know a Legacy Codebase appeared first on CSS-Tricks.

The peculiar magic of flexbox and auto margins

In front-end development, there are often times when I know that I don’t know something. I might know enough to know what CSS to search for, but I have absolutely no idea how to use it or what the right syntax is. Somehow, in my head, there appears to be a filing cabinet that’s entirely empty, and when I try to look something up, all I find is an almost illegible sticky note instead.

One topic like this (which is an area I’ve sort of always known about but never really understood) is how auto margins and flexbox interact with one another.

Take this example for instance:

.parent { display: flex
} .child { margin: auto;

What does this do again? I seem to recall there’s a bunch of nifty things you can do with it, and earlier this week, I half-remembered them after reading a great post by Sam Provenza from a while back that shows how auto-margins and flexbox work together. But I still didn’t quite get the concept even after reading that post, and it wasn’t until I started making demos of my own that it started to click.

In that post, Sam describes how margin: auto impacts flex items like so:

If you apply auto margins to a flex item, that item will automatically extend its specified margin to occupy the extra space in the flex container, depending on the direction in which the auto-margin is applied.

Let’s pick that apart a bit and say we have a simple parent div with a child div inside it:

<div class="parent"> <div class="child"></div>

And let’s assume we’re using the following CSS to style those divs:

.parent { display: flex; height: 400px; background-color: #222;
} .child { background-color: red; width: 100px; height: 100px;

The result is something like this:

See the Pen margin-auto: #1 by Robin Rendle (@robinrendle) on CodePen.

When we add margin-left: auto to the .child element like so:

.child { background-color: red; width: 100px; height: 100px; margin-left: auto;

…then we’ll see this instead:

See the Pen margin-auto: #2 by Robin Rendle (@robinrendle) on CodePen.

Weird, huh? The left-hand margin is pushing the parent so that the child is nestled up in the far right-hand corner. But it gets a little weirder when we set all margins to auto:

.child { background-color: red; width: 100px; height: 100px; margin: auto;

See the Pen margin-auto: #3 by Robin Rendle (@robinrendle) on CodePen.

It’s like we’re using a popular centering trick by setting justify-content and align-items to center because the child decides to rest in the center of the parent, both horizontally and vertically. Likewise, if we set margin-left and margin-top to auto, then we can let the flex item push itself into the bottom-right of the parent:

See the Pen margin-auto: #4 by Robin Rendle (@robinrendle) on CodePen.

When Sam says, “that item will automatically extend its specified margin to occupy the extra space in the flex container,” the way my empty filing cabinet brain interprets that is like so:

Setting the margin property on a flex child will push the child away from that direction. Set margin-left to auto, the child will push left. Set margin-top to auto and the child will push to the top.

After I write that down, it sounds so obvious to me now that it’s almost foolish but sometimes that’s what it takes to get a new concept to stick in my big dumb spongey noggin.

Why is this useful to know? Well, I think there are a few moments where justify-self or align-self might not get you exactly what you want in a layout where using auto margins gives you that extra flexibility to fine-tune things. A lot of demos I’ve seen out there, including the ones Sam made for her original post, mostly appear to be for aligning navigation items in a menu. So, pushing one item in that menu to the bottom or far right of a flex parent is certainly useful in those scenarios.

Anyway, I think this weird trick is important to remember, just in case.

The post The peculiar magic of flexbox and auto margins appeared first on CSS-Tricks.

Stuff you can do with CSS pointer events

Martijn Cuppens (the same fella with the very weird div!) has some more irresistible CSS trickery. Three of the examples are about making a child element trigger an event on a parent element (almost like the magic that is :focus-within).

Here’s how I reasoned it out to myself:

  1. You know how if you display: hidden; an element, even if you display: block; a child, it doesn’t matter — it’s hidden because its parent is hidden.
  2. The same is not true for visibility: hidden;. Children will be hidden because visibility inherits, but if you visibility: visible; them, they become visible again.
  3. That’s what is happening here with pointer-events. If you pointer-events: none; on a parent and then pointer-events: auto; on a child, you’re re-enabling pointer events. Then a :hover on a parent will be triggered (for example), when hoving the child, but nowhere else inside the parent.

And don’t miss pointer-events: visiblePainted; 😳

Direct Link to Article — Permalink

The post Stuff you can do with CSS pointer events appeared first on CSS-Tricks.

Sometimes `sizes` is quite important.

Paraphrased question from email:

I just read your article Responsive Images: If you’re just changing resolutions, use srcset. In the age of “responsive websites,” srcset does not help in certain situations. For example, I have a popular products slider. On mobile, I have one image per slide where the images are 320px wide. On desktop, I have six images per slide where each is 160px wide. So the desktop images are smaller on desktop, not bigger.

How do I handle this situation with srcset?

I tried to be careful with that post title: “If you’re just changing resolutions, use srcset.” In this case, we’re changing the size of the images not just at certain resolutions, but at specific breakpoints as well, which means we’re also going to need to use the sizes attribute to get the most out of responsive images. The entire job of the sizes attribute is to tell the browser what size the image will be shown at, as per our CSS.

A demo! Resize the width to see it alternate between the “Desktop” and “Mobile” views.

See the Pen Responsive Images Slider by Chris Coyier (@chriscoyier) on CodePen.

As the email mentioned, the “Desktop” version actually renders the images smaller (160px) than the “Mobile” version (320px).

Let’s also account for 2x displays. To prepare ourselves, let’s have three versions of each image:

  • 160px (for 1x desktop displays)
  • 320px (for 2x desktop displays, or 1x mobile displays)
  • 640px (for 2x mobile displays)

With srcset, that looks like this:

<img srcset=" food-big.jpg 640w, foot-medium.jpg 320w, food-small.jpg 160w"

Notice we’re not yet using the sizes attribute. Browsers will assume you’re probably going to render this image at 100vw wide. That’s unfortunate because the browser may download a larger image than it needs, which is what we’re trying to fight against with responsive images in the first place.

On my 2x desktop display, I can tell it’s downloading the 640px version, but it really only needs the 320px version.

It’s our CSS that controls how big these images render. In fact, we have a media query in this demo that says, “Hey browser, only render the images at 160px wide on Desktop displays.”

@media (min-width: 600px) { .slider img { width: 160px; }

You’d think the browser would know that, and it does — it just needs to download and parse the CSS first. The browser wants to make a decision about what to download faster than that. So, let’s tell it with the sizes attribute.

<img srcset=" food-big.jpg 640w, foot-medium.jpg 320w, food-small.jpg 160w" sizes="(min-width: 600px) 160px, 320px"

That’s saying, “OK, we’ll be rendering this image 160px wide on Desktop. Otherwise, let’s go with 320px wide.” With that in place, we can see the browser is making the right choice:

The browser is now only choosing to download the 320px version, which is correct on a 2x display where the images are being rendered at 160px.

And just to be sure, here’s a narrow viewport (like “mobile” would be):

We’re back to downloading the 640px version, which is correct, since at this viewport size, the sizes attribute is telling the browser we intend to render at 320px and we’re on a 2x display.

There is even more nuance here

I showed this demo to Eric “Sizes Master” Portis, who confirmed all this, but had some browser-specific things to add. I’ll summarize (but note the date of this blog post because these things tend to change):

  • Firefox does exactly as described above.
  • Chrome does too, except that it will always use the larger version if it has that version in cache. So, if it has a 640px version in cache, it knows it really only needs a 320px version, but since it doesn’t have a 320px version in cache, it’ll use the 640px version instead.
  • Safari does too, except that after it has made its choice, it never changes (like if you resize the browser window).
  • An interesting part about srcset is that the spec allows it to make choices however it wants, perhaps using stuff like network conditions to decide. Most browsers don’t do anything like this yet, except Chrome which downloads the smallest resource should it get a Save-Data header on the HTML document.
  • Joe McGill also noted: “For older iOS devices that don’t support w descriptors in srcset, the first source item in the list will be used, so you may want to lead with your preferred default size if you’re supporting legacy iOS devices.” In other words, those older iOS devices may have supported earlier syntaxes of responsive images, but only with x descriptor (like big-image.jpg 2x), so perhaps specify a good default image as the first in your srcset.

It might be helpful to look at Eric’s fork to more easily see what gets downloaded:

See the Pen Responsive Images Slider by Eric Portis (@eeeps) on CodePen.

Random notes

  • I snagged those food photos from Unsplash.
  • I uploaded them to Cloudinary so that I could use URL params to resize them instead of having to deal with that myself.
  • They are all squares, not because I downloaded them like that, but because I sized them that way in CSS and prevented squishing with object-fit. That means image data is being downloaded that isn’t needed, so I either should have cropped them myself or used Cloudinary URL params to do that.
  • I used the Pug HTML preprocessor for my demo just to reduce code repetition.

This is easier to look at:

img(srcset=` ${img_base}w_640${img_1} 640w, ${img_base}w_320${img_1} 320w, ${img_base}w_160${img_1} 160w,
` sizes=sizes)

…than the output:

<img srcset=",f_auto,q_auto,w_640/v1531407936/robin-stickel-82145-unsplash_qnexwz.jpg 640w,,f_auto,q_auto,w_320/v1531407936/robin-stickel-82145-unsplash_qnexwz.jpg 320w,,f_auto,q_auto,w_160/v1531407936/robin-stickel-82145-unsplash_qnexwz.jpg 160w, " sizes="(min-width: 600px) 160px, 320px"/><img srcset=",f_auto,q_auto,w_640/v1531407936/cel-lisboa-60315-unsplash_qsji9j.jpg 640w,,f_auto,q_auto,w_320/v1531407936/cel-lisboa-60315-unsplash_qsji9j.jpg 320w,,f_auto,q_auto,w_160/v1531407936/cel-lisboa-60315-unsplash_qsji9j.jpg.jpg 160w, " sizes="(min-width: 600px) 160px, 320px"/><img srcset=",f_auto,q_auto,w_640/v1531407936/charles-deluvio-466056-unsplash_ocd3dh.jpg 640w,,f_auto,q_auto,w_320/v1531407936/charles-deluvio-466056-unsplash_ocd3dh.jpg 320w,,f_auto,q_auto,w_160/v1531407936/charles-deluvio-466056-unsplash_ocd3dh.jpg.jpg 160w, " sizes="(min-width: 600px) 160px, 320px"/>

The post Sometimes `sizes` is quite important. appeared first on CSS-Tricks.