DrupalEasy: Visual Debugger module: a modern take on an old idea

If you've been a Drupal developer since before the time of modern Drupal (pre-Drupal 8,) then you probably remember the Theme Developer module. This module is/was used to figure out theme template usage and possible overrides in Drupal 7.

With modern Drupal, this same information is available directly in the HTML source code of a file when Twig development mode is enabled. 

Image removed.

The Visual Debugger module by Marcos Hollanda combines the best of the present with the best of the past to surface template information directly in the user interface without having to dig into the page's HTML. 

Image removed.

Pre-impressions

I will admit that before I installed the module, I was doubtful that I'd be interested in using it. Marcos had pinged me on Slack asking me to take a look at it, and I figured it would be a nice exercise for DrupalEasy Office Hours, which it was.

Much to my surprise though, I really like using it. 

Basic usage

There's not much to say about how to use this module - it works just like you'd expect. Use Composer to get the code, enable the module, then enable Twig development mode and you're done. By default it will appear on each non-admin page of your site, with a handy activate/deactivate icon. There's really not too much to say about its usage 😀.

Current status

The module is in alpha status with several planned features not yet implemented. What is implemented so far appears to be solid and useful. The basic functionality that I expected is there. Click on any section of the page, and the module will display the template file that is used to render that section as well as a list of possible template file override names. This is the same information that Twig developer mode displays in HTML comments.

Marcos let me know that other planned features include theme hook suggestions and displaying caching information; (similar to the Cache review module, perhaps?)

There are other challenges to overcome as well, including how to handle selecting overlapping elements. I did make one very minor suggestion to relocate the module's configuration page which Marcos quickly implemented 🤘🏼.

Who is this module for?

I would definitely put this module in the category of a developer tool for folks who are either new to Drupal theme development or people who prefer a UI instead of scrolling through raw HTML.

I plan on following the progress of this module closely, in hopes that it will be suitable to use during the next semester of Drupal Career Online, where we have a theming lesson that could definitely benefit from this module. 

Tag1 Consulting: Migrating Your Data from Drupal 7 to Drupal 10: Generating migrations with Migrate Upgrade

Series Overview & ToC | Previous Article | Next Article - coming June 27th In the previous article we performed an automated migration via the administration interface with tools provided by Drupal core out of the box. This gave us the opportunity to familiarize ourselves with the different modules that assist with the task, settings that affect the migration, and the results when there are no customizations in place. Today we will leverage the Migrate Plus and Migrate Upgrade modules to generate migrations from the command line, which we can then pick from and customize. Automated migration using the Migrate Upgrade module Let’s start by listing the modules that we will use to run the automated migration from the command line: * Migrate: consists of the core API that can be used to import data from any source. * Migrate Drupal: allows connecting to a Drupal 6 or 7 site to import configuration and content. * Migrate Plus: provides extra source, process, and destination plugins; handles migrations as configuration entities; allows reusing of configuration via migration groups; and more. It is a dependency of Migrate Upgrade and a very useful module on its own. * Migrate Upgrade: provides a Drush...

Read more mauricio Thu, 06/20/2024 - 05:15

Mario Hernandez: Responsive images in Drupal - a guide

Images are an essential part of a website. They enhance the appeal of the site and make the user experience a more pleasant one. The challenge is finding the balance between enhancing the look of your website through the use of images and not jeopardizing performance. In this guide, we'll dig deep into how to find that balance by going over knowledge, techniques and practices that will provide you with a solid understanding of the best way to serve images to your visitors using the latest technologies and taking advantage of the advances of web browsers in recent years.

Hi, I hope you are ready to dig into responsive images. This is a seven-part guide that will cover everything you need to know about responsive images and how to manage them in a Drupal site. Although the excercises in this guide are Drupal-specific, the core principles of responsive images apply to any platform you use to build your sites.

Where do we start?

Choosing Drupal as your CMS is a great place to start. Drupal has always been ahead of the game when it comes to managing images by providing features such as image compression, image styles, responsive images styles and media library to mention a few. All these features, and more, come out of the box in Drupal. In fact, most of what we will cover in this guide will be solely out of the box Drupal features. We may touch on third party or contrib techniques or tools but only to let you know what's available not as a hard requirement for managing images in Drupal.

It is important to become well-versed with the tools available in Drupal for managing images. Only then you will be able to make the most of those tools. Don't worry though, this guide will provide you with a lot of knowledge about all the pieces that take part in building a solid system for managing and serving responsive images.

Let's start by breaking down the topics this guide will cover:

  1. What are responsive images?
  2. Art Direction using the <picture> HTML element
  3. Image resolution switching using srcset and sizes attributes
  4. Image styles and Responsive image styles in Drupal
  5. Responsive images and Media
  6. Responsive images, wrapping up

What are responsive images?

A responsive image is one whose dimensions adjust to changes in screen resolutions. The concept of responsive images is one that developers and designers have been strugling with ever since Ethan Marcotte published his famous blog post, Responsive Web Design, back in 2010 followed by his book of the same title. The concept itself is pretty straight forward, serve the right image to any device type based on various factors such as screen resolution, internet speed, device orientation, viewport size, and others. The technique for achieving this concept is not as easy. I can honestly say that over 10 years after reponsive images were introduced, we are still trying to figure out the best way to render images that are responsive. Read more about responsive images.

So if the concept of responsive images is so simple, why don't we have one standard for effectively implementing it? Well, images are complicated. They bring with them all sorts of issues that can negatively impact a website if not properly handled. Some of these issues include: Resolution, file size or weight, file type, bandwidth demands, browser support, and more.

Some of these issues have been resolved by fast internet speeds available nowadays, better browser support for file tyes such as webp, as well as excellent image compression technologies. However, there are still some issues that will probably never go away and that's what makes this topic so complicated. One issue in particular is using poorly compressed images that are extremely big in file size. Unfortunately often times this is at the hands of people who lack the knowledge of creating images that are light in weight and properly compressed. So it's up to us, developers, to anticipate the problems and proactively address them.

Ways to improve image files for your website

If you are responsible for creating or working with images in an image editor such as Photoshop, Illustrator, GIMP, and others, you have great tools at your disposal to ensure your images are optimized and sized properly. You can play around with the image quality scale as you export your images and ensure they are not bigger than they need to be. There are many other tools that can help you with compression. One little tool I've been using for years is this little app called ImageOptim, which allows you to drop in your images in it and it compresses them saving you some file size and improving compression.

Depending on your requirements and environment, you could also look at using different file types for your images. One highly recommended image type is webp. With the ability to do lossless and lossy compression, webp provides significant improvements in file sizes while still maintaining your images high quality. The browser support for webp is excellent as it is supported by all major browsers, but do some research prior to start using it as there are some hosting platforms that do not support webp.

To give you an example of how good webp is, the image in the header of this blog post was originally exported from Photoshop as a .JPG, which resulted in a 317KB file size. This is not bad at all, but then I ran the image through the ImageOptim app and the file size was reduced to 120KB. That's a 62% file size reduction. Then I exported the same image from Photoshop but this time in .webp format and the file size became 93KB. That's 71% in file size reduction compared to the original JPG version.

A must have CSS rule in your project

By now it should be clear that the goal for serving images on any website is doing it by using the responsive images approach. The way you implement responsive images on your site may vary depending on your platform, available tools, and skillset. Regardless, the following CSS rule should always be available within your project base CSS styles and should apply to all images on your site:

img { display: block; max-width: 100%; }

Easy right? That's it, we're done 😃

The CSS rule above will in fact make your images responsive (images will automatically adapt to the width of their containers/viewport). This rule should be added to your website's base styles so every image in your website becomes responsive by default. However, this should not be the extend of your responsive images solution. Although your images will be responsive with the CSS rule above, this does not address image compression nor optimization and this will result in performance issues if you are dealing with extremly large file sizes. Take a look at this example where the rule above is being used. Resize your browser to any width including super small to simulate a mobile device. Notice how the image automatically adapts to the width of the browser. Here's the problem though, the image in this example measures 5760x3840 pixels and it weights 6.7 MB. This means, even if your browser width is super narrow, and the image is resized to a very small visual size, you are still loading an image that is 6.7 MB in weight. No good 👎

In the next post of this series, we will begin the process of implementing a solution for handling responsive images the right way.

Navigate posts within this series

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: 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: Demystifying components integration with Drupal

Component-based development is something I have been doing for at least five years and it is incredible that I still find myself learning something new every time I work on a new project. In addition to development, I write training curriculums on the topic and this gives me more exposure to this topic than most people. You’d think by now I should have learned all there is to learn about components and integrating them with Drupal, but that’s not the case, and I love it because I alway look forward to learning something new.

The inspiration for this post

I came across an outstanding blog series about Building with Emulsify Part 3: Component Complexity by Evan Willhite of Four Kitchens.

It's not you, it's me

I’d say I’m about 90% onboard with how Evan approaches component integration, but the part I am not a fan of is writing preprocess functions to achieve full integration, mainly because I am not well-versed in preprocess functions or PHP in general. There is absolutely nothing wrong with this, but what if you are someone like me who is not comfortable with preprocess functions or custom modules? So I decided to use most of the work Evan put together, but will perform the integration slightly differently so we only work with Twig and not PHP.

Both instances for which PHP code was required in Evan’s post were the result of using a Paragraph type to reference nodes. My approach will be to eliminate the paragraph type and work directly with the node entity.

Let’s start. I will pick up from Architecture since everything prior to this is typically the approach I take as well.

Architecture

We want administrators to create Nodes of any type and using a Display View Mode we can automatically display them using the card component. The one difference for me is that I don’t have a card variation.

Passing data between entities

Following Evan’s instructions, create a new Display view mode called Card. Here's another minor difference in that my Card uses an image field and date field in addition to title, body, and link fields. Here’s what the card looks like.

Image removed.

In the Card display view mode of an Article content type, ensure Body and Image are available. All other fields should be placed under Disabled. The Title and Date fields don’t display in the Manage Display screens, but they are always available in all Entity templates.

Integrating the Card component within a Node template

Just like in Evan’s post, we still need to associate a Node template with our Card. For this we will use the same template suggestion as Evan, node--card.html.twig.

{% include '@molecules/card/card.twig' with { 'image': content.field_image, 'date': date, 'title': label, 'body': content.body, 'link_url': url, 'link_text': "Read the article", } only %}

Displaying a list of cards with Views

Now that the Card component has been integrated with Drupal, let’s create a simple view to display a collection of nodes displayed as Cards.

The views' settings can be seen below with description of the important configurations to note.

Image removed.

A few things about the view:

  • It’s called Latest Articles
  • The page built by the view can be viewed at /blog
  • Rather than using fields it uses the Card view mode we created earlier. This is the biggest advantage of integrating the Card component with the Entity, any time a node is displayed using the Card Display View Mode, the node will be displayed automatically as a Card.
  • It only pulls nodes of type Article

With some minor CSS the articles would look like this:

Image removed.

In closing

There will be times when writing a preprocess will be required based on the requirements, but whenever possible I’d like to avoid it.

Mario Hernandez: Responsive images, wrapping up

As far as image resolution switching, all the work we need to do is done. We will proceed to creating a quick Drupal view to display a list of news articles each of which will have a responsive image. When we finish with that, we will do the last pending thing, configuring responsive image styles using the <picture> element. You didn't forget about the picture element, did you?

Creating a new Drupal view for news articles

Out of the box Drupal already comes with a view that shows a list of content, but in the Olivero theme this view is not displayed the way we need it, so we will create our own view.

  1. From the admin toolbar, click, Structure | Views
  2. Click Add view
  3. Give the new view any name you wish (i.e. News, Latest News, etc.)
  4. In the View settings select to show Content of type Article
  5. In Page settings check Create a page
  6. Page title can be anything you wish
  7. Type news (lower case) as the path
  8. Under Page display settings chose Unformatted list of teasers
  9. Scroll and click Save and edit
  10. Scroll down and click Save

Two important things in the view above:

  • The path is the url where the content list will be available (i.e. https://my-site.com/news).
  • Using Teaser allows us to make sure of all the previous configuration we've done for responsive images.

With the view now in place, go to the new page we created, /news. This should show a list of news articles. Don't worry if the list does not look like the screenshot we showed earlier. The main thing is that you get a list of articles with images. The images in each article should reflect the configuration we setup for responsive images. You can check this by inspecting the images and you should see many of the attributes we configured. See example below.

Image removed.

  • First, the image is rendering using the img tag and not <picture>
  • The img tag uses the srcset and sizes attributes
  • We can see the diferent image styles we created

That's it! We have completed all the steps for managing responsive images using the resolution switching approach. Now we will complete this series by going back to creating a new responsive image style but this time using the <picture> element.

Responsive image style using art direction

I opted to leave this approach for last because it requires a couple of extra tools that are not part of Drupal core. As previously mentioned, art direction requires that each device gets an image cropped differently to ensure better user experience. Although Drupal provides a cropping "effect" within image styles, it is an automatic cropping process and cannot be customized for each image. This may not always work because we don't know what the focal point for each image we need cropped may need to be when trying to achieve art direction. For example, I may upload an image that I need to crop so the focal point is on the top-left corner, but next time I may upload an image where the focal point should be the bottom-right corner. Focal point refers to picking the area that is the most important to display specially on small devices.

What we need is to be able to manually crop each image we intend to do art direction with as we add them to the site. The good news is that within the Drupal echosystem we have many tools to choose from. In the interest of time, I'm going to simply discuss the tools you need to be able to manually crop your images on demand, but will not go into detail about their configuration or settings as those modules/tools have good documentation you can follow for proper configuration.

Here are the tools we will be working with:

  • Crop API: On its own it does nothing, but in combination with other tools like Image widget crop, it gives you the ability to crop images on demand.
  • Image widget crop: Provides the UI for content creators to be able to crop images on demand. It has a hard requirement of the Crop API module.
  • Cropper: A simple jQuery image cropping plugin for added cropping functionality.

Note: With the exception of the Crop API module, the other two tools above are optional or can be replaced by other similar tools/modules. Often times the modules you pick for a job depend on your unique requirements. So don't feel you need to use the tools above if you know of other equivalent ones that may do a better job.

Next key steps to complete

With your tools inplace, you will probably need to complete the following steps:

  • Creating crop types
  • Create image styles that match your images rendering requirements (aspect ratio, dimentions, crop settings, etc)
  • Adding a new effect to image styles that use "Manual crop"
  • Create new responsive image style using the <picture> element

Crop types: They are in principle similar to image styles. They allow us to setup parameters for how to crop images. In particular, they help us predefine aspect ratios for cropping images. We can create a Square crop type, 3:2 crop type, 16:9 crop type, etc. Important to note, crop types's main job is to define cropping parameters in images, they don't restrict you from manually picking the image focal point.

Image styles: Since we are going to be doing art direction, we will need image styles that allow for custom/manual cropping. We already know how to create image styles, the ones for art direction will follow the behavior of the hero image on this page. Notice how the main images are wide when viewed in a large screen, but if you resize your browser or view the site on a mobile device the images become narrow and their aspect ratio changes. See both examples below.

Image removed.

Image removed.

The examples above shows an image cropped differently for different device sizes. This is Art Direction and is achieved using the <picture> element.

Responsive image styles using <picture>

The biggest difference between creating responsive image styles for resolution switching and art direction is the "Breakpoint group" we select. Let's go through the process now:

  1. If you haven't already, enabled the Responsive image module
  2. Head over to /admin/config/media/responsive-image-style to begin creating a responsive image style
  3. Click Add responsive image style
  4. Type Banner as the label for the responsive image style. This name is solely based on the image examples above. Feel free to assign any name that makes sense to you.
  5. Select Olivero from the Breakpoint group dropdown. If you are using a different theme, choose that theme from the dropdown. We will discuss breakpoints in a bit.
  6. Scroll down and select a Fallback image style. Pick an image style that could be used on desktop and mobile if all failed with our responsive image style.

Breakpoints

Breakpoints are defined in your theme's <theme-name>.breakpoints.yml which is located in the root of your theme. For each device you wish to target you create a breakpoint. Here's an example (I modified the breakpoints slightly for better read):

olivero.sm: label: Small mediaQuery: 'all and (min-width: 500px)' weight: 0 multipliers: - 1x - 2x olivero.md: label: Medium mediaQuery: 'all and (min-width: 960px)' weight: 1 multipliers: - 1x olivero.lg: label: Large mediaQuery: 'all and (min-width: 1440px)' weight: 2 multipliers: - 1x

Based on the breakpoints found in *.breakpoints.yml, you should see an image similar to the one below which should reflect the same breakpoints.

Image removed.

  • Expand any of the breakpoints fieldset and you should see a familiar set of settings. Think of each fieldset you expand here as the <source> element inside the <picture> element. This is where we choose a list of image styles. Then we repeat the process for each breakpoint. This is where we are telling the browser which images to use for each device size and therefore setting up art direction.
  • The sizes field works the same as what we did in resolution switching.
  • Once you have completed all yoru configuration, save your changes.

What's next

Once the responsive image style above is ready to go, You can repeat the process of creating a new view mode for your Media image and configuring it to use the new responsive image style you created above (Banner).

Navigate posts within this series