Mario Hernandez: Image resolution switching using srcset and sizes attributes

In the previous article we defined what art direction is and how to address it using the <picture> element. In this post, the focus will be how to address responsive images when the requirement is image resolution switching. Resolution switching, in the context of responsive images, is rendering identical image content on all devices. Unlike art direction where each device gets a differently cropped image that may vary on aspect ratio, resolution switching uses images that are simply larger or smaller based on the device but retain the same aspect ratio and cropping settings. Resolution switching is how most images are rendered (the rule), the <picture> element approach is the exception to the rule. Take a look at an example of resolution switching below.

Image removed.

The image above demonstrate how multiple resolutions of the same image can be served to different devices. All the images in the example above are cropped exactly the same maintaining the same aspect ratio from large to small.

Using srcset and sizes attributes

Using the srcset and sizes image attributes is how most images are rendered in the web today. As indicated before, this is the recommended way for configuring responsive images if all you need is to switch resolution of images rather than art direction. So how does this approach work? Let's take a look at a typical configuration of the <img> tag using the image above as an example of the different image sizes we will want the browser to choose from:

<img srcset="original-image.jpg 2400w, extra-large.jpg 2000w, large.jpg 1600w, medium.jpg 1080w, small.jpg 800w, x-small.jpg 500w" sizes="100vw" src="large.jpg" alt="Image of sky shown at different resolutions" />

Let's break things down so we can understand this approach better.

  • <img>: Right off the bat we start by using a widely supported html tag.
  • srcset: The srcset attribute in the img tag serves two important roles, 1) It stores a list of images that can be used by the browser, 2) Each image provides its width value which plays a role on the browser choosing the right image.
  • sizes: The sizes attribute tells the browser the width, in relation to the viewport, the image should be rendered at. The value of 100vw shown above, means the image will be rendered at 100% the viewport width on all the devices. You could also use media queries like (max-width: 720px) 100vw, 50vw. This means that if the device does not exceed 720px in width, the image will be rendered at 100% the viewport width, otherwise (if the device is larger than 720px), the image will be rendered at 50% the viewport width.
  • src: The src attribute is used as a fallback if everything fails.

What does it all mean?

Let me explain things in more detail because it is important we understand how this approach is so much better than using the <picture> element.

The biggest difference/advantage of using srcset and sizes versus <picture>, is the fact that we let the browser decide which image is the best image to render on any device. This is possible thanks to all the information we have supplied to the browser. For example, in the srcset we are not only providing the browser with a list of images to choose from, but we are also telling the browser how big each image is. This is very important because the browser will use this information when choosing the image to render. In the <picture> element approach, the image size descriptors are not available.

The sizes value tells the browser the size the image needs to be rendered at in relation to the viewport. This too is extremely important information we are providing the browser because if the browser knows the dimensions of all the images to choose from and how big/small the image needs to be rendered, then the browser is able to pick the best image possible.

But that's not all, the browser is smarter and knows more about the web environment than we do when a page or image is rendered. For example, the browser knows the viewport width used when viewing a website, it knows how fast/slow your internet connection is, and it knows about any browser preference settings (if any), setup by the user. Using all this information the browser is able to determine which image from the srcset is the best to use. In contrast, with the <picture> element, we tell the browser which image to use solely based on the device size.

Closing the gap

Now let's see how using the srcset and sizes attributes closes the gap we identified when using the <picture> tag.

Environment conditions What the developer knows
during development What the browser knows
during image rendering Viewport dimensions No Yes Image size relative to the viewport Yes No Yes via sizes Screen density No Yes Images dimensions Yes No Yes via srcset

Pretty nice huh? Now thanks to the srcset and sizes attributes we've closed the gap and the browser has all the information it needs to ensure the best image is served to each device.

The next post of this series will focus on image styles. These are fun but can also get you in a lot of trouble if not properly done. See you there.

In closing

Time for a story: I recently did an experiment that 100% proves the use of resolution switching using srcset and sizes attributes. As most people nowadays, I use a very large second display when working on projects to fit more apps and see things better. My second display is nice but it's not a 4K display. It's double the physical size of my mac's screen, but the mac's screen resolution is higher by almost double (twice the number of pixels). When I look at an image of a project where I've implemented the practices in this guide, in the large display, and inspected the page, I see the browser has selected an image that is 720px which makes complete sense for the use case I am testing. I then unplugged the second display and viewed the page on my mac's screen (higher resolution), I reloaded the page and inspected it, I noticed the browser has now selected an image that is double the size of the first image. This is exactly the behavior I would expect because my mac screen is of higher resolution and my connection speed is very fast. So the browser was able to make the smart decision to use a different images based on my environment.

Navigate posts within this series

Mario Hernandez: Art Direction using the picture HTML element

In the previous article of this guide we covered the concept of responsive images and some of the challenges that come with implementing an effective system for them. In this article we will go in detail about the concept of "Art Direction" and how this applies to responsive images.

What is art direction?

In the context of responsive images, art direction is the ability to display differently-cropped images based on the device size. For example, a large landscape shot of a person rowing in the middle of a lake is shown when viewed on a large desktop device. If we were to use the same image on a mobile device, that image would shrunk down, making the person in the image very small and hard to see. A better option would be to show a different version of the image that zooms in and focuses on the most important part of the image, the person rowing. See an example of this image below.

Image removed.

Enter the <picture> HTML element

In order to achieve art direction we need to be able to query for the size of the device being used to view the website. Once we've identified the device size we instruct the browser which image to use based on the device size. This will allow us to provide a better user experience as each device will display an image intended specifically for that device. Going back to the image above, we can see that the main image has been cropped differently to ensure the most important part of the image is displayed on each divice.

So how do we query for the device size and how do we instruct the browser which image to use? This is where the <picture> element/tag comes in. Let's take a look at the code that makes all this possible and break it down.

<picture> <source media="(min-width: 2400px)" srcset="images/rowing-2400.jpg 1x, images/rowing-4800.jpg 2x" type="image/webp"> <source media="(min-width: 1280px)" srcset="images/rowing-1400.jpg 1x, images/rowing-2800.jpg 2x" type="image/webp"> <source media="(min-width: 640px) and (max-width: 1279px)" srcset="images/rowing-1200.jpg 1x, images/rowing-2400.jpg 2x" type="images/webp"> <img src="images/rowing-1200.jpg" srcset="images/rowing-2400.jpg 2x" alt="Person rowing on a lake" width="1200" height="800"> </picture>

Note: The order in which the media queries are written within the <picture> tag matters. The browser will use the first match it finds even if it's not the intended one. Therefore, consider the media query order very carefully to ensure the right image is served.

  • <picture>: The <picture> tag is simply a wrapper. On its own it does not do anything.
  • <source>: The <picture> HTML element contains zero or more <source> elements. The browser will consider each child <source> element and choose the best match among them. If no matches are found—or the browser doesn't support the <picture> element—the URL of the <img> element's src attribute is selected. The selected image is then presented in the space occupied by the <img> element.
  • Within the <source> element, you will find some very handy attributes (media, srcset, and type):
    • media: Rembember earlier we said we need to query for the device size? Well, within the media attribute you can write media queries much like the media queries you write in CSS (media="(min-width: 600px)"). This is how we check the size of the device when a page is rendered.
    • srcset: This attribute allows us to provide a list of images the browser can use when the media query finds a match (srcset="img-768.jpg, img-1440.jpg").
    • type: The type attribute specifies a MIME type for the resource URL(s). This is optional if using common image types such as JPG, PNG, TIFF, etc. If you plan on providing images in different file formats, you can do so using the type attribute. This is handy in the event the browser does not support a specific file type (type="image/avif"), as you can then provide a supported file type.
  • <img>: The img element serves two purposes:
    • It describes the dimensions of the image and its presentation
    • It provides a fallback in case none of the offered <source> elements are able to provide a usable image.

And there you have it. The <picture> element is a great way to serve different images based on things like device size or screen density. When the <picture> element was first introduced it required a pollyfill as not all browsers supported it. Nowadays, unless you are supporting Internet Explorer 11 (sorry bro), all other major browsers provide native support for it. Take a look at the chart below for current browser support.

Image removed.

Great! Let's use <picture> on all our images ...NOOOOOOOO!!!!!!

Say what? If the <picture> element is so great, why can't we use it for rendering all of our images? Well, as great as the <picture> element is, it should not be the default solution for serving responsive images in your site. The only use case for the <picture> element is when you are trying to achieve "Art Direction" (cropping your images differently for each device size).

Remember at the begining of this post when I said "In order to achieve art direction we need to be able to query for the device size. Once we've identified the device size we instruct the browser which image to use..."? There lies the problem. Let me explain.

The issue with the statement above is that "we are telling the browser which image". Not only that, but we are doing so solely based on the size of the device. This may not always be the best way to determine which image a device should use. Imagine you are using a nice relatively new laptop with a super high density screen. Based on our rules established within the <picture> element code snippet above, we would end up with an image that is 4800px in size. This is a pretty large image but it's the one that meets our creteria defined in the media query above. If you're home with a decent wifi connection you will never see any issue loading an image this large, but imagine you are working out of a coffee shop, or at a conference with poor wifi connection, or worse yet, you're on the road using your phone as a hotspot and your signal is very bad, now you will really experience some performance issues because we are telling the browser to load the largest image possible because your computer screen is big (relatively speaking). With the <picture> element we can't check how fast your internet connection is, or whether there are browser preferences a user has configured to account for slow internet speeds. We are basing everything on the size of the device.

Then why use the picture element? Well, when developing a website, the developer does not have all the information they need to serve the best image. Likewise, when rendering a page and using the <picture> tag, the browser does not know everything about the environment. The table below shows this in more detail and exposes the gap between the developer and the browser.

Identifying the gap when using <picture>

Environment conditions What the developer knows
during development What the browser knows
during image rendering Viewport dimensions No Yes Image size relative to the viewport Yes No Screen density No Yes Images dimensions Yes No

You may be wondering: "Why did you get us all excited about the <picture> element if we can't really use it?" well, if you are trying to achieve art direction, then you use the <picture> element. It's the recommended approach for that use case. If you are looking for resolution switching, a use case for most images in the web, you need to use the srcset and sizes attributes approach. In the next post we'll dive deep into this technique.

Navigate posts within this series

Mario Hernandez: Drupal base path

Recently I was building a component that required a static image which was not stored in the database but instead needed to be stored somewhere in the file system of the site. There are several ways for serving a static image for example we could have stored the image in the sites/default/files/images/ directory. A very common approach which in many cases would work just fine, however, in my case I was building a component and I wanted for the component image to be located within the same component's directory. This makes sense because if I wanted to reuse or share this component, all component assets would be included in a single directory.

Requirements

My goal with this task was to dynamically point to the image regardless the site this component was running on. Oh yeah, we are running a multi-site architecture with hundreds of sites and a single code base. So this component needed to work in all of these hundreds of sites. Now the challenge seems a little more... "challenging".

¡Manos a la hobra'!'

I started by doing research to determine the best way possible to achieve this. I read about using a pre-process function that would generate a dynamic base path of the site but I was hoping I could keep things simple and do everything on the front-end with only Twig. This would make it a more appealing approach for front-end developers.

After some research, I came across two little gems that became game-chargers for my project. One of these gems is the {{ url('<front>') }} Twig function. This will provide the current site's homepage/base path. The other very handy Twig function is {{ active_theme_path() }} which prints the path of the current active theme (themes/custom/my_theme). While researching for this task, I also found you can use the {{ directory }} Twig variable in your theme's templates to print the active theme's path. A word of coution when using either the {{ active_theme_path() }} function of the {{ directory }} variable as these could have different results depending on your whether you are using them in a base or sub theme. Here's a drupal.org issue that discusses this in more detail.
Armed with these two little functions, and one Twig variable, we can now work in generating a dynamic path to our theme's directory where the static image for our component is located. So this may seem like a simple thing but remember, our component's image should work regardless of the site the component is used on within our multi-site architecture. Some sites even use a different sub-theme but the parent theme is always the same which is where our image is stored.

Building the dynamic path

Before we can use the first function we need to run it through the |render Twig filter. Since Twig will return an array from the {{ url() }} function, we need to convert it to a string because we need the value of the function. Let's take a look:

{{ url('<front>')|render }} # This will give us http://my-site.com/

Next let's work with the theme path function. Similarly to the function above, we will use the |render Twig filter to convert it from an array to a string.

{{ active_theme_path()|render }} # This will give us themes/custom/my-theme

Now that we have two strings we can joint them together to compose the full path to our image:

<img src="{{ url('<front>')|render }}{{ active_theme_path()|render }}/images/image.jpg" alt="alt text" />

If we want to get fancy we could actually set a variable to shorten things a bit:

{% set theme_url = url('<front>')|render ~ active_theme_path()|render %} <img src="{{ theme_url ~ '/images/image.jpg' }}" alt="alt text" />

And there you have it. A dynamic path that will work on any of our sites.

I realized some people reading this already knew all of this but I didn't. So I figured I would share it because I bet there are others out there that also do not know about the {{ url('<front>') }} or {{ active_theme_path() }} Twig functions as well as the {{ directory }} variable. As I said before, there are many ways to handle this challenge, but in my case this is exactly how I wanted to approachh it. I hope this was helpful. Cheers!

Mario Hernandez: Five principles for building better components

When working on a component-based project, building components or patterns, can be a liberating experience because we are able to draft the best markup possible to build the most flexible, scalable and reusable components. If you work with third party platforms such as SharePoint, WordPress, Drupal, or others, this becomes even more rewarding as in most cases content management systems are not known for producing the best markup possible. However, this liberating experience can come a a price if you are not taking the appropriate measures and checks when building your library of patterns.
In this post I am going to discuss five critical principles I follow when building components. My goal is always to achieve first and foremost, semantic markup that works in all devices including assistive technologies, reusability, scalability, and finally, ease of use. In some cases it is hard to achieve all of these goals so it is important to understand where you draw the line and what is more important in the long term.

Disclaimer: Components and Paterns are used interchangeably.

Find patterns in your patterns

Ideally, before you begin building patterns, or components, you want to fully understand how and when these patterns will be used. Certainly there are times when we don’t have all this information when we first start working on a project, but if you do, take a detailed inventory of your patterns. Doing this will help you build better and more reusable patterns.
Failing to identify the patterns in your patterns can lead to bad decisions when building them. For example, let’s say we have a card component for displaying latest news articles, if we don’t know that there are cards for events that look similar to news articles, we may miss an opportunity to turn the card component into one we can use for multiple purposes in our website. But don’t let this get you down, building a website is an iteration process. If you later discover that the news card component can be leveraged for events, it’s perfectly okay to update the card component so it can be used with events as well. My point is that it is preferred if you can catch these patterns early on, but we all know that sometimes designs are not always available in full when a project is started and when they become available we may need to re-think our process of component-building.

Don't sacrifice simplicity over reusability

Reusability when working with components is important and should be at the forefront when building components, however, don’t paint yourself in a corner by over-engineering your components because you found a way to turn a component into a multi-level reusable machine. Trying to make your components do too much can lead to over complex development and in the long run, very hard to maintain. It is better to have components that are simple and easy to maintain even if it means you may have some components that are similar. It is hard to find the balance between simplicity and reusability and this discovery will only come as you work on your components. If you have to choose between simple and reusable, simple may be the way to go.

One set of markup for all devices

Earlier I mentioned that before you start building components you should have a full picture of how and when those components will be used by looking at the design comps. Of course this is not always possible, but in an ideally designs comps give us opportunities to identify areas of improvement or areas that could lead to potential problems. An example of a problem would be if you are provided the designs for mobile, tablet, and desktop. This is great, but let’s say the information displayed at each device type changes in such a way that you don’t know how to best write the markup so it works on all devices. In a perfect world, you should not have to alter the markup of your components per breakpoint. Doing so could lead to confusion on how content is rendered, not to mention problems with accessibility or even SEO. If you find that markup may be a challenge from breakpoint to breakpoint, it is perfectly okay to go back to the designer and propose updates to the design so a unified markup structure could serve all devices. In my experience, the designer would be okay with your recommendations as long as you are not completely changing the layout of the website but instead are simply proposing minor adjustments that don’t change the overall look and feel of the website.
In some cases a designer may not be fully aware that the designs they are proposing could lead to issue when the site is rendered in different device sizes, so it’s okay to bring these issues to their attention and you may find that they are onboard with your suggestions.

Find the right names for your patterns

Another way to paint yourself in a corner is by the name you choose for your components. Component names should be generic and yet descriptive so they can be used on different scenarios. Conversely, names that are too specific will limit when and how you can use those components. Let’s take a look at some bad component names and propose a better name:

  • News Card: If we think back of how we can reuse components, naming a component News Card will limit us on what kind of content we can use this component on. What if Events use a similar card with minor differences? A better name for this component may be Card or Content Card. This allows us to use on any type of content.

  • FAQ Accordion: We have seen this before, we want to build a collapsible list of Frequently Asked Questions so the name makes sense. However, what if we want the same functionality for other type of content such as Forums or Knowledge base content? A better name would simply be Accordion which describes the functionality of the component, not the content that it can hold.

  • Latest News List: Again, we are limiting ourselves to only showing content of type news. A list of content should be generic so we can use them for any kind of content (i.e. Blog posts, events, popular content etc.). A more appropriate name would be Content List.

  • Finally, Homepage Hero: It is not uncommon for Hero sections to be in multiple pages other than the homepage. By naming this component simply Hero, we can leverage it and use it in more than just the homepage. You may wonder, what if I have other types of heroes in non-homepage pages? Well, perhaps we can find alternative names for those, things like Hero Short, or Page Breaker, something that is descriptive and yet provides the ability to be used in multiple pages.

The above are only some examples of how a bad name can not only limit where or what type of content you can use your components with, but it can also lead to building unnecessary components.

Document your components

One of the great things about design systems like Pattern Lab, Storybook and others, is that they provide a way to document the details of your components. Documenting components can go a long way to ensure your entire team is fully aware of the why and how of your components.
I practice that I follow when building components is documenting the technical aspects of the component such as its name, where it is used, and details about any variants of the components. Just as important, I like to define the components fields, their data type and values they accept. This architectural information ensures gives your team and your stakeholders a detailed view of a components role in your project.

In closing, before you begin building components, take the time to study your design comps and take notes of how you feel you can make the most out of your components library. You will not get it right the first time, that’s okay. As long as you are giving yourself the room to iterate through the process, you can always go back and update a component if it will give you more flexibility and will turn your project into a solid component-based system.

In closing

You may not always get it righ the first time, but keeping these principles in mind will help you achieve better implementation of your website's patterns.

Mario Hernandez: Flexible Headings with Twig

Proper use of headings h1-h6 in your project presents many advantages incuding semantic markup, better SEO ranking and better accesibility.

Updated April 3, 2020

Building websites using the component based approach presents all kinds of advantages over the traditional page building approach. Today I’m going to show how to create what would normally be an Atom if we use the atomic design approach for building components. We are going to take this simple component to a whole new level by providing a way to dynamically controlling how it is rendered.

The heading component

Headings are normally used for page or section titles and are a big part of making your website SEO friendly. As simple as this may sound, headings need to be carefully planned. A typical heading would look like this:

<h1>This is a Heading 1</h1>

The idea of components is that they are reusable, but how can we possibly turn what already looks like a bare bones component into one that provides options and flexibility? What if we wanted to use a h2 or h3? or what if the title field is a link to another page? Then the heading component would probably not work because we have no way of changing the heading level from h1 to any other level or add a URL. Let's improve the heading component so we make it more dynamic.

Enter Twig and JSON

Twig offers many advantages over plain HTML and today we will use some logic to transform the static heading component into a more dynamic one.

Let’s start by creating a simple JSON object which we will use as data for Twig to consume. We will build some logic around this data to make the heading component more dynamic. This is typically how I build components on projects I work on.

  1. In your project, typically within the components/patterns directory create a new folder called heading
  2. Inside the heading folder create a new file called heading.json
  3. Inside the new file paste the code snippet below
{ "heading": { "heading_level": "", "modifier": "", "title": "This is the best heading I've seen!", "url": "" } }

So we created a simple JSON object with 4 keys: heading_level, modifier, title, and url.

  • The heading_level is something we can use to change the headings from say, h1 to h2 or h3 if we need to.
  • The modifier key allows us to pass a modifier CSS class when we make use of this component. The modifier class will make it possible for us to style the heading differently than other headings, if needed.
  • The title key is the title's string of text that will become the title of a page or a component.
  • ... and finally, the url key, if present, will allow us to wrap the title in an <a> tag, to make it a link.
  1. Inside the heading folder create a new file called heading.twig
  2. Inside the new file paste the code snippet below
<h{{ heading.heading_level|default('2') }} class="heading{{ heading.modifier ? ' ' ~ heading.modifier }}"> {% if heading.url %} <a href="{{ heading.url }}" class="heading__link"> {{ heading.title }} </a> {% else %} {{ heading.title }} {% endif %} </h{{ heading.heading_level|default('2') }}>

Wow! What's all this? 😮

Let's break things down to explain what's happening here since the twig code has changed significantly:

  • First we make use of heading.heading_level to complete the number part of the heading. If a value is not provided for heading_level in the JSON file, we are setting a default of 2. This will ensue that by default we will have a <h2> as the title, much better than <h1> as we saw before. This value can be changed every time the heading isused. The same approach is taken to close the heading tag at the last line of code.
  • Also, in addition to adding a class of heading, we check whether there is a value for the modifier key in JSON. If there is, we pass it to the heading as a CSS class. If no value is provided nothing will be added.
  • In the next line line, we check whether a URL was provided in the JSON file, and if so, we wrap the Flexible Headings with Twig variable in a <a> tag to turn the title into a link. The href value for the link is ``. If no URL is provided in the JSON file, we simply print the value of Flexible Headings with Twig as plain text.

Now what?

Well, our heading component is ready but unfortunately the component on its own does not do any good. The best way to take advantage of our super smart component is to start using it within other components.

Putting the heading component to use

As previously indicated, the idea of components is so they can be reusable which eliminates code duplication. Now that we have the heading component ready, we can reuse it in other templates by taking advantage of twig’s include statements. That will look like this:

<article class="card"> {% include '@components/heading/heading.twig' with { "heading": heading } only %} </article>

The example above shows how we can reuse the heading component in the card component by using a Twig’s include statement.

NOTE: For this to work, the same data structure for the heading needs to exist in the card’s JSON file. Or, you could also alter the heading's values in twig, like this:

<article class="card"> {% include '@components/heading/heading.twig' with { "heading": { "heading_level": 3, "modifier": 'card__title', "title": "This is a super flexible and smart heading", "url": "https://mariohernandez.io" } } only %} </article>

You noticed the part @components? this is only an example of a namespace. If you are not familiar with the component libraries Drupal module, it allows you to create namespaces for your theme which you can use to nest or include components as we see above.

End result

The heading component we built above would look like this when it is rendered:

<h3 class="heading card__title"> <a href="https://mariohernandez.io" class="heading__link"> This is a super flexible and smart heading </a> </h3>

In closing

The main goal of this post is to bring light on how important it is to build components that are not restricted and can be used throughout the site in a way that does not feel like you are repeating yourself.

Additional Resources:

Managing heading levels in design systems.

Mario Hernandez: Surviving the fire

We are used to watching the news and somewhere in California there is a wildfire destroying nature and people's homes. In 30 years I have lived in the Los Angeles area I have never experienced this first hand. I've have been a victim of earthquakes but this was my first as a fire victim.

We first heard about the fires earlier in the week and the night of November 8th we knew the fires were escalating, but they were nowhere near our neighborhood. All this changed when we went to bed Thursday night and we noticed winds were pretty strong to the point that they would make loud and weird noises as they blew through trees and roof of our place.

We went to bed without a single concern. At 3:30 am. the morning of Friday November 9th, we woke up to loud screams and knocks on our door by the Fire Department. As I opened the door still half asleep, they told me we had 15 min minutes to get out and to head to the nearest shelter in place. They had to repeat this information about 3 times as I was still in disbelief and completely confused. As I looked out our door, this was the image I saw:

Image removed.

You probably can't tell from the picture but that fire is only feets away from our house. That is the same hills I hike on and now they are completely burned.

It gets worse

My wife and I got the kids ready and were only able to pick up passports and personal documents. We didn't have enough time to grab anything else except change cloths to something more practical for the weather.

We arrived at the shelter in place at around 4:00 am. and it was packed with people and pets. We also had a pet of our own. After registering we sit there for a while waiting to hear news but nothing was coming in. At around 5:00 am. we decided it would be best to leave to my parent's house, about 28 miles away. As we are ready to leave we see one of our neighbor who proceeds to give us the worst news of the morning. He informed us our building complex has been completely burned and our house is gone. We didn't know how to respond or react to these news. The thought that we no longer had a house was unreal. I recall telling my wife I didn't believe it but I had no way to prove it. I was probably in denial or perhaps hoping it wasn't true.

As we leave the shelter in place at around 5:30 am., my wife asked me to drive by our house to see for ourselves what it looked like. To our surprise, there was zero damage to our building or buildings in our neighborhood. I was both relieved and extremely upset at my neighbor for giving us such as bad and inaccurate information. I hope I can put this behind us, but for now I am still bothered by this.

The fire stopped short of our place and we could not be more fortunate. I was relieved and felt like we had made it through the worst when we saw our place still standing.

Image removed.

Then it gets better

While at the shelter in place, I notified several people at my job, Mediacurrent.com, that I was being evacuated and would not be able to work that day. The response from everyone was unbelievable. Mediacurrent's partner Paul Chason responded within seconds of my email to let me know that they were behind us and to let him know of anything we needed. This was the same message I received from many colleagues and friends. I have always felt fortunate to be part of a great team like Mediacurrent's, but they go above and beyond to support their employees. This is not the first time they have shown me this kind of support. The first time was when my wife was diagnosed with Chronic Kidney disease and Mediacurrent's response was unbelievable.

As other friends in social media learned about our situation, the flood of support was so great and it gave us strength and hope that we were going to be okay.

As we started communicating with other neighbors we began to feel more confident that we would be able to return home soon.

We came back home on Friday evening to pick up some stuff, including my wife's dialysis machine, which she uses every night as treatment for her chronic kidney disease, and also to clean up and change cloths. Things by then looked pretty normal in our neighborhood but the air quality was still pretty bad so we decided to go back to my parent one more night. On Saturday evening we returned home for good and began the cleaning process which was not as bad as it could had been.

In closing

I hope we never have to go through something like this again, and really hope our friends and family never have to go through this, but having the support of our family, friends and coworkers made this horrible experience more manageable. We want to thank our family for always being there, and for providing a place to stay during this emergency. Our Mediacurrent family for showing us that we are more than coworkers, we care for each other. Thank you to our friends who would continuously check on us and offer help. Finally, our deepest and most special thanks to the everyday heroes who risk their lives to help others; first responders, fire fighters and law enforcements who worked and continue working tirelessly to protect us.

Thank you - The Hernandezes. 🙏 ❤️

Mario Hernandez: Adding Social Share Links to Gatsby

Sharing is caring.

I've been working on my personal blog (this site), for a while. I built it with Gatsby and little by little I have been adding extra functionality. Today I'm going to show you how I added social sharing links to allow visitors to share my posts with others using Twitter, Facebook, LinkedIn, and other channels.

For an example of the Sharing links, look at the icons above the hero image on this and every post on this site.

There are many ways to accomplish this but from the begining I wanted to use something that was simple and did not require too much overhead to run. There are solutions out there that require third libraries and scripts and I wanted to avoid that. A while back I was introduced to Responsible Social Share Links. The beauty of Responsible Social Links is that they do not need any Javascript to work. They use the sharing links available for most social media channels.

Let's take a look at some examples of what these links look like:

Facebook

https://www.facebook.com/sharer/sharer.php?u=URL_TO_SHARE

Twitter

<a href="https://twitter.com/intent/tweet/ ?text=Check this out &url=https://mariohernandez.io &via=imariohernandez" target="_blank">Share on Twitter</a>

Most of these links accepts several parameters. You can see these parameters in more details at the Responsible Social Share Links page for additional information. In addtion, some systems may require you to encode the links but luckily for us Reacts does this for us automatically.

Using the links in a Gatsby site (or React for that matter)

You may think, that's so easy, just modify each of the links with my personal information and done. That's true to an extend. However, the tricky part is dynamically passing the current page's URL and post title to your sharing link. So here's how I did it:

  1. Edit your blog post template. In my case my blog post template is /src/templates/blog-post.js This is based on the Gatsby starter I used. Your mileage may vary.

  2. Add the following code where you wish to display the sharing links to generate a twitter share link:

<Share> <ShareLink href={`https://twitter.com/intent/tweet/?text=${post.frontmatter.title} &url=https://mariohernandez.io${post.frontmatter.path}%2F&via=imariohernandez`}> // Optional icon <LinkLabel>Share on Twitter</LinkLabel> </ShareLink> </Share>

The example above creates a twitter share link and uses the data variables I am already using to print the blog post content. As you know, Gatsby uses GraphQL to query the posts and by doing this you have access to each of the fields in your post (i.e. title, path, tags, date, etc.).

In the example above, I am passing ${post.frontmatter.title} so when the post is shared the title of the post is included as your tweet text. In addition, I am linking to the current post by passing ${post.frontmatter.path}. Finally I am passing my twitter handle.

There are other parameters you can pass to your share links. Things like hashtags, mentions, and more. Following the same pattern you can do the same for Facebook, LinkedIn and others.

A much cleaner approach

You may have noticed that I created the sharing snippet directly in the blog-post.js template. A much cleaner approach would be to create a new React component for all yoru sharing links and include the component in your blog-post.js.

Here's the full snippet for all the social channels I am using:

<Share> <ShareLabel>Share this post</ShareLabel> <ShareSocial> <ShareItem> <ShareLink href={`https://twitter.com/intent/tweet/?text=${ post.frontmatter.title }&url=https://mariohernandez.io${post.frontmatter.path}%2F&via=imariohernandez`} > <span> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-twitter" > <path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z" /> </svg> </span> <LinkLabel>Share on Twitter</LinkLabel> </ShareLink> </ShareItem> <ShareItem> <ShareLink href={`https://www.facebook.com/sharer/sharer.php?u=https://mariohernandez.io${ post.frontmatter.path }`} target="_blank" > <span> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-facebook" > <path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z" /> </svg> </span> <LinkLabel>Share on Facebook</LinkLabel> </ShareLink> </ShareItem> <ShareItem> <ShareLink href={`https://www.linkedin.com/shareArticle?mini=true&url=https://mariohernandez.io${ post.frontmatter.path }&title=${post.frontmatter.title}&source=${post.frontmatter.title}`} target="_blank" > <span> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-linkedin" > <path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z" /> <rect x="2" y="9" width="4" height="12" /> <circle cx="4" cy="4" r="2" /> </svg> </span> <LinkLabel>Share on LinkedIn</LinkLabel> </ShareLink> </ShareItem> </ShareSocial> </Share>

In Closing

If you want to have a clean and light weight way to share your content with others, the Responsible Sharing Links may just be what you need.

Mario Hernandez: Styling Forms Elements

Whether you are a veteran or just getting started with web development, working with web forms is not the sexiest thing but there is no avoiding them. Forms on a website are critical to the website's mission and the visitors using them. In this post I am going to show you how to properly style webforms and form elements so you can ensure they are consistent with your brand and provide a pleasant user experience.

Resources:

I have recording video tutorials on some of the concepts covered in this post. Scroll to the bottom if you are the kind of person who learns better watching tutorials.

Where to start

One thing about forms you can count on is that they are not consistent. In today's API era forms can be generated from any source and you don't always have control of their HTML. I personally work with Drupal a lot and even within it forms can originate from Views, Blocks, Nodes, Paragraphs, Modules, and more. I imagine this is the case with most Content Management Systems. So how do you address something where you can't always predict source or markup of forms?

If you can't beat them, join them

Whether is Drupal or other system, it is best to let that system dictate the markup of forms. Try to bend a system to your needs can prove challenging and not worth the trouble. This is the approach I take and so far this has worked very well for me.

Attributes are your friends

As a Front-End developer for many years, I love a good css class. They make my job a lot easier than not having a class. When it comes to form elements however, it is best to ignore classes and rely solely in attributes. What attributes you may be asking yourself? Let's take a look

From element types

The type attribute in form elements make it easy to style them in a global manner. Rather than styling form elements based on their css class or ID, the type attribute is the best approach. Each form field has a type attribute which makes it possible for browsers to render the element as expected. The type attribute can also play a factor in Javascript and form handling, but for now we are going to focus on styling.

  • Input fields: Input fields such as text fields, are probably the most common form elements in a form. But don't let its simplicity fool you because text fields come in many types; the most common being text. this is the type for a typical text box where you can type just about any kind of information. This sometimes leads to developers using it for anything including for data that should be in a different form type. Let's take a look at the various types a text field can be:

    • text: Used for most text fields and accept any string of text
    • email: Used to capture email address. Using this type is recommended for email addresses as it provides regular expressions to validate the data entered in the field meets the patterns of an email addresses. In addition, using this type of field makes it possible for your mobile devices to show a custom keyboard where the "@" sign is available without having to toggle your keyborad characters to find it.
    • password: As you can imagine, this makes it possible to hide passwords from view as you type them.
    • search: Elements of type search are text fields designed for the user to enter search queries into. These are functionally identical to text inputs, but may be styled differently by the user agent.
    • tel: Similarly to the email address, using this type allows for the keyboard on mobile devices to display numbers by default rather than alpha characters.
    • url: Similarly to email, this provides you with a custom keyboard on mobile devices that make it easier to type a common url.

As you can see from the examples above, text fields may seem simple but they come in all flavors. In most cases, the goal of form elements is to be styled the same across an entire site. So it is recommended you style these elements globally so no matter where they are used they automatically inherit the intended styles. So how do you style them globally? Let's take a look:

Here are a couple of examples of differnt input fields which we will style to ensure they all look similarly everywhere.

<input type="text" name="firstname"> <input type="password" name="password"> <input type="email" name="email">

Styling

input[type='text'], input[type='password'], input[type='email'], input[type='tel'], input[type='search'], textarea { background-color: #ffffff; border: 1px solid #000000; height: 40px; padding: 10px; width: 100%; } textarea { height: initial; }

By using the element's type attribute we can collectively style them with a single set of rules. As you may have noticed I included textarea as on of the elements because I want textareas boxes (multi-row textbox), to inherit all of the styles from text boxes with the exception of the height property; thus we override the height property while keeping all other styles the same as text boxes.

Button elements

Buttons are elements you typically want to display with consistent styles across your entire website. This includes buttons you may create yourself and those provided by the content management system you may be working with. So similarly to input fields above, we can't always rely on IDs or classes to style them. However, similarly to the input fields above, we can rely on the type attribute to style the different type of buttons in our site. Different type of buttons? yes, there are different types. Let's tae a look.

Markup

<a class='button'>I want to look like a button</a> <button>I'm an actual button</button> <input type='submit' value='Yo tambien'> <input type='reset' value='Me too'>
  • All elements above will have the same look and feel.
  • The first 3 elements should look identical, but the last one (type=['reset']) should look slightly different because it's not a primary button, it's more of a secondary button.
  • Sometimes this secondary button will be used to cancel or to reset someting on a page. While the top 3 will be used for important actions such as submit, save, etc.
  • Let's style them now

Styles

.button, button, input[type='submit'], input[type='reset'] { background-color: rebeccapurple; border-radius: 2px; border: 2px solid rebeccapurple; color: #ffffff; cursor: pointer; display: inline-block; font-size: 18px; line-height: 1; padding: 20px 40px; text-align: center; text-decoration: none; white-space: nowrap; margin-bottom: 20px; } .button:hover, .button:focus, button:hover, button:focus, input[type='submit']:hover, input[type='submit']:focus { background-color: rgb(126, 63, 189); /* lighter purple */ color: #ffffff; text-decoration: none; }
  • We are including all the button elements in our initial set of styles. The reason for this is that we want all the buttons (regardless of their type of function), to share the same shape, font size, font-weight, border width, hover behavior, and other properties.
input[type='reset'] { background-color: #ffffff; border-color: rebeccapurple; color: rebeccapurple; } input[type='reset']:hover, input[type='reset']:focus { background-color: #ffffff; border-color: #444444; color: #444444; }
  • Then for the reset type only, we are styling this button with white background and purple text. This will ensure this button will not stand out as much as the other buttons.

Radio buttons and Check boxes

Probably the hardest elements to style due to their dynamic nature, they have a hard time fitting in with the rest of HTML elements. Rather than link you to another blog post where you can copy and paste the necessary CSS to style these elements, I am walk you through the process of styling them.

Checkout the Codepen for these elements.

Markup

The typical markup for a checkbox or radio button looks like this:

<div class="checkbox__item"> <input type="checkbox" id="checkbox1" name="checkboxname" value="Item 2"> <label for="checkbox1">Item 2</label> </div> <div class="checkbox__item"> <input type="checkbox" id="checkbox2" name="checkboxname" value="Item 2"> <label for="checkbox2">Item 2</label> </div> <div class="radio__item"> <input type="radio" id="radio1" name="radioname" value="Item 2"> <label for="radio1">Item 1</label> </div> <div class="radio__item"> <input type="radio" id="radio2" name="radioname" value="Item 2"> <label for="radio2">Item 2</label> </div>

Styles

Out of the box, you can not style the native checkbox nor radio button elements. To be able to apply custom styles we need to do it in a hacky way. This is my favorite way to style these elements.

Drawing the checkbox

/* visually hide the native checkbox and radio buttons. */ input[type='checkbox'], input[type='radio'] { position: absolute; opacity: 0; }
  • By setting absolute position and opacity to zero, we are hiding the native radio and checkbox elements from view. However, we need the elements to still function as expected so using visibility-hidden or display: none are not viable options.
  • Although we are visually hiding the elements, they are still available in the DOM so we can interact with them and also so they can be available to assistive technologies such as screen readers.
/* Add space to the left of the label for later use. */ label { position: relative; padding-left: 35px; }
  • We set relative position on the label as we prepare to add pseudo elements in the next steps.
  • The left padding here will allow us to draw a box or a circle for the checkbox/radio button. More on this later.
/* Draw a square box with border using a pseudo element (`::before`). */ input[type='checkbox'] + label::before { border: 2px solid #e15b00; content: ''; display: inline-block; height: 24px; left: 0; position: absolute; top: -2px; width: 24px; }
  • First we define a sibling element of the checkbox with the + sign. The sibling element being the label element. If you look at the markup we wrote above, you will notice that the checkbox and the label are siblings. This is also true for the radio button and its label.
  • Using a ::before pseudo element on the label, we are drawing a 24px square box.
  • For any pesudo element to be visible on the page, we need to assign the property of content:, even if it's value is empty as shown above.
  • We then add a 2px border on the box. This box is what will be presented as the actual checkbox for the user to interact with (check/uncheck).
  • By setting the box with absolute position, we are positioning just to the left of the label. The position of the box is in relation to the label's position (hence relative position on the label).
/* Draw checkmark using a ::after pseudo elment on the label */ input[type='checkbox'] + label::after { border-bottom: 3px solid #fff; border-left: 3px solid #fff; content: ''; display: inline-block; height: 10px; left: 4px; position: absolute; top: 2px; transform: rotate(-45deg); width: 18px; }
  • The same way we drew the box previously, now we draw a checkmark symbol using a ::after pseudo element on the label. This means we are drawing the checkmark symbol after the label element.
  • In reality, we are drawing a rectangular box with left and bottom borders of 3px. By rotating the box negative 45 degrees, this makes it look like a checkmark.
  • We then use absolute position on the checkmark so we can position it right in the middle of the box we drew before.

Drawing the radio button

Before proceeding with the styles, let's repeat the steps above but this time for the radio buttons. These styles are extremely similar with the exception of in stead of drawing a square box, we will be drawing a circle with an outline, and instead of a checkmark, we will be drawing a filled circle in the middle of the outlined circle.

/* Draw a circle and add borders to it */ input[type='radio'] + label::before { border-radius: 50%; border: 2px solid #e15b00; content: ''; display: inline-block; height: 24px; left: 2px; position: absolute; top: -4px; width: 24px; } /* Draw an inner circle */ input[type='radio'] + label::after { background-color: #e15b00; border-radius: 50%; content: ''; display: inline-block; height: 20px; left: 6px; position: absolute; top: 0; width: 20px; }
  • This time we are targeting the input type of radio and we are using border-radius to draw a perfect circle.
/* Hide checkmark and inner circle by default */ .radio input[type='radio'] + label::after, .checkbox input[type='checkbox'] + label::after { content: none; }
  • By default, we don't want either the checkboxes or radio buttons to be checked. So we set the value of content: to none. This will present the checkboxes and radio buttons unchecked.
/* Show checkmark and inner circle when input is checked */ input[type='radio']:checked + label::after, input[type='checkbox']:checked + label::after { content: ''; }
  • Using the :checked pseudo class (input[type='radio']:checked, input[type='checkbox']:checked), we then show the checkmark or inner circle by setting the content: property's value to empty ('' i.e. removing none). The :checked pseudo class becomes available when the checkbox or radio buttons are click-checked and when that happens, then we show the checkmark or inner circle.
/* When box is checked, add background color. */ input[type='checkbox']:checked + label::before { content: ''; background-color: #e15b00; }
  • Since the checkmark we drew is white, we are adding a background color inside the checkbox to display the checkmark. We are doing this only when the :checked pseudo class is present.
/* Add focus styles when elements are in focus */ input[type='radio']:focus + label::before, input[type='checkbox']:focus + label::before { outline: rgb(59, 153, 252) auto 5px; }
  • Finally, using the :focus pseudo class, we are adding basic outline styles to show the "on focus" state of the inputs. We need to do this since we are not using the native input elements. If we were, the browser would automatically add these styles to our inputs.

Resources

I have recorded tutorials on severalof these things. Check them out if you are the kind of person who learns better through video tutorials.

Mario Hernandez: Getting started with Gatsby

As many developers, when I hear the words "static website" I immediate think of creating flat HTML pages and editing them by hand. Times have changed. As you will see, Static Site Generators (SSG), offer some of the most advanced features and make use of latest technologies available on the web.

Static Site Generators are nothing new. If you search for SSG you will find many. One of the most popular ones is Jekyll, which I have personally worked with and it's a really good one. However, this post focusing on Gatsby. Probably one of the hottest system for creating static sites.

What is Gatsby?

Gatsby's primarily objective is to build static sites, but as you will learn, that's just the tip of the iceberg.

Gatsby is a blazing-fast static site generator for React.

How does Gatsby work?

While other SSGs use templating languages like Mustache, Handlebars, among others, Gatsby uses React. This not only allows for building modern component-driven websites, it also provides an incredible fast page rendering. Like mind-blowing fast.

Extending Gatsby

One of the most powerful features of Gatsby is its growing number of "Plugins". Plugins are the building blocks of Gatsby. They allow you to implement new features and functionality by running a couple of commands and making some configuration changes. Anything from adding Sass to your React project, creating a blog, configuring Google Anaylitics and many many more.

Plugins are contributed code kindly provided by the generous Open Source community which totally rocks. Anyone is able to write plugins and make them available to the world to consume and use.

Check out their Plugins page for a full list of ways you can take your static site to the next level.

Editorial Process

So we are building static sites and you may be wondering How do I create content for my site? There are several ways in which you can create a content editign workflow for your site. Probably the easiest way is to use static Markdown files. Markdown is a lightweight markup language with plain text formatting syntax. It is designed so that it can be converted to HTML and many other formats. Markdown is often used to format readme files, for writing messages in online discussion forums, and to create rich text using a plain text editor. This blog is using markdown. Since I am the only creating content I don't need a fancy administrative interface to crate content.

Markdown is only one of the ways you can create content for your static sites. Others include more advanced methods such as plugging in Gatsby with your Content Management System (CMS) of choice. This includes Wordpress, Drupal, Netlify, ContentaCMS, Contenful, and others. This means if you currently use any of those CMSs, you can continue to use them to retain a familiar workflow while moving your front-end workflow to a simpler and easier to manage process. This method is usually referred to as decoupled or headless, as your back-end is independent of your front-end.

Quering Data

As previously mentioned, Gatsby with the power of React create the perfect system for building robust, flexible and super fast static sites. However, there is a third component that takes that power to a whole new level, and that is GraphQL.

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.

Deploying Gatsby

Hosting for a Gatsby site can be done anywhere where React apps can run. Nowadays that's pretty much anywhere. However, before investing in an expensive and highly complicated hosting environment, take a look at some of the simpler and less expensive options on this page.
You will see that for a basic website, you can use several of the free options such as github pages, netlify and others which already include advanced continuous integration workflows. For more advanced sites where a CMS may be involved, you can also find options for deployment that will simplify your DevOps process.

My own blog is running out of a github repo that automatically get deployed when I push new updates. This is happening via Netlify which to me is probably the easiest way I have ever deployed a website.

In closing

Don't worry if you are a little skeptical about static site generators. I was too. However, I gave Gatsby a try and I see myself building more gatsby sites in the future. Before Gatsby I worked with Jekyll which is also a great static site generator, but what sets Gatsby apart is its seamless integration with React and GraphQL. The combination of those 3 provides endless posibilities in your web building process. Check it out.