Wednesday, April 16, 2014

Journey Into Mobile - Level 5

Notes from Code School's Journey Into Mobile - Level 5 (Responsive Media)

  • Responsive Images
  • Retina Images


Responsive Images


Up to this point the images in our layouts have been fixed width. But we want our images to be able to scale with the viewport, like the rest of our content. To do this there is a two-step process.

1. Scale out an image that is larger than we actually need, that way it can be scaled down as necessary.
2. Use a max-width property in CSS

/* base image */
img {
  max-width: 100%;
}

If we have a set width for our image, it tells the browser to fit that set width with a 100% of the image so that even if the image container is smaller than the total size of the image, we still get the full resolution image in that container. 

/* specific image */
about img {
  max-width: 29.6875%;
}



The containing element is going to scale, and as the result the image itself if going to scale as a result of the max-width property.

You can use this technique with any media type:

img, 
embed,
object,
video {
  max-width: 100%;
}

Note: 
- No IE6 Support
- Prior to Windows 7 there is poor max-width support
- Specifically Firefox 2 and IE7
- If you need to support older browsers, use AlphaImageLoader:  http://msdn.microsoft.com/en-us/library/

For more robust options for creating responsive media, try these JavaScript libraries.


Retina Images

With the ipad and newer iphones, retina images have become more of an issue. Retina images have 1.5 to 2 times the pixel density, so if you serve a normal image on a retina display it could look blurry or pixelated.

You could double the image size, but you're looking at larger images, larger downloads, and slower site speeds. Instead, use media queries to target those specific devices and optimize images for retina displays.

@media
  only screen and (-webkit-min-device-pixel-ratio: 1.5),
  only screen and (min-device-pixel-ratio: 1.5) {

    /* styles */
  }

In the above media query, we are targeting devices that have a pixel density of at least 1.5x.
Note, ipad and newer iphones have a pixel density of 2x, but some andriod devices have 1.5x, so we will target at least 1.5x to cover all cases.

Within the media query, you'll want to set your styles and images for retina display devices.

Example 1:
Let's say you have an image that is 200px by 200px.

You will want to scale the image up to 400px by 400px, and save it. 

Best practice naming convention is to use the same name as the original file, in this case 'logo', and then use the '@2x' to signify it's twice as big. So your new file will be logo@2x.png.

Example 2: 
On our example site, Nautilus from previous levels, we had a map it! button. The original size of the button was 12px by 16px. For retina images, first scale up the button to 24px by 32px (double the size).


/* Original CSS */
.logo {
  background-image: url(images/mapit.png) no-repeat;
}

/* Media Query */
@media
  only screen and (-webkit-min-device-pixel-ratio: 1.5),
  only screen and (min-device-pixel-ratio: 1.5) {
    .logo {
      background-image: url(images/mapit@2x.png);
      -webkit-background-size: 12px 16px;
      background-size: 12px 16px;
    }
  }

The background-size is equal to the original image, if we don't specify background-size, the browser will serve up the image at its original doubled size.

top: original button, bottom: button@2x

What about file size?

The previous examples used larger images, which looked good but if you're not using a retina screen they would still download and slow site speed unnecessarily.

What do you do?

There is a good solution created by Scott Jehl called Picture Fill. http://scottjehl.com/picturefill/. To use it you must include picturefill.js in the <head> of your document.

<picture alt="some alt text">  
  <!-- Smallest size first, no @media qualifier -->
  <source src="content-image.jpeg" />
  <!-- Large size- send to viewports 800px wide and up -->
  <source src="content-image-lrg.jpeg" media="(min-width: 800px)" />
</picture>

In our picture tag, we first specify our image for non-retina display devices. Next, we use a larger image for devices that have retina display and are at least 800px wide.

For users who have JavaScript disabled, or for browsers that don't support media queries, create a fallback:

<!--Fallback content for non-JS or non-media-query-supporting browsers -->
<noscript>
  <img src="content-image.jpeg" alt="some alt text" />
</noscript>
</picture>



 

Journey Into Mobile - Level 4

Notes from Code School's Journey Into Mobile - Level 4 (Responsive Adventures)

  • The Mobile First Approach
  • Responsive Applied
  • Advanced Media Queries

The mobile first approach:

prepares you for the explosive growth and new opportunities on the mobile internet, ... forces you to focus, ... enables you to innovate in ways you previously couldn't. -Luke Wroblewski (Mobile First, 5)
The mobile first approach forces you to focus on the most important things, like simplify the content, prioritize layout, and optimize user experience. In mobile, you don't have nearly as much screen real estate, the space you have is more valuable, forcing you to prioritize what is most important.

Is responsive design the same as adaptive?

  • all responsive are adaptive
  • not all adaptive designs are responsive
Responsive designs are basically fluid sites with a series of break points. Whereas adaptive design is selectively adapted for the context you are targeting.
Responsive designs provide continuity between contexts... Responsive designs are portable and accessible. -Ethan Marcotte


 Responsive Applied

In responsive design content determines the break points. In adaptive design, the height and width determine the break points, but in responsive design where the content breaks down is where the break points are.

Taking a look at our demo site from level 3, if we narrow our browser window, we'll see that at around 870px our header starts to get crowded. This will be our first breakpoint.


In this case, there is a new logo image and we will move all the location information below it.

/* <870px */
@media screen and (max-width: 870px) {
  
  /* Header */
  h1 {
    background: url(images/logo_l.png) no-repeat;
    height: 105px;
    margin: 0 auto;
    width: 400px;
  }
  .location {
    background-color: #26343e;
    float: none;
    min-height: 85px;
    margin: 0 auto;
    margin-top: 20px;
    padding: 10px;
    text-align: center;
  }


Now at 768px, our menu items start to get too narrow and the text is hard to read. Also note that 768px is the width of an ipad, so while it's a good idea to make break points based on content, also keep in mind the widths of common mobile devices. To adjust for our mobile layout, we will stack the menu blocks one above another.



/* <768px */
@media screen and (min-width: 768px) {
  /* -- section -- */
  .box {
    padding: 10px;
    margin: 20px auto;
    width: inherit;
  }
  .beverage {
    float: none;
  }
  .cuisine {
    float: none;
  }

Next, at about 510px, our contact information starts to break below the location information:


    BUT, because we already have a media query at 480px (adapted for the iphone standard screen in level 3), we can just change the 480px media query to 510px. We are able to do this because we are using a fluid layout that scales easily.

/* <480px */
  @media screen and (max-width: 480px) {
}

becomes:

/* <510px */
  @media screen and (max-width: 510px) {
}


Advanced Media Query Options

Here are some advanced media query options from Responsive Web Design by Ethan Marcotte.

For example, instead of defining a screen size, you could use portrait and landscape modes.

/* Portrait */
@media screen and (orientation: portrait) {
  
  /* portrait styles */
}

/* Landscape */
@media screen and (orientation: landscape) {

 /* landscape styles */
}


Tuesday, April 15, 2014

Journey Into Mobile - Level 3

Notes from Code School's Journey Into Mobile - Level 3 (Adaptive Adventures)


What is Adaptive Design?

Adaptive design is design for controlled adaptation. You know the device or design context that you need to design for, i.e. when you need to adapt the styles from one environment (like desktop) to another (like mobile). This does not mean you are designing for the universal web, but for a specific context. 

Designing to Meet a Specific Context
  • device
  • screen size
  • resolution

Four Design Keys

Keep these in mind before starting any design project.
  • Who is your user?
  • How will they use the site?
  • Context (i.e. what device?)
  • Content (how will it adapt?)
The next couple of levels in this course will use an example site for the "Nautilus Bar & Restaurant". Here is what the site looks like on desktop:
CSS adaptive design
example site as seen on desktop

And here is what we want it to look like on mobile:
CSS adaptive design
example site as seen on mobile


Elements of Adaptive Web Design

  • Adaptive Markup
  • Break Points
  • Media Queries

Break Points

Break points are where your design break down, typically the height and width of the viewports.
There are many mobile devices of varying sizes, but for this example we'll use the standard iphone dimensions to set our break points.

height: 480px
width: 320px
standard iphone dimensions CSS break points
standard iphone dimensions

Media Queries

As part of the CSS3 spec, the @media query was introduced. E.g.

@media screen and (max-width: 320px) {
  body {
    font-size: 100%;
  }
}

Media type is 'screen'
Query is 'max-width: 320px'
Beneath is all the styles contained for that query

What is this actually telling the browser to do?
It's saying, for any viewport that is less-than or equal to 320px in width, use these styles over the original styles.

You can also set a min-width if you want to set styles for really large screens.

@media screen and (min-width: 1024px) {
  body {
    font-size: 100%;
  }
}

Where do you put media queries?
You could use a separate stylesheet for each, but that would be cumbersome and increase the load time. It's best practice to put your media queries in a group at the bottom of your stylesheet. This way they are easier to maintain, easier to find, and doesn't increase the load time as much as an external stylesheet.

For our Nautilus Restaurant example, we could create two media queries, one for portrait and one for landscape.

@media screen and (max-width: 320px) {
}

@media screen and (max-width: 480px) {
}

But, if your site is based on a fluid layout, it can scale based on the viewport size, which means you only need to define the larger of the two. The site will scale down gracefully to 320px.

Here are our styles for the header area of the desktop site:
h1 {
  background: url(images/logo.png) no-repeat;
  height: 84px;
  text-indent: -9999px;
  width: 308px;
}

header {
  border-bottom: 15px solid #26343e;
  padding: 25px 0;
}

And now, to adapt this for mobile, we will remove the bottom border and padding. As well as swap out the logo for a smaller version.

@media screen and (max-width: 480px) {
  h1 {
    background: url(images/logo_s.png) no repeat;
    height: 80px;
    margin: 0 auto;
    text-indent: -9999em;
    width: 295px;
  }
  header {
    border-bottom: none;
    padding: 0;
  }
}

header adapted to mobile

Next, we want to move the location and contact information below the logo. In the desktop environment it was floated to the right of the logo. Here are the original desktop styles:

.logo {
  float: left;
}
.location {
  float: right;
}
.addy {
  float: left;
}
.mappy {
  float: right;
  text-align: center;
  width: 270px;
}

location and contact info. desktop version


To adapt to mobile, we will remove all the floats, add a background color and make the 'map it' button the width of the viewport:

@media screen and (max-width: 480px) {
  .logo {
    float: none;
    margin: 0 auto;
    text-align: center;
  }
  .location {
    background-color: #26343e;
    float: none;
    margin: 0 auto;
    text-align: center;
  }
  .addy {
    float: none;
  }
  .mappy {
    float: none;
  }
}

location and contact info. adapted for mobile

Now, for the desktop version, the menu blocks are floated to the right and left of each other. 
menu blocks .beverages and .cuisine floated left and right on desktop version

.box {
  min-height: 425px;
  width: 41.666667%;  /* 400px/960px */
}
.beverages {
  float: left;
}
.cuisine {
  float: right;
}

But this won't work in a mobile environment because the boxes and text would become too small to read. Instead, we will stack the boxes on top of each other. To do this, we'll allow the width to inherit the full width of the viewport size, then remove the floats.

@media screen and (max-width: 480px) {
  .box {
    margin: 20px auto;
    min-height: 0;
    width: inherit;
  }
  .beverages {
    float: none;
  }
  .cuisine {
    float: none;
  }
}

menu blocks with floats removed, adapted for mobile


Journey Into Mobile - Level 2

Notes from Code School's Journey Into Mobile - Level 2 (Fluid Layouts)

Fluid Layouts: Layouts that scale to the size of the viewport
Fixed Layouts: Layouts that are static

What makes a fluid site?

- Fluid Grid: The grid is a series of same-size columns spaced apart evenly across the page. This helps make the design more legible to the user and better organized for the designer.

CSS fluid layout grid
fluid grid

- Relative Values (percentages): When you resize the viewport, each element remains the same size relative to everything else.

CSS fixed layout vs fluid layout
left: static layout, right: fluid layout

Converting a Fixed Layout to a Fluid One

target ÷ context = result

The example site we will be working with:
- a main <div> called .site

- a sidebar <div> called .sidebar

- and a content <div> called .content
The Main Site Area

html:
<div class="site"></div>

css (static layout):
.site {
  margin: 40px auto;
  width: 940px;
}

The main .site area currently has a fixed width, there is nothing wrong with fixed width sites, but they don't scale with the viewport. Instead of 940px, we need to set this as a percentage. When talking about the main site container there is not a magic formula to determine the proper percentage, its really a matter of trial and error, because you want to make sure the design looks good in the browser.

css (fluid layout)
.site {
  margin: 40px auto;
  width: 90%;
}

At the smaller viewport size, this conversion does not make a difference, but as you scale it, things change. The site is no longer centered in the browser, everything is flush left. This is because the main site container is scaling at 90%, but the rest of the site is still static.
regular viewport view

expanded viewport view

Now to convert the other elements:

Sidebar

Our sidebar layout in html:
<section class="sidebar">
  <header></header>

 <nav>
    <ul class="menu>
    </ul>
  </nav>

  <footer></footer>
</section>

styles:
.sidebar {
  float: left;
  text-align: center;
  width: 305px;
}

To change our 305px width to a percentage, use the target ÷ context = result formula.

305px ÷ 940px = 0.32446809

305px = our .sidebar width
940px = the width of .sidebar's parent container (.site)

0.32446890*100 = 32.446890%
There is no need to round the percentages up or down as we want to be precise.

New fluid styles:
.sidebar {
  float: left;
  text-align: center;
  width: 32.446890%;  /* 305px/940px */
}

Now that our sidebar element has a relative size, but the content section does not, the sidebar creeps into the content section. Let's fix this.

.sidebar and .site fluid, .content fixed

html of content section:
<section class="content">
  <aside></aside>
  
  <p></p>

  <footer class="stapleton">
    <div class="bio">
    </div>
  </footer>
</section>

styles (fixed layout):
.content {
  background-color: #fff;
  box-shadow: 0 3px 4px rgba(0, 0, 0, 0.3);
  margin-left: 325px;
  padding: 20px;
  width: 590px;
}

In this case, we will need to change the margin, padding and width to a percentage value for relative sizing.

Width

target ÷ context = result
590px ÷ 940px = 0.62765957 or 62.765957%

590px = .content width
940px = width of parent container (.site)

Our styles so far:
.content {
  background-color: #fff;
  box-shadow: 0 3px 4px rgba(0, 0, 0, 0.3);
  margin-left: 325px;
  padding: 20px;
  width: 62.765957%;  /* 590px/940px */
}

Flexible Margins

When setting flexible margins on an element, your context is the width of the element's container. - Ethan Marcotte (Responsive Web Design, 35)
target ÷ context = result
325px ÷ 940px = .34574468 or 34.574468%

325px = width of margin-left
940px = width of parent container (.site)

Our styles so far:
.content {
  background-color: #fff;
  box-shadow: 0 3px 4px rgba(0, 0, 0, 0.3);
  margin-left: 34.574468%;  /* 325px/940px */
  padding: 20px;
  width: 62.765957%;  /* 590px/940px */
}


Flexible Padding

When setting flexible padding on an element, your context is the element itself. -Ethan Marcotte (Responsive Web Design, 35)
This makes sense when you think about the box model, because with margin you're dealing with the space outside an element and with the padding you're dealing with the space inside an element.

The box width will be the context for our flexible padding:
target ÷ context = result
20px ÷ 590px = .03389830 or 3.389830%

20px = width of margin-left
590px = width of parent container (.content)

Our new flexible styles:
.content {
  background-color: #fff;
  box-shadow: 0 3px 4px rgba(0, 0, 0, 0.3);
  margin-left: 34.574468%;  /* 325px/940px */
  padding: 3.389830%;  /* 20px/590px */
  width: 62.765957%;  /* 590px/940px */
}

Now the site scales based on the size of the viewport.
fluid layout expanded viewport


fluid layout contracted viewport



Journey Into Mobile - Level 1

Notes from Code School's Journey Into Mobile - Level 1 (Foundations for Mobile)


What is the mobile web?

There is no mobile web, in as much as there is no "desktop web." This is the only web:
The web is not limited to one particular device or environment.

The primary design principle underlying the web's usefulness and growth is universality. -Tim Berners-Lee
The web:
- Must work with any form of information
- Must be accessible from any device

mobile design. adaptive design, and responsive design all just mean web design.

This course covers:

  • Fluid Layouts
  • Adaptive Design
  • Responsive Design

Fluid Type


Example sentence:

<h1>It is quite a three pipe problem. <a href="#">Please get me a pipe.</a></h1>

h1 {
  font-size: 30px;
  font-weight: bold;
}

This would be fine, except we want our type to be relative in size, so that when our site scales the type will scale too. Instead of our font-size being a static 30px, we want to convert the pixels to ems.

pixels --> ems

The standard font-size for most browsers is 16px. To make sure our base font-size for our site is 16px for all browsers, we will set it as the standard in our html style.

html {
  font-size: 16px;
}

Next, because we will be converting all our pixel font-sizes from here on to ems, and that includes lots of dividing by 16 (not fun math), we'll change our base from 16px to 10px. Yay! 10 is so much easier to work with.  10/16 = .625 = 62.5%

body {
  color: #352a25;
  font-family: Georgia, serif;
  font-size: 62.5%;  /* 1em = 10px */
}


How to Convert Pixels to Ems

target ÷ context = result

target = font-size
context = font-size of containing element
result = value of ems

30px(value of h1) ÷ 10px(default browser font-size) = 3em

result:
h1 {
  font-size: 3em;  /* 30px/10px */
  font-weight: bold;
}

But, we also have an anchor tag inside our h1 that needs to be sized correctly.

h1 a {
  font-size: 14px;
  text-transform: uppercase;
  text-decoration: none;
  color: #6c564b;
}

target ÷ context = result

Bad example:
14px(a font-size) ÷ 10px(default font-size) = 1.4em

result of 'h1 a' with wrong context

Now the anchor text is too large. That is because we used the wrong context. Because the anchor text is within the h1 tags, the h1 is its parent text, and thus its correct context.


Good example:
14px(a font-size) ÷ 30px(font-size of h1) = 0.4666667em

result:
h1 a {
  font-size: 0.4666667em;
  text-transform: uppercase;
  text-decoration: none;
  color: #6c564b;
}

result of proper 'h1 a' pixel to em conversion

Note: It is perfectly okay that the number 0.4666667 is long and complicated; it is the exact pixel value that we want. There is no need to round up or down.


Monday, April 14, 2014

Front End Formations: Level 5

Notes from Code School's Front End Formation: Level 5

Fonts and Interactions

  • Font Face
  • Transforms
  • Transitions
  • Progressive Enhancement

Font Face

Using @font-face, we have the ability to use online fonts on our websites.

E.g.
@font-face {
  font-family: 'OpenSansRegular';
  src: url('opensansregular-webfont.eot');
  font-style: normal;
  font-weight: normal;
}

1. <font-family> We will specify the font-family, which is what we'll use to call the font.
2. <src> We'll add the location of the font files through the src property
3. <font-style> We will specify the font style to be normal.
4. <font-weight> We'll specify the font weight to be normal.

To use the @font-face property, specify the font-family to be the same name as what you assigned in the @font-face property above.
e.g.

h1 {
  font-family: 'OpenSansRegular';
}

With the @font-face fonts, just like any other font declaration, we'll want to add fallback fonts, incase that font isn't supported. E.g.

h1 {
  font-family: 'OpenSansRegular', Hevetica, Arial, sans-serif;
}

We can also use a varying weights of @font-face fonts:

@font-face {
  font-family: 'OpenSansBold';
  src: url('OpenSansBold-webfont.eot');
  font-style: normal;
  font-weight: normal;
}

h1 {
  font-family: 'OpenSansBold';
}

We can alter the @font-face call in order to use the font-weight and font-style properties as usual. For example, an alternative way to use the bold version of the font 'OpenSansRegular' do this:
1. Start by adding the regular version of the font-family.
2. Point the <src> to the bold version of the font
3. Change the font-weight to 'bold'

@font-face {
  font-family: 'OpenSansRegular';
  src: url('OpenSansBold-webfont.eot');
  font-style: normal;
  font-weight: bold;
}

And to call the bold version (assumes you've already declared somewhere that the base font for h1 should be 'OpenSansRegular'):

h1 {
  font-weight: bold;
}

Transforms

Using the transform property in CSS3 we can translate, rotate, scale, and skew elements in CSS.

Translate

Translate allows you to create a 2D translation using the transform property. E.g.

.element {
  transform: translate(20px, 30px);
}

- Translate the element 20px to the right (moves on the x-axis)
- Translate the element 30px down (moves on the y-axis)

transform: translate(<tx>, <ty>);

- <tx> is a <transition value> for the x-axis, which can be either a length or a percentage
- <ty> (optional) is a <transition value> for the y-axis, which can be either a length or a percentage. If not specified, the value is 0.

Translate can also be expressed like this and will produce the same result:

.element {
  transform: translateX(20px);
}

.element {
  transform: translateY(30px);
}

Rotate

With rotate, you can rotate and element clockwise around its origin by the specified angle. E.g.

.element {
  transform: rotate(45deg);
}

CSS3 transform: rotate
The element is rotated 45 degrees

Scale

With scale, you can do a 2D scale by a specified unitless number. E.g.

.element {
  transform: scale(1.2);
}

transform: scale(<sx>, <sy>)

The scale transform takes two arguments, a unitless number for the x-axis, and an optional unitless number for the y-axis. If <sy> is not specified, it will default to the value of <sx>. You can also scale and X and Y values individually. E.g.

.element {
  transform: scaleX(1.2);
}

.element {
  transform: scaleY(0.3);
}

Skew

With skew, an element is skewed around the x or y axis by the angle specified. In this case, x and y must be skewed individually. E.g.

.element {
  transform: skewX(-25deg);
}



CSS3 transform: skew
The element is skewed -25 degrees along the x-axis.
Skew-x and skew-y take angle arguments.

Example 1:

.element {
  transform: skewX(25deg);
}

Example 2:

.element {
  transform: skewY(-85deg);
}

Transition

CSS3 provides transitions, which allow you to transition between two states of a specified element.
For example, if you have an element with a black background, but when we hove over it, we want it to change to blue. We don't want a quick, jarring change but a gradual one.

.element {
  background-color: black;
  transition: background-color 0.2s ease-in-out;
}

.element:hover {
  background-color: blue;
}

The background-color transitions from black to blue over a period of .2 seconds.

Values of Transition Property

transition: <property> <duration> <timing function> <delay>

<property> The name of the CSS property you actually want to transition (optional)
<duration> The duration of the transition. The default value is 0s, or zero seconds.
<timing function> The timing of the transition itself (optional)
    Timing Function Keywords aka transition styles:
  • ease
  • ease-in
  • ease-in-out
  • linear
  • cubic bezier
  • step-start
  • step-end
  • steps()
<delay> The amount of time you want to wait, if at all, before the transition begins. (optional)

How to set transition values individually:
.element {
  transition-property: background-color;
  transition-duration: 0.2s;
  transition-timing-function: ease-n-out;
  transition-delay: 0.1s;
}

By using the 'all' keyword, we can transition multiple properties at once. In this case we'll transition both the background color and the text color on a button when someone hovers over it.

.element {
  background-color: black;
  color: white;
  transition: all 0.2s ease-n-out;
}

.element:hover {
  background-color: grey;
  color: black;
}

Progressive Enhancement

The term "progressive enhancement" refers to the use of the newer features that add to the experience in modern browsers that support those features, but doesn't detract from the experience in older browsers. An example of progressive enhancement:

.element {
  background: #ccc;
  border-radius: 10px;
  box-shadow: 0 1px 1px rgba(0, 0, 0.75);
}

If a browser supports these properties it would look like this:
CSS3 box-shadow property
.element using CSS3 as shown in browsers that support CSS3 
If the border-radius and box-shadow properties are not supported, we still get a useable design, which is what progressive enhancement is all about.

grey box
.element using CSS3 as shown in browsers that DO NOT support CSS3



Progressive enhancement is important to keep in mind because we want to make sure that we are creating experiences that degrade gracefully for browsers that don't support newer features.