Skip to content

Instantly share code, notes, and snippets.

@kkas
Last active May 28, 2021 18:33
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save kkas/6e8981baeb0971828e38 to your computer and use it in GitHub Desktop.
Save kkas/6e8981baeb0971828e38 to your computer and use it in GitHub Desktop.
Responsive Design Notes

Responsive Design Notes

DevTool

  • Device Pixel Ratio

Viewport

  • The viewport defines the area of the screen that the browser can render content to.

    • If not set properly, your content might flow off the page or you have to pinch and zoom to see anything.
      • Because it is up to the browser to determine the viewport size.
  • Not all displays have the same pixel density.

    • The Chromebook pixel display, for example, has the width of 2,560 pixels by 1,700 pixels, but the viewport size is only 1,280 pixels (1/2, not 2,560 pixels!)
    • A pixel is not always created the same. A pixel is not always a pixel.
  • Hardware Pixels:

    • Actual, pysical pixels on the device.
    • for example, 1,920 x 1,080 pixels in the tech specs for the screen of a mobile device.
  • Device Independent Pixels (dips)

    • If a device pixel ratio (DPR) is set to 2, 1 dip takes 2 x 2 hardware pixels.
    • For example, you have hardware device screen pixels of 1,024 x 640 pixels with DPR=2, then the width in dips will be 512. (1024 / 2 => 512)

Basics

  • Set the viewport ALWAYS.
  • It is safe to add a below snipet. "width=device-width" instructs the page to match the screen's width in device independent pixels. "initial-scale=1" sets a one to one relationship between device independent pixels and CSS pixels. (without it, some browsers keep the width constant when rorating to landscape mode. Also, they scale the content rather than allowing it to reflow.)
<meta name="viewport" content="width=device-width,initial-scale=1">
  • It is recommended adding a catch all in your main CSS for image, embed, object, and video elements, that sets the below, just to be safe.
img, embed,
object, video {
  max-width: 100%;
}
  • Smaller devices have 320 pixels width. Any width below the size of 320 is fine (it does not overflow).
  • Make a button at least 48 x 48 pixels. For example,
button {
  min-width: 48px; min-height: 48px;
}

Start Small

  • Designing a responsive site, uses the same concepts and processes that you go through for a non responsive site. Except, instead of drawing a single wide desigh, there are few more to accommodate different screen sizes.

  • Design for smaller device first. Then, think if there's really need a design for bigger screen.

  • By starting designing from smaller devices, you need to prioritize content, meaning what is the most important thing that the users want to do or that they are going to see on screen. So that the most important thing are always there no matter what device the uses are using.

    • The design for one hardware store prioritizes information about the nearest store, its address, hours, and phone number and puts those right at the top so you can find them easily.
  • Advantages of designing from small to large

    • Like designing, code from small to large. This way, the style and layout will work for any devices, even on legacy browsers that don't support media queries.

    • Performance also. By designing for the smallest viewport first, it forces to think you about performance from the beginning.

  • CSS Properties

Responsive CSS

  • Design Patterns
    • To apply different styles for different devices, there are some ways to accomplish this but the easiest is using media queries.
    • Example of when the screen(viewport width) is over 500px.
<link rel="stylesheet" href="yes.css">
<link rel="stylesheet" media="screen and (min-width:500px)" href="over500.css>
  • 2 other ways to apply media attribute.
    • @import or
    • @media
      • Ignore @import for performance reason
@media screen and (min-max:200px) {
  { body ... }
}
@media screen and (min-width:500px) {
  { body ... }
}
  • You need to choose between Linked CSS or @media

    • Linked CSS
      • Many small css files
      • Many HTTP Requests
    • @media
      • Fewer HTTP requests
      • Files tend to be a little bit bigger
  • min-width, max-width, min-device-width, max-device-width

    • Using xxx-device-width is strongly discouraged
      • xxx-device-width is the size of the device screen. Therefore, it can prevent content from adapting on desktops or other desktops that allow the windows to be resized because the query is based on the actual device size, not the browser window.
      • legacy android browsers may return the wrong value

break points

  • Can change page layouts by using min-width and max-width
  • Where should I put the breakpoints?
    • Scott Yale said, "We shouldn't choose break points at all. Instead, we should find them, using our contents as a guide."

Flexbox

  • Flexbox is one of the most powerful tools that you can use for layout.
    • ability to fill the space available.
    • If an element has an extra room around it, then it'll expand to fit, or if it's getting crowded elements will shrink so that they take up as little space as possible.
  • It has been changed alot. But it's hit candidate recommendation and it's supported by most browsers.
  • Make sure to include all the vendor prefixed versions, so that you don't leave users using older broser out in the cold.

Properties

  • Let's say you have three divs, contained within a container div.
    • In normal block layout, each div is positioned, one underneath the other one.
    • Adding the attribute, 'display: flex;' to the container div, the divs are shown in a row. That's because the default flex direction is row.
      • By default, flex items fit on a single line, no matter what the width size is. Instead, the browser will shrink or expand the elements where they need to be.
    • Adding the attribute, 'flex-wrap: wrap;' to the container element, it changes the default to accept the elements to wrap to the next line, instead of changing their sizes.
      • The browser resizes the elements only it really needs to be.
    • 'order' attribute. Just add an order attribute to each element. This makes the layout really responsive. In some layouts, content appers in one order, but in another layout, it appears in a whole different order.
@media screen and (min-width: 700px) {
 .dark_blue { order: 4; }
 .light_blue { order: 5; }
 .green { order: 2; }
 .orange { order: 3; }
 .red { order: 1; }
}
  • Use relative width size like the below to make sure the elements are placed at the right place.
xxxx {
 .header {order: 0; width: 100%; }
 .dark_blue { order: 1; width: 50%; }
 .light_blue { order: 2; width: 50%; }
 .footer { order: 3; width: 100%; }
 .orange { order: 4; width: 20%; }
 .red { order: 5; width: 60%; }
 .yellow { order: 6; width: 20%; }

Responsive Design Pattens

  • Even though the design patterns have been quickly evolving, there are a handful of well established patterns that work well, across pretty much any devices.
  • Most patterns used by responsive web pages can be categorized into one of four patterns:
    • Mostly fluid pattern:
      • very similar to Column drop. but it tends to be a bit more grid-like.
      • Just like column drop at its narrowest viewport, the layout is stacked but as the layout gets wider, the grid pattern starts to appear.
      • Eventually, once the layout hits its widest viewport, margins are added on the left and right, instead of expanding things out.
<div class="container">
  <div class="box dark_blue"></div>
  <div class="box light_blue"></div>
  <div class="box green"></div>
  <div class="box red"></div>
  <div class="box orange"></div>
</div>
.container {
  display: flex;
  flex-wrap: wrap;
}

/* Apply when the narrowest viewport size. */
.box {
  width: 100%;
}

@media screen and (min-width: 450px) {
  .light_blue, green {
    width: 50%;
  }
}

@media screen and (min-width: 550px) {
  .dark_blue, .light_blue {
    width: 50%;
  }
  .green, .red, .orange {
    width: 33.333333%;
  }
}

/* Apply at the maximum viewport size. The width is fixed.
   and it starts adding the margins. */
@media screen and (min-width: 700px) {
  .container {
    width: 700px;
    margin-left: auto;
    margin-right: auto;
  }
}
  • Column drop pattern:
    • easiest.
    • At its narrowest viewport, each element simply stacks vertically, one on top of the other.
    • As things get wider, the elements expand, until the first break point is hit.
    • At the first break point, instead of having all the elements stacked, two elements are now side by side. And the third element is underneath.
    • The elements keep expanding as the viewport gets wider until the next break point is hit.
    • Then, things reflow to a three-column layout.
    • Generally, once the viewport hits a maximum width, the columns hit a maximum size, and instead of getting wider, margins are added to the left and right.
<div class="container">
  <div class="box dark_blue"></div>
  <div class="box light_blue"></div>
  <div class="box green"></div>
</div>
.container {
  display: flex;
  flex-wrap: wrap;
}

.box {
  width: 100%;
}

@media screen and (min-width: 450px) {
  .dark_blue {
    width: 25%;
  }
  .light_blue {
    width: 75%;
  }
}

@media screen and (min-width: 550px) {
  .dark_blue, .green {
    width: 25%;
  }
  .light_blue {
    width: 50%;
  }
}
  • layout shifter pattern:
    • Probably the most responsive pattern.
    • The key to this layout is the way that content moves about, instead of reflowing and dropping below other columns.
    • We use the order CSS attributes, too.
    • The default CSS order attribute is 1. So, if "-1" is specified, then the element will be set at the first. If "1" is set, which is greater than 0, then the element will be set at the last.
<div class="container">
  <div class="box dark_blue"></div>
  <div class="container" id="container2">
    <div class="box light_blue"></div>
    <div class="box green"></div>
  </div>
  <div class="box red"></div>
</div>
.container {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
}

.box {
  width: 100%;
}

@media screen and (min-width: 500px) {
  .dark_blue {
    width: 50%;
  }
  #container2 {
    width: 50%;
  }
}

@media screen and (min-width: 600px) {
  .dark_blue {
    width: 25%;
    order: 1;
  }
  
  #container2 {
    width: 50%;
  }
  
  .red {
    width: 25%;
    order: -1;
  }
}
  • off cnavas pattern:
    • Instead of stacking content vertically, it places less frequently used content, for example, navigation or app menus, off screen, only showing them if the screen is large enough.
    • On smaller screens, the off canvas content is typically shown when the user tap on the hamberger icon.
<nav id="drawer" class="dark_blue">
</nav>

<main class="light_blue">
</main>
html, body, main {
  height: 100%;
  width: 100%;
}
  
nav {
  width: 300px; /* fixed size */
  height: 100%;
  position: absolute; /* This is important too. */
  transform: translate(-300px, 0);  /* moves the menu off the screen */
  transition: transform 0.3s ease;  /* the menu moves nicely */
}

/* This will be applied when a hamberger button is tapped. */
nav.open {
  transform: translate(0, 0);
}

@media screen and (min-width: 600px) {
  nav {
    position: relative; /* Set it back to relative */
    transform: translate(0, 0);
  }
  body {
    display: flex;
    flex-flow: row nowrap;
  }
  main {
    width: auto;
    flex-grow: 1; /* Allows the element to grow and take up the full remaining width fo the viewport. */
  }
  
  ... also add some javascript to toggle the nav and nav.open.
  • In some cases, a page may use a combination of patterns. For example, "column drop" and "off canvas".

Responsive Tables

  • There's a good chance that the table with more than a few columns is going to overflow the viewport on smaller screens, forcing horizontal scrolling.
  • To fix this:
    • "Hidden Columns"
      • Essentially hides columns based on their importance as teh viewports size gets smaller.
      • The biggest problem of Hidden Columns is that you are hiding content from the user. So, use it with caution.
      • Use abbreviated data instead of hiding it completely.
.longName {
  display: none;
}

.inning {
  display: none;
}
  • "No more tables"
    • With this tequnique, below a certain viewport width, the table is collapsed and resembles a log list, as opposed to a table data.
    • Nice thing about this tequnique is that all the data are visible, no matter what the viewport size is.
@media screen and (max-width: 500px) {
        /* make the table no more table. */
        table, thead, tbody, th, td, tr {
          display: block;
        }
        /* Get rid of the table header. Set aside instead of 'display: none' for people using screen readers. Becase the browser wont tell them the column headers, it would cause accessibility problems. */
        thead tr {
          position: absolute;
          top: -9999px;
          left: -9999px;
        }
        /* Since the table cells are displayed as full width block elements, you need to add some left paddin and also set the position omn these elements to relative. */
        td {
          position: relative;
          padding-left: 50%;
        }
        /* To add the row label. */
        td:before {
          position: absolute;
          left: 6px;
          content: attr(data-th);
        }
      }
  • "Contained Scrolling"
    • One of the easiest thing you can do, to contain the table in the view port is:
      • to wrap it in a
        .
      • set the 'width' of the div to '100%' and 'overflow-x' to auto.
    • instead of breaking out of the viewport, the table will instead take up the same with, but will scroll within the viewport.
div.contained_table {
  width: 100%;
  overflow-x: auto;
}

Fonts

  • ideal measure for the length of a line of text
    • if it is printed, if it's projected, or on a computer screen
      • 45 - 90 cpl (characters per line)
    • for web
        • 65 cpl
  • this can be a guidline for choosing breankpoints.
  • Make sure the fonts are big enough for every device.
    • set the base font to at least below, and increase them for text heavy sites, depending on the situation.
font-size: 16px;
line-height: 1.2em;

Minor Breakpoints

  • In addition to major breakpoints, where layout changes significantly, it's also helpful to add minor breakpoints to make some small changes.
  • For example, between major breakpoints, it may be helpful to adjust margins and paddings on an element, or to increase the font size to make things a little bit easier to read and feel more natural in the layout.
@kantologist
Copy link

kantologist commented Jul 13, 2018

Nice article. I also did a brief demo of common responsive design patterns here. https://kantologist.github.io/Common-Responsive-Pattern-Demo/ and the repo is here https://github.com/kantologist/Common-Responsive-Pattern-Demo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment