Jon Yablonski – CSS-Tricks https://css-tricks.com Tips, Tricks, and Techniques on using Cascading Style Sheets. Tue, 11 Apr 2017 00:57:50 +0000 en-US hourly 1 https://wordpress.org/?v=6.1.1 https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/07/star.png?fit=32%2C32&ssl=1 Jon Yablonski – CSS-Tricks https://css-tricks.com 32 32 45537868 Developing Extensible HTML and CSS Components https://css-tricks.com/developing-extensible-html-css-components/ https://css-tricks.com/developing-extensible-html-css-components/#comments Mon, 29 Aug 2016 13:15:15 +0000 http://css-tricks.com/?p=244866 The following is a guest post by Jon Yablonski. Jon is going to show us an example of how we might approach markup such that one component is particularly versatile. It works as-is, and has a standardized way of


Developing Extensible HTML and CSS Components originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
The following is a guest post by Jon Yablonski. Jon is going to show us an example of how we might approach markup such that one component is particularly versatile. It works as-is, and has a standardized way of making variations (adding a single class) that allow the design to be altered to fit the situation.

Media patterns

The days of building fixed-width web pages from pixel-perfect Photoshop files are gone. In order to produce flexible layouts that smartly adapt to any screen size, our workflows have undergone changes to be more iterative and agile. We’ve come to understand the importance of modularity and how it facilitates the flexibility we need to stay nimble in the browser. As a designer and front-end developer, this flexibility is integral to how I approach web projects. I find myself making design decisions in the browser more often than design files, and to support this workflow I need the ability to build user interface modules that can be easily extended.

Extendable Modules

What I’ve come to value highly is extensibility, a systems design principle where the implementation takes future growth into consideration. The central theme of extensibility is to provide for change while minimizing impact to the existing system. For front-end development, this means building module variations that can easily be extended to fit the needs of the user interface while preserving the underlying foundation of the module. The end result is less code bloat, less fragmentation of the code base due to one-off solutions, and code that is easier to maintain.

Building for Extensibility

To ensure consistency in the structure of our components and patterns, it’s necessary to build them in a fashion that is repeatable and predictable. The following are the basic steps I take:

Step 1: Identify the Module Type

The first step is to identify the type of module we are working with, which can be classified into one of two categories: component or pattern. A component is an independent, modular object that has no children elements, but can have modifier states that change their appearance (example: buttons, messages, thumbnails). A pattern on the other hand is an object that has children (which can be stand-alone components as well), all of which is affected by the parent object (example: header, header logo, header nav). Both components and patterns can have modifier states that change their appearance or structure.

Step 2: Define the Module Foundation

The next step is to find the component or pattern’s foundational rules that all variations of the component will inherit. These rules should be relatively minimal and reserved for properties that will rarely change. More often than not, I find these rules are properties like margin, padding, position, and display.

All code examples in this article are using BEM (block, element, modifier) naming methodology. BEM offers a number of advantages, but perhaps my favorite is that I can simply look at a piece of markup is doing from its name alone. If you want to know more about this naming methodology, I’d recommend checking out this article for a good introduction.

HTML Foundation
<div class="block"></div>
CSS Foundation
.block {
  position: relative;
  margin: 0 0 1em;
}

Step 3: Define Common Elements

If you’re building a component, then you can skip this step and go straight to the next step; but if you’re building a pattern that will contain child elements, then the next step is to define common elements. These elements are thematically-related to the parent block (but can exists outside of the pattern as stand-alone components).

HTML Common Elements
<div class="block">
  <div class="block__element">…</div>
  <div class="block__another-element">…</div>
</div>
CSS
.block__element {
  padding: 1em;
  background: white;
  border: 1px solid black;
}

.block__another-element {
  position: absolute;
  top: 0;
  right: 0;
}

Step 4: Extend with Modifiers

The final step is to extend your component/pattern with modifiers. Modifiers are essentially variations that extend the foundational block and children, and can be created as you need them.

Example of HTML modifier class

<div class="block block—modifier">
  <div class="block__element">…</div>
  <div class="block__another-element">…</div>
</div>

Example of CSS Modification

.block—modifier {
  border-top: 3px solid red;
}

.block—modifier .block__element {
  background: grey;
}

Examples

Now that we’ve taken a look at the basic steps involved with building extendable components and patterns, it’s time to explore some examples. We’ll begin with a relatively simple component and how it can be extended to cover a variety of scenarios, and then we’ll look a slightly more complex pattern.

About Components

The following is a demo of several common components along with variations. Each component consists of a parent block and modifiers that extend the style of the block. This allows for variations to be rapidly created, giving you the flexibility to quickly iterate and adapt components to any circumstance in your user interface.

Common Components Example

See the Pen Common Extendable Components by Jon Yablonski (@jonyablonski) on CodePen.

Components by their nature should be relatively simple, as they do not contain child elements. Now, let’s take a look at a something that is slightly more complex.

About Patterns

A media pattern is an object that consists of a media element (this can be an image or video), and related content (usually in the form of text). You might be familiar with a variation of the media pattern known as a ‘media object’ or ‘flag object’, which we’ll touch on in a bit. This pattern is a great example of how building with extensibility in mind provides endless flexibility.

Media Default Pattern

We’ll start with our default pattern, or how it will be displayed with no modifiers. I’ve made some assumptions here by leveraging an <article> tag to provide more semantic information, but this can be changed to be any tag you want. The core styles of our media pattern are:

  1. A flex container in which its children do not wrap
  2. A bit of margin

These are styles that all media pattern’s will inherit. In addition, each media pattern will contain the media item (in this case an image), and the media body which consists of a title and a definition list.

See the Pen Default Media Pattern by Jon Yablonski (@jonyablonski) on CodePen.

Media Card Pattern

While this default variation of our media pattern might be sufficient in some circumstances, there will be plenty others in which you’ll want to drastically alter its appearance. The next step is to begin identifying variations which will allow our pattern to adapt to a variety of situations. Let’s begin with a variation that is not a huge departure from the default appearance — a card variation. The premise is that very little will need to change to our markup, and we can change the appearance of our pattern by simply adding a modifier class to the parent block:

See the Pen Media Card Pattern by Jon Yablonski (@jonyablonski) on CodePen.

Media Object Pattern

Let’s say, later on, I’ve discovered I need a pattern which the image and text are displayed side-by-side when there is enough space available. This is a pattern commonly known as a ‘media object’. To create it, we can simply extend the media pattern we already have in order keep redundant code minimal.

See the Pen Media Object Pattern by Jon Yablonski (@jonyablonski) on CodePen.

Media Slat Pattern

Let’s push things a bit further with a variation that will really put it to the test. The variations we defined thus far are accommodating pretty much all my design needs, but I need one more with a little more of an impact. Let’s create a variation that is spans the full-width of the window with the body filling half, and the image filling the other. In addition to this, I want to make sure the body content aligns with the other content on the page. We’ll call this variation a ‘media slat’:

See the Pen Media Slat Pattern by Jon Yablonski (@jonyablonski) on CodePen.

Now we have several variations of our media pattern: we have the default variation, the card variation, the object variation, and finally the slat variation. These variations of our pattern are all useful in different circumstances, and they all make sure of the same underlying foundation of code! What’s great about this is that any change that happens to our pattern will affect all patterns, so each instance of this pattern will remain in sync and consistent.

Conclusion

We have covered why extendable components and patterns are better when building interfaces, which center around flexibility and maintainability. And to illustrate this, we covered the steps involved in creating some extendable components. The advantages of building interfaces in this way will become apparent right away because you will spend less time refactoring due to an unexpected design change or addition, and your styling that makes up these components will be easier to maintain.


Developing Extensible HTML and CSS Components originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/developing-extensible-html-css-components/feed/ 23 244866
Optimizing for Large-Scale Displays https://css-tricks.com/optimizing-large-scale-displays/ https://css-tricks.com/optimizing-large-scale-displays/#comments Mon, 09 May 2016 14:11:49 +0000 http://css-tricks.com/?p=241350 The following is a guest post by Jon Yablonski. Jon told me he recently worked on a project where there was a lot of emphasis placed on giant screens. Jon is going to show us that just like RWD


Optimizing for Large-Scale Displays originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
The following is a guest post by Jon Yablonski. Jon told me he recently worked on a project where there was a lot of emphasis placed on giant screens. Jon is going to show us that just like RWD work of any kind, it requires planning. Extra media queries are useful for targeting the huge displays, and typography can take you far.

With the rise of ultra high-definition displays and devices that enable browsing the web via smart TVs, the internet is increasingly being accessed and viewed on screens that dwarf traditional desktop displays. Most websites fall short of being optimized for this scale. But if you’re building responsive websites, it’s likely that the tools you need to scale your content are already in place. In this article, we’ll take a look at the challenges and techniques for optimizing your site on large-scale displays.

Identifying Large-Scale Displays

First, let’s identify what exactly constitutes an large-scale display. According to W3Counter, screens with a device width of 1366×768 pixels are the most common large device resolution. The next common large resolution is 1920×1080 pixels. These values come primarily from desktop monitors, and most websites will adapt to these screens without much problem.

Traveling up the scale, the next most common device width lands at 2560 pixels wide. This width is what you will find with most high-definition desktop displays that start with 27” monitors. It is also the range at which most websites begin to struggle because of excess screen real-estate.

A small sampling of popular websites, each captured with a screen size of 2560×1600 pixels

Take for example the image above, which depicts a small sampling of popular websites that were each captured at a screen size of 2560×1600 pixels. As you can see, none of these sites are optimized for this scale: text is too small, the volume of content packed into a relatively small space makes it difficult for the eye to know where to focus, and everything seems to be dwarfed by the whitespace that surrounds it. Each of these factors contribute to a decrease in legibility and less than optimal user experience.

So what is preventing designers and developers from optimizing for large-scale displays? The answer is sure to vary by team, but there are definitely a few technical challenges at this scale. Let’s identify what these challenges are.

The Challenges of Large-Scale Displays

The challenges of optimizing for large-scale displays center around how to scale and manage content. Broken down into categories, these challenges would look like the following:

Content choreography

Content choreography refers to how content is adapted proportional to screen size, serving the best possible experience at any width. The larger the screen, the less proportional the content will seem. This is a problem for a few reasons: 1) the awkward space that results is distracting, 2) the excessive space can dwarf the content, which makes the content seem smaller than it is, and 3) legibility will most likely suffer as a result of being too small.

Generally speaking, the way content adapts on small screens is pretty straight-forward: we stack content within a single column and adjust the visual order if necessary. On the other hand, the way we approach this on large devices can vary greatly, depending on the content and the space available. If you avoid adapting your content to the excess space made available on large-scale displays, your content will most likely seem dwarfed in comparison to the negative space that surrounds it. But, if you attempt to fill the space with content by introducing more columns, you risk visually overwhelming the user by presenting too much content in a relative area of the screen.

Images

Images pose a number of unique challenges on large-scale displays. Since most large screens are also higher resolution, we must manage additional variations of each image to ensure the appropriate image is served. In addition, we must also manage how the images will behave in the context of the layout. Images that don’t scale with the screen can leave awkward gaps of space between them and other elements. In contrast, images that scale too large can take away from other elements and become overwhelming. Since there is no one-size-fits-all solution to the challenges that images pose, you must carefully consider how you want to manage them based on the unique needs of your content.

Techniques for Optimization

Now that we’ve identified the various challenges that come with large-scale displays, let’s take a look at some approaches to optimizing our content for this scale.

I’ve created a site to demonstrate each technique we’ll be looking at for optimizing for large-scale displays. Given the topic, I chose a theme that seems appropriate in the context of scalability, the Death Star II. I will be referring to bits of code from this demo, but you can see it in it’s entirely here on CodePen.

Screenshot of the Death Star II demo on CodePen

The method you use to optimize your content for large-scale displays will vary, depending on your content. One option is to simply adjust the layout in order to present your content in a way that takes advantage of the additional screen space. Another method is to responsively upscale your content so that it fits the space proportionately. And of course, you could also leverage a combination of both methods. In our demo, we will responsively upscaling our content in order to provide a superior experience for users on larges-scale displays.

Plan Ahead

The first step in optimizing for large-scale displays to is plan for them. By planning ahead, you are minimizing surprises and ensuring that everything works together before diving in, at which point it’s harder to make changes. If your design process involves working in a design application in order to visualize how you want content to behave, then do so by creating a canvas size that represents a extra large screen alongside your other comps that represent more traditional screen sizes. If you prefer to design in the browser, then plan how you want your content to behave on large screens by first sketching out your ideas.

For our demo, I chose to start with sketching out the general idea for the layout and content. By doing this first, I got a sense for how I should break the site down into sections, and how the page as a whole could be structured to accommodate these sections. Next, I explored design aesthetic a bit by creating a high-fidelity composite in Sketch, which allowed me to identify design elements such as fonts, colors and proportion. The key here is to stay loose and don’t worry about pixel perfection — the important things like interaction, scaling and even font-size should be decided in the browser.

Initial wireframe sketches and design exploration for the Death Star II demo

Build with Relative Units

Relative units such as percentages, EMs, and REMs are essential to responsive web site because they provide us a way to build on a flexible foundation. By using relative units everywhere, we can ensure that measurements will remain proportional, regardless of the font size set by the user. This is in direct contrast to explicit pixel values, which will not scale relative to a user’s settings, and therefore measurements will not be proportional if the user scales up or down the default font size.

// Breakpoints
$bp-small: 48em; // 768px
$bp-medium: 64em; // 1024px
$bp-large: 85.375em; // 1366px
$bp-xlarge: 120em; // 1920px
$bp-xxlarge: 160em; // 2560px

// Media Queries
$mq-small: "(min-width: #{$bp-small})";
$mq-medium: "(min-width: #{$bp-medium})";
$mq-large: "(min-width: #{$bp-large})";
$mq-xlarge: "(min-width: #{$bp-xlarge})";
$mq-xxlarge: "(min-width: #{$bp-xxlarge})";
$mq-retina: "(-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)";

Take for example the media queries used for our Death Star II demo. By defining our media queries in EMs, we are ensuring the design scales proportionately without enabling awkward scrolls bars in the browser if the user was to adjust the zoom level.

Scaling Text

In addition to media queries, relative units also come in handy for text. Font-sizing can be controlled globally by adjusting the font-size property on the <body> element, as long all text on the site is defined in relative values like EMs. This is especially useful when it comes to large screens because it allows you to proportionately scale type up globally as screen size increases, thus avoiding the text in your design from seeming too small in relation to the screen.

To implement this on our demo, we began by defining some variables. As you can see below, the first step is to define what the base value of your font sizing will be. In our case it is set to 1em, which means we are defaulting to whatever default font-size is set by the browser. This base value can easily be adjusted in browser, but it usually defaults to 16px. It’s also useful to define the base line-height values here in conjunction with font-size. You’ll notice we are leaving off the unit at the end of these line-height values, also known as ‘unit-less’ values. By setting line-height this way, we ensure that child elements can compute their line heights based on their computed font size, instead of inheriting this value from its parent.

// Font-Size
$base-font-size: 1em;

// Line-Height
$base-line-height: 1.5;
$header-line-height: 1.25;

Next, we apply these variables to our <body> element and increase both font-size and line-height gradually as the screen gets larger. As mentioned before, this will scale up the text size everywhere if you have set font sizes in your content as a relative unit like EMs.

body {
  font-size: $base-font-size;
  line-height: $base-line-height;

  @media #{$mq-medium} {
    font-size: $base-font-size*1.2;
    line-height: $base-line-height*1.2;
  }

  @media #{$mq-large} {
    font-size: $base-font-size*1.3;
  }

  @media #{$mq-xlarge} {
    font-size: $base-font-size*1.4;
  }

  @media #{$mq-xxlarge} {
    font-size: $base-font-size*1.6;
  }
}

So how much of a difference does scaling text up to fit the proportions of the screen? Turns out, pretty significantly. Take a look at the image below, which illustrates the difference between our demo when font-size isn’t scaled up on the body (on the left), and when font-size is globally scaled up (on the right) at 2560 pixels wide. Not only is the scaled-up version more legible, but all elements on the page have been proportionately scaled up to activate the space.

Screenshots at 2560px wide illustrating the difference between not scaling text up globally (left) versus scaling text up (right).

Containment

When it comes to controlling content, there are few tools in the responsive web design toolbox as useful as the ubiquitous ‘container’. This element has one purpose, and that is to control the maximum-width in which our content can extend to. Take for example the following, which is the most common way you see these elements defined in CSS:

.container {
  margin: 0 auto;
  max-width: 1024px;
}

This approach works but, but it doesn’t scale to large screens because the maximum width is too dependent on a specific width. Even if the max-width value was increased to something much larger, it isn’t relative to the viewport width. A better way to approach this is to define the left and right margins as relative units and gradually increase these values as the screen size gets larger. As a result, content will be contained in relation to the screen width and feel more at home if the screen is extra large.

.container {
  margin: 0 4%;

  @media #{$mq-medium} {
    margin: 0 8%;
  }

  @media #{$mq-large} {
    margin: 0 12%;
  }

  @media #{$mq-xlarge} {
    margin: 0 18%;
  }
}

Manage Images

How you manage images on extra large screens is entirely dependent dependent on your project needs, but you will most likely need to serve up higher resolution variations of each image to ensure images aren’t too small. The approach we take is different, based on how the image is applied.

.detail {
  height: 0;
  padding-bottom: 40%;
  margin: 0 0 $base-spacing*2;
  background-image: url(/Death-Star/detail_sml.jpg);
  background-position: center center;
  background-size: cover;

  @media #{$mq-xlarge} and #{$mq-retina} {
    background-image: url(/Death-Star/detail_sml%402x.jpg);
  }

  @media #{$mq-medium} {
    background-image: url(Death-Star/detail_med.jpg);
  }

  @media #{$mq-medium} and #{$mq-retina} {
    background-image: url(/Death-Star/detail_med%402x.jpg);
  }

  // Additional media queries

}

For background images, this is quite simple: define the background image on the appropriate element, give the element dimensions, and define higher resolution sources of the image within media queries. The image above illustrates how this is done on our demo. Notice that we are setting the height property to 0, providing bottom padding, and setting the background-size property to cover. This is a technique known as “Uncle Dave’s Ol’ Padded Box”, and allows us to maintain an aspect ratio by percentage padding based on the width of the parent element.

For inline images, we now have an HTML specification that allows us to extend the img and source elements to provide a list of available image sources and their sizes. This allows browsers to use this information to pick the best image source. The image below details how this is implemented on our demo, in which we are defining additional image sources and their sizes with srcset and sizes attributes. This enables the browser to switch image resolution based on screen size and pixel density, thus providing the most appropriate image.

<header role="banner" class="header">
  <div class="header__img">
    <img  
      srcset="./death-star_sml%402x.jpg 400w,
      ./death-star_lrg.jpg 600w,
      ./death-star_sml%402x.jpg 800w,
      ./death-star_lrg%402x.jpg 1200w"
      sizes ="(min-width:1336px) 75vw, 50vw"
      alt="Death Star 02">
  </div>
</header>

You might notice that we aren’t including a src attribute on our inline image. This is because we must leverage a polyfill to enable support for srcset and sizes in browsers that do not yet support them. Browsers without support will prefetch the img’s src if specified, often causing wasteful overhead. To prevent this, it is recommended by the polyfill author to omit src and only use srcset.

Conclusion

Serving the best possible experience at any screen size is imperative. When it comes to optimizing our content for large-scale displays, we shouldn’t stop short of common desktop resolutions. With the proper planning, we can leverage the tools already available to us when building responsive websites to scale up and adapt our content for large-scale displays.

Further Reading/Tools


Optimizing for Large-Scale Displays originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/optimizing-large-scale-displays/feed/ 21 241350