G$earch

Redesigning A Responsive Youtube with HTML5/CSS3 [Tutorial]

Posted by Harshad

Redesigning A Responsive Youtube with HTML5/CSS3 [Tutorial]


Redesigning A Responsive Youtube with HTML5/CSS3 [Tutorial]

Posted: 18 Feb 2013 06:34 AM PST

If you have seen YouTube recently you may notice one glaring omission from their website layout. Their design lacks the ability to fold responsively as you resize the browser window. It’s strange how the layout does not even contract to a smaller width; YouTube is currently designed using a fixed-width webpage.

I want to bring in some modern web design techniques and give the YouTube homepage a nice redesign. In this tutorial I’ll explain how we can build a custom mobile-responsive YouTube clone layout from scratch.

Custom YouTube Responsive Layout Redesign in HTML5/CSS3

I’ll be using some newer HTML5 and CSS3 techniques which are supported in mostly all modern browsers.

If you want to see my code in action check out the live demo at the end of the article below.

Creating the Structure

To get us started we should create a single index.html page with the typical HTML5 doctype. Since this is a mobile responsive layout we need to include a few specific meta tags as well.

In this project I’ll be separating our JavaScript and CSS code into different files, and you can see what that looks like in my codes below:

<!doctype html>  <html lang="en-US">  <head>    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">    <title>Demo sliding menu test</title>    <meta name="author" content="Jake Rocheleau">    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">    <link rel="shortcut icon" href="favicon.ico">    <link rel="icon" href="favicon.ico">    <link rel="stylesheet" type="text/css" href="css/styles.css">    <link rel="stylesheet" type="text/css" href="css/responsive.css">    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.0/jquery-ui.min.js"></script>    <script type="text/javascript" src="js/retina.js"></script>    <script type="text/javascript" src="js/scripts.js"></script>  <!--[if lt IE 9]>    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>  <![endif]-->  </head>  

So along with the viewport meta tag, I’m including a series of external documents. The stylesheets styles.css and responsive.css contain the design rules for our typical layout and over responsive media queries.

Additionally I am including two JS libraries from Google’s CDN hosting: jQuery and jQuery UI. Both will come in handy as the layout shrinks and we use a sliding animation to display the navigation menu.

This animation is tied to the scripts.js file where I’ll be keeping all our custom jQuery codes. Additionally I have another 3rd party script named retina.js which is by far the easiest way to work around retina display images.

If you visit the retina.js website you’ll find a download link for their minified library. Simply include this into your document and the script will auto-scan your images for @2x variations (when on retina devices).

More Responsive Tendencies

For this particular tutorial I have gone with a more atypical approach to website design techniques.

When our layout is displaying in full at 950px, you’ll see two sidebars along with the center video content. However when you get down to the smallest frame, around 320px, you’ll only see the center column and a top toolbar area.

toogle youtube toolbar

This toolbar will have a menu toggle button which you can tap, to slide back and forth. None of the menu links work in my demo because we don’t have any pages with content right now. But you may update these anchor links with new HREF values to get them working on a real website.

Let me copy over just the top header & navigation code from our document body.

<body>    <div id="w" class="clearfix">      <header id="fulltop">        <span id="logomini"><a href="index.html"><img src="design-responsive-youtube/logo-mini.png" alt="YouTube - Broadcast Yourself"></a></span>                <span id="userlogin">          <img src="design-responsive-youtube/avatar-sm.png" alt="default user pic" class="defaultphoto">           <a href="javascript:void(0)">Log In</a>        </span>                      <div id="searchbox">          <form id="searchform" name="searchform" action="#" method="get">            <input type="text" name="s" id="s" class="searchbar" placeholder="" tabindex="1">            <input type="submit" name="sbtn" id="sbtn" value="" tabindex="2">          </form>                    <ul id="topsidelinks">            <li><a href="javascript:void(0)">Browse</a></li>            <li><a href="javascript:void(0)">Featured</a></li>            <li><a href="javascript:void(0)">Upload</a></li>          </ul>        </div>      </header>            <nav>        <ul id="sidenav">          <li class="heading">User Account</li>          <li><a href="#login" class="signin"><i></i>Sign In</a></li>          <li><a href="#register" class="register"><i></i>Register</a></li>          <li class="heading">Video Categories</li>          <li><a href="#popular" class="popular"><i></i>Popular</a></li>          <li><a href="#recent" class="recent"><i></i>Recently Uploaded</a></li>          <li><a href="#comedy" class="comedy"><i></i>Comedy</a></li>          <li><a href="#entertainment" class="entertainment"><i></i>Entertainment</a></li>          <li><a href="#film" class="film"><i></i>Film & Animation</a></li>          <li><a href="#gaming" class="gaming"><i></i>Gaming</a></li>          <li><a href="#people" class="people"><i></i>People & Blogs</a></li>        </ul>      </nav><!-- end navigation menu -->  

So all the content wrapped inside our body is inside another wrapper div with the ID #w. This is how we can fix the page content towards the center and limit the maximum width around 950px. But inside the header tag you’ll notice that many of the features are not displaying on smaller screens. We are using @media queries inside CSS to limit when the search bar and top links will be displayed.

Additionally the sliding nav menu will always appear hidden on smaller screens. Once your browser width passes about 600px then the side navigation is displayed naturally as a left column in the body container. This is the reason why these links should always work properly regardless of the responsive situation.

Common Webpage Styles

I want to jump into discussing a few important blocks of CSS code. To begin we need to understand how the core body is centered and why the two-column layout drops down as you resize the window.

Now these rules are separated into two documents as you saw earlier, so the easiest way to understand this is by downloading my source code directly.

/* page structure */  #w {     -webkit-box-sizing: border-box;    -moz-box-sizing: border-box;    box-sizing: border-box;    max-width: 950px;     min-width: 300px;     height: 100%;    margin: 0 auto;     overflow: hidden;    position: relative;     display: block;     -webkit-box-shadow: 0px 0px 9px rgba(0,0,0,0.65);    -moz-box-shadow: 0px 0px 9px rgba(0,0,0,0.65);    box-shadow: 0px 0px 9px rgba(0,0,0,0.65);   }    #pageWrapper { display: block; width: 100%; }  #page {     display: block;     -webkit-box-sizing: border-box;    -moz-box-sizing: border-box;    box-sizing: border-box;    width: 100%;    min-height: 650px;    position: relative;     top: 0;     background: #fff;     z-index: 999;      padding: 0;    -webkit-box-shadow: -4px 0px 9px -4px rgba(0,0,0,0.65);    -moz-box-shadow: -4px 0px 9px -4px rgba(0,0,0,0.65);    box-shadow: -4px 0px 9px -4px rgba(0,0,0,0.65);  }  #content { display: block; padding: 10px 14px; }    #fulltop { display: none; visibility: hidden; }  #secondary { display: none; visibility: hidden; }  

Initially we are hiding the top header section and the secondary sidebar from view. All the HTML is still in our document, but none of this will be displayed until the width has surpassed 600px.

The secondary sidebar is actually hidden until 800px because there simply isn’t enough room in the layout.

/* header */  #topbar {     display: block;     -webkit-box-sizing: border-box;    -moz-box-sizing: border-box;    box-sizing: border-box;    height: 60px;    padding: 0px 6px;    padding-top: 10px;    text-align: center;    border-bottom: 1px solid #677282;    background-color: #6279a3;    background-image: -webkit-gradient(linear, left top, left bottom, from(#8da1c2), to(#6279a3));    background-image: -webkit-linear-gradient(top, #8da1c2, #6279a3);    background-image: -moz-linear-gradient(top, #8da1c2, #6279a3);    background-image: -ms-linear-gradient(top, #8da1c2, #6279a3);    background-image: -o-linear-gradient(top, #8da1c2, #6279a3);    background-image: linear-gradient(top, #8da1c2, #6279a3);    -webkit-box-shadow: 0px 1px 0px rgba(255,255,255,0.5) inset;    -moz-box-shadow: 0px 1px 0px rgba(255,255,255,0.5) inset;    box-shadow: 0px 1px 0px rgba(255,255,255,0.5) inset;  }    #logo { position: relative; top: -5px; }    #slidelink {     display: block;     font-size: 0.01em;     line-height: 1.8em;     width: 50px;     height: 35px;     position: relative;    top: 2px;    left: 10px;    background: url('../design-responsive-youtube/menu.png') top left no-repeat;     float: left;     z-index: 999;  }  

All the header codes are pertaining to the responsive mobile top navigation toolbar with the blue gradient background. We are creating all of this through CSS3 except for the sliding button, which uses a background image.

For retina devices I have included an @2x copy of the menu icon, along with all of the sidebar icons which are from the Glyphish icon pack.

When using CSS background images we cannot rely on the retina.js script. That will only parse images which are loaded into the page using an HTML5 <img> tag. Instead we need to setup new responsive rules inside the stylesheet named responsive.css.

I’ve copied over my block of code below:

/* retina display devices only */  @media only screen and (-webkit-min-device-pixel-ratio: 2),	only screen and (min--moz-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {      #slidelink { background: url('../design-responsive-youtube/menu@2x.png') top left no-repeat; background-size: 50px 35px; }      #sbtn { background: url('../design-responsive-youtube/search@2x.png'); background-size: 24px 24px; }      #sidenav li a.signin i { background-image: url('../design-responsive-youtube/user@2x.png'); background-size: 24px 21px; }    #sidenav li a.register i { background-image: url('../design-responsive-youtube/gear@2x.png'); background-size: 26px 26px; }   #sidenav li a.popular i { background-image: url('../design-responsive-youtube/star@2x.png'); background-size: 26px 26px; }   #sidenav li a.recent i { background-image: url('../design-responsive-youtube/coffee@2x.png'); background-size: 24px 26px; }   #sidenav li a.comedy i { background-image: url('../design-responsive-youtube/mic@2x.png'); background-size: 12px 24px; }   #sidenav li a.entertainment i { background-image: url('../design-responsive-youtube/tv@2x.png'); background-size: 24px 24px; }   #sidenav li a.film i { background-image: url('../design-responsive-youtube/film@2x.png'); background-size: 20px 25px; }   #sidenav li a.gaming i { background-image: url('../design-responsive-youtube/joystick@2x.png'); background-size: 22px 20px; }   #sidenav li a.people i { background-image: url('../design-responsive-youtube/pencil@2x.png'); background-size: 23px 23px; }  }  

The background-size property along with an @2x copy is what performs all the magic here. We need to squeeze an image twice as large into the typical sizing constraints.

This will look a whole lot better on retina devices where your natural images would look blurry and upscaled in comparison.

Important Responsive CSS Blocks

Much of the responsive codes should be straightforward for web developers who are familiar with using the syntax. But I’ll copy over some other sections from my responsive.css document and explain the layout effects.

/* first responsive changes between mobile and desktop layout */  @media only screen and (min-width: 600px) {    #sidenav { z-index: 999; width: 250px; }    #page { z-index: 1; padding-left: 250px; }        #topbar { display: none; visibility: hidden; }        #fulltop { display: block; visibility: visible; height: 45px; padding: 8px 14px; border-bottom: 1px solid #d8d8d8; }    #logomini { display: block; float: left; margin-right: 40px; }        #searchform { display: block; float: left; }    #s {       width: 310px;       border: 1px solid #ccc;      padding: 8px 7px;      color: #999;      background: #f7f7f7;      font-size: 1.45em;      text-shadow: 0px 1px 0px #fff;      outline: none;      -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.5) inset;      -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.5) inset;      box-shadow: 0 1px 3px rgba(0,0,0,0.5) inset;      -webkit-transition: all .4s linear;      -webkit-border-radius: 3px;      -moz-border-radius: 3px;      border-radius: 3px;      -moz-transition: all .4s linear;      transition: all .4s linear;    }    #s:focus { color: #666; background: #fff; border-color: #b8b8b8; }        #sbtn { cursor: pointer; width: 24px; height: 24px; border: 0; background: none; background-image: url('../design-responsive-youtube/search.png'); position: relative; top: -4px; left: -35px; opacity: 0.7; }    #sbtn:hover { cursor: pointer; }  

Right when your browser viewport hits 600px the whole layout should change immediately. We are no longer using the toggle menu and now wish to display it openly as a left sidebar.

We also need to change the visibility of the older responsive toolbar and display the #fulltop header div instead.

Additionally you may get a kick out of the CSS3 transitions and box shadow effects I’m using on the search field. These effects should perform exactly the same in most browsers including Firefox, Opera, Safari, and even IE9-10.

It’s a nice additional touch giving this YouTube layout some modern aesthetics.

/* as the layout widens display a secondary sidebar and top user links */  @media only screen and (min-width: 810px) {    #userlogin { display: block; float: right; margin-right: 35px; margin-top: 4px; height: 30px; line-height: 30px; }    #userlogin .defaultphoto { display: block; float: left; border: 1px solid #ddd; margin-right: 3px; }    #userlogin a { line-height: 35px; }        #secondary { display: block; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; visibility: visible; width: 240px; padding: 10px 14px; z-index: 999; position: absolute; right: 0; }    #secondary h2 { font-size: 1.3em; font-weight: bold; font-style: italic; line-height: 1.45em; color: #66666d; margin-bottom: 7px; }    .videoblock { display: block; visibility: visible; width: 100%; }    .videoblock a .vidimg { display: block; visibility: visible; }        .videoblock a { display: block; width: 100%; margin-bottom: 7px; padding: 5px 0px; text-decoration: none; border-bottom: 1px solid #fff; }    .videoblock a:hover { border-bottom: 1px solid #ebebeb; background: #f6f6f6; }        .videoblock a .vidimg img { display: inline-block; visibility: visible; border: 1px solid #cdcdcd; }      .videoblock a h4 { font-weight: bold; font-size: 1.3em; color: #333; margin-bottom: 1px; }    .videoblock a:hover h4 { color: #5a7aaa; }      .videoblock a .uploader { display: block; font-size: 1.1em; color: #666669; }    .videoblock a .views { display: block; font-size: 1.1em; color: #666669; }    .videoblock a:hover .uploader, .videoblock a:hover .views { color: #525252; }        #page { padding-right: 240px; }  }  

Now this last bit of responsive code takes effect once the browser window is slightly larger than 800px. I have included a secondary sidebar area which supports “featured videos”, among other similar blocks of code.

I haven’t included much dummy content since the focus of this tutorial is on working responsive codes. But this new secondary sidebar is perfect for extra page content which just can’t be fitted into the smaller layouts.

You may also notice these styles add a small set of links into the full top header display. When a user is logged in this is the perfect opportunity to present more impactful profile-related links. These could pertain to user account settings, favorite videos, channel subscriptions, or recent uploads.

Developing JS with jQuery

There are just two core functions I’ve built into the scripts.js asset file: whenever the user taps on our mobile responsive menu, it opens/closes the panel accordingly and if the user opens the menu and then resizes their browser, all the content is pushed over to the right.

In this scenario we need to handle if the menu is open and the browser is resized large enough to hide the menu, then reposition the main content area. I’ll break down each of these code snippets into two segments.

  var page = $("#page");      // show and hide navigation menu    $("a#slidelink").on("click", function(e){      e.preventDefault();      var position = page.position();      var winwidth = $(window).width();            if(position.left == 0) {        $(page).animate(          { left: '+=240px' },          250,          'easeOutBack',          function() {            // callback        });      } else {        $(page).animate(          { left: '-=240px' },          400,          'easeOutCirc',          function() {            // callback	        });         }    });  

The #slidelink refers to our menu button which is displayed in the top mobile toolbar area. Whenever the user clicks on this link then we find the current position of our page content. If the left position returns a value of 0 then we know the menu is still closed, and we need to open it.

If the value is anything except 0 then we can assume the menu is already open and we’re looking to close it.

Both of these effects use the jquery .animate() method which is why we’re including a copy of the jQuery UI library as well. None of the callback functions are active, but it’s easy to add in your own codes.

Inside you can place anything you want to execute immediately after these animations are complete.

  // check content position on browser resize    var resizeTimer;    $(window).resize(function() {      clearTimeout(resizeTimer);      resizeTimer = setTimeout(resetPagePosition, 150);    });              function resetPagePosition() {      var position = page.position();      var winwidth = $(window).width();            if(winwidth >= 600 && position.left != 0) {        // if the window is above 600px and the menu is open we need to reset back into position        $(page).animate({left: "0px"}, 110);      }    };  

The second function will handle repositioning of our page content whenever the menu is open & the browser window gets resized wide enough to hide it. This event handler which is attached to the window object listens for jQuery’s .resize() method. I have set a timer for 150 milliseconds so the function isn’t firing immediately after the resize.

All the interactive code can be found inside my custom function resetPagePosition(). Inside the function I have created another position variable to determine where our page is located.

If the left value is not 0, then we know the menu was open and we have now passed the 600px threshold. It’s a simpler solution for cleaning up this annoying bug, which you will likely run into if you’re using any type of sliding mobile menu techniques.

Secondary Sidebar design - YouTube Responsive tutorial CSS3 media queries

Demo & Download

Feel free to play around with the live demo version and see if you can get a working solution on your desktop, laptop, tablet, or smartphone.

Final Thoughts

I hope this tutorial has demonstrated a few key traits for building responsive websites. The developers at YouTube could be drawing in more attention to the site if it was directly supported on mobile devices. YouTube does have their own mobile subdomain but it’s just not the same experience.

If you have any questions or comments about the tutorial, you can share with us in the post discussion area below.

A Look into: HTML5 Datalist

Posted: 18 Feb 2013 06:23 AM PST

You probably have experienced this kind of response somewhere on the Web: when you are typing in an input form, a list of suggestions appears at the bottom of the input.

Over the years, we rely on JavaScript to create such a function. Today, we are able to do that with the new HTML5 <datalist> element. This HTML5 new element allows us to store a list of options that will be shown as the users type in the input.

HTML5 List Attribute

The <datalist> can be linked to <input> element using a new HTML5 attribute, list. We can use list in a few input types like text and search. But, according to Mozilla Developer Network, the list attribute is not applicable within the following input types: hidden, checkbox, radio, file and button.

In the following example, we add a list of cities with <datalist> and assign it with ID attribute, like so.

  <datalist id="city">  	<option value="Adelaide">  	<option value="Bandung">  	<option value="Bangkok">  	<option value="Beijing">  	<option value="Hanoi">  	<option value="Ho Chi Minh City">  	<option value="Hong Kong">  	<option value="Jakarta">  	<option value="Kuala Lumpur">  	<option value="Osaka">  	<option value="Seoul">  	<option value="Shanghai">  	<option value="Singapore">  	<option value="Surabaya">  	<option value="Sydney">  	<option value="Tokyo">  </datalist>  

To hook the <datalist> to an <input> element, simply add list attribute and refer to the id attribute, like so.

  <input class="destination-list" type="text" placeholder="From:" list="city">  <input class="destination-list" type="text" placeholder="To:" list="city">  

Browser Behavior

Each browsers that support <datalist> element, Chrome, Opera and Firefox act slightly different.

In Chrome, it will show the options that start with the value we type in. In the example below, Chrome shows values that start with “s”.

On the other hand, as we click on the input twice, it will show all the options available, as shown below.

In Opera, as we are focusing on the input form, it immediately shows all the options and then sort them based on the initial letters we type in.

Firefox will not show anything upon focusing in the input. It will show the options that contain the values as we type them in. For example, this screenshot below shows Firefox displaying the options that contain the letter “u”.

Safari at the moment, does not support the <datalist> element and Internet Explorer is reported to support this element as of version 10.

Using HTML5 Datalist with Polyfills

There are a few polyfills to replicate similar functionality in unsupported browsers. In this post, we will implement the datalist polyfills from Michael Taylor. To use it, we will need jQuery and Modernizr for browser feature detection.

As for the Modernizr, we have to make a few customizations. In the Modernizr download page, check the following options.

  • Input Attributes under the HTML5 section
  • Modernizr.addTest under the Extensibility section
  • Modernizr.load under the Extra section
  • elem-datalist under the Non-core detects

Now, let’s open the HTML document where we add the <datalist> element and add the Modernizr library we have just downloaded in the <head> section.

  <script src="js/modernizr.js" type="text/javascript"></script>  

After adding Modernizr, we can test the browser whether it supports datalist element with the script below.

  if (!Modernizr.datalistelem) {  	alert('This browser does not support HTML5 datalist element, so we will load the polyfills');  }  

The script above will show an alert saying “This browser does not support HTML5 datalist element, so we will load the polyfills” when datalist element is not supported. In Safari, it looks like this.

Next, create a new JavaScript file named load.datalist.js and add this line below in it. This will target and run the script to the input that has the list attribute.

  $('input[list]').datalist();  

Lastly, we will load the jQuery, jquery.datalist.js and load.datalist.js using Modernizr.load, as follows.

  Modernizr.load({  	test: Modernizr.datalistelem,  	nope: ['js/jquery.js', 'js/jquery.datalist.js', 'js/load.datalist.js']  });  

Thus, they will be loaded only when the browser does not support <datalist> element.

That’s it, now you can view the demo in action or download the source file from the links below.

Further Resources

Below are a few resources to dig into this subject further.

0 comments:

Post a Comment