This site is dedicated to all things I see and that I think are interesting to publish almost always are other very smart people.

CSS

Poly Fluid Sizing

Jake Wilson digs in, and while he finds that calc() isn’t quite up for the job (e.g. font-size: calc(3vw * 3vw); /* This doesn't work in CSS */), he does land on a technique he’s calling Poly Fluid Sizing, which takes a map of breakpoints and font sizes and linear interpolates them just about as good (*it depends*).

Direct Link to ArticlePermalink

Poly Fluid Sizing is a post from CSS-Tricks


Sass for Web Designers review

I had this little book by Dan Cederholmlaying around for quite some time. I’ve bought it as a reference for when I would try to get my head around Sass. Now I finally managed to write the review. Let’s get right into it.
Sass for Web Designers book

Table of contents

I’ve hesitated to start with Sass. This book was written to help with that: an informative, concise introduction to all things Sass. Honestly, I think Sass needs a getting started guide for a designer anyway.

Foreword

The foreword in Dan’s book is written by a person that knows a thing or two about CSS, and runs a hugely valuable web site called CSS Tricks. If you’ve ever googled something CSS related, Chris Coyier will most likely be high up there in the search results. Chris says “By the time you finish this book and give Sass a real try on your first project, you’ll be a master of 95% of the important, truly value-adding parts of Sass”

  • Chapter 1: Why Sass
  • Chapter 2: Sass Workflow
  • Chapter 3: Using Sass
  • Chapter 4: Sass and Media Queries

Chapter 1: Why Sass

In this first part Dan tells the story of how he was reluctant to start with Sass as he writes his stylesheets by hand. It took him a while to come around. In this chapter Dan explains what Sass is and he also goes into the misconceptions about Sass.

Chapter 2: Sass Workflow

In chapter two it is time to get your hands dirty and start using it. When you are on a Mac it’s relatively easy to get started but there still is a need to fire up Terminal. Dan also shows all the necessary commands. I’m not scared of using Terminal, but if I can avoid messing around with my system I opt for that and use a tool instead. My tool of choice is CodeKit. Luckily Dan also sums up all others as well. There are plenty of options at your disposal. The last part in this chapter deals with choosing your output.

Chapter 3: Using Sass

Chapter three is where the real adventure starts. You’ll use a fictional project (Sasquatch Records) as an example to get your head around the most valuable and easiest to add core Sass features such as nesting rules, referencing parent selectors, variables, mixins, extends and content blocks. Here Dan takes the time to explain each part in an understandable manner, step by step. If you’re done with this section you’ve got the basics of Sass covered.

Chapter 4 Sass and Media Queries

The final chapter takes things a serious step further. This section is where I needed to re-read things a few times to get my head around it. Dan explains some useful techniques for simplifying the use of media queries. You’ll learn how to nest media queries, using variables to define breakpoints and how to‘Retinize’ your HiDPI background images. The book ends with a valuable and useful resource section with links to the most useful Sass tutorials, mixin libraries, apps and frameworks.

Conclusion

Just like Dan I was reluctant to start with Sass as I mentioned earlier. When I first dangled my feet into this world of preprocessors I’ve used Compass, but now I’ve switched to pure Sass as it kinda feels like the world has moved on and Compass isn’t getting any updates anymore. This book was a great companion and reference to see if I did things correctly. If you’ve been writing , CSS the traditional way like I’ve done for many years, Sass feels like a radical change. When something radical takes place you need help and Dan’s approach is wonderful just like in his other books, Bulletproof CSS, Handcrafted CSS, andCSS3 for Web Designers. Dan takes the time to explain his examples thoroughly so you fully understand what’s going on. For me such a thorough instruction was needed to grasp how things work. I would recommend it if you are still doubting about Sass. Dan’s guidance is a reassuring way to get started with the important concepts. There’s much more to learn, but when you’re done with this book you’re off to a great start. You can buy the book over at A Book Apart.


Scroll Drawing

We’ve taken an in-depth look at how SVG line drawing works before. It’s a clever trick where you use dashed lines for the stroke, but the gap in the dash is so long it covers the entire path. Then you can move it such that it covers the entire path again, which makes it appear as if it’s drawing itself.

Using a bit of JavaScript, we can get a little fancier, drawing the shape to completion as page is scrolled to the bottom.

Demo

See the Pen Scroll Drawing by Chris Coyier (@chriscoyier) on CodePen.

Step 1: Get a <path>

It has to be a <path>. Any other kind of SVG element won’t work (e.g. <rect>). You can force elements to be paths though. I have a Lodge video on this. You may need to resort to trickery like adding an additional vector point along an already straight edge.

In my demo here, I just copy-and-pasted the shape right out of Illustrator.

Give the path an ID if it doesn’t have one:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100.6 107.6" id="star-svg">
  <path id="star-path" fill="none" stroke="black" stroke-width="2"  d=" ... " />
</svg>

Step 2: Find length of that path

// Get a reference to the <path>
var path = document.querySelector('#star-path');

// Get length of path... ~577px in this demo
var pathLength = path.getTotalLength();

Step 3: Hide shape by offsetting dash

// Make very long dashes (the length of the path itself)
path.style.strokeDasharray = pathLength + ' ' + pathLength;

// Offset the dashes so the it appears hidden entirely
path.style.strokeDashoffset = pathLength;

Step 4: When page scrolls, offset dash same amount as % scrolled

// When the page scrolls...
window.addEventListener("scroll", function(e) {
 
  // What % down is it? 
  var scrollPercentage = (document.documentElement.scrollTop + document.body.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
    
  // Length to offset the dashes
  var drawLength = pathLength * scrollPercentage;
  
  // Draw in reverse
  path.style.strokeDashoffset = pathLength - drawLength;
  
});

Step 5: If scrolled to bottom, remove dashing

If you don’t do this, the shape doesn’t look quite as neatly/sharply finished as if you didn’t applying any dashing at all.

I’m not sure why. I don’t think you can fiddle with the numbers to fix it. But it’s easy enough to remove.

  // ... at bottom of scrolling function

  // When complete, remove the dash array, otherwise shape isn't quite sharp
  if (scrollPercentage >= 0.99) {
    path.style.strokeDasharray = "none";
  } else {
    path.style.strokeDasharray = pathLength + ' ' + pathLength;
  }

The 0.99 is to account for fuzzy math. Sometimes you don’t get a perfect 1.0 from the division.

See a full page demo.

Scroll Drawing is a post from CSS-Tricks


Spriting with

Sprites aren’t limited to background-image, as with the object-fit and object-positionproperties we can nudge an inline image around its content-box to act just like a sprite. For example, let’s say we want the image below to be added to our HTML page like a regular ol’ image:

Sprite
<img src='sprite.png' alt='Icons'> 

Then we’ll crop the image so that only the first icon is visible on screen:

img {
  object-fit: none;
  object-position: 0 0;
  width: 100px;
  height: 100px;
}
Sprite image cropped to reveal the world icon

Here, the content-box of the <img> should be 100px wide and 100px tall, but because the image extends beyond those boundaries, it’s automatically cropped for us with object-fit: none. We might then want to use a class to nudge the image and reveal another part of it altogether:

.book {
  object-position: 0 -234px;
}
Sprite cropped to reveal the book icon

These sprites can be in any regular image format but it’s also possible to use the same technique with SVG. Here’s an example that currently works in the latest stable version of Chrome:

See the Pen Sprites with object-position by Robin Rendle (@robinrendle) on CodePen.

Image Slider

Using a dab of JavaScript, we can actually use this same concept to create an image slider out of a single <img> tag. When the image is clicked, just change some classes which change the object-position.

See the Pen SVG sprite with object-position by Robin Rendle (@robinrendle) on CodePen.

Support

Keep this in mind for the future, since unfortunately the browser support for object-fitisn’t particularly great at the moment. The current desktop versions of Safari and Firefox don’t support it and neither does iOS. So make sure to double check the almanac entry forobject-fit before using this trick anytime soon.

Spriting with <img> is a post from CSS-Tricks


Simple CSS-Only Row and Column Highlighting

Highlighting rows of a table is pretty darn easy in CSS. tr:hover { background: yellow; } does well there. But highlighting columns has always been a little trickier, because there is no single HTML element that is parent to table cells in a column. A dash of JavaScript can handle it easily, but Andrew Howe recently emailed me to share a little trick he found on StackOverflow, posted by Matt Walton.

It was a few years old, so I thought I’d just clean it up and post it here.

The trick is using huge pseudo elements on the <td>s, hidden by the table overflow

You don’t really know how big the table is from CSS, so just make the pseudo elements super tall with a negative top value of half of that.

table {
  overflow: hidden;
}

tr:hover {
  background-color: #ffa;
}

td:hover::after,
th:hover::after {
  content: "";
  position: absolute;
  background-color: #ffa;
  left: 0;
  top: -5000px;
  height: 10000px;
  width: 100%;
  z-index: -1;
}

The negative z-index keeps it below the content. Negative z-index is a fun trick, but beware this table then can’t be nested within other elements with backgrounds, otherwise the highlight will go below them.

You can see that in action here:

See the Pen Row and Column Highlighting with CSS Only by Chris Coyier (@chriscoyier) onCodePen.

Making it work with touch

Hover pseudo classes only kinda work on touch devices. First, the element needs to be focusable, which table cells are not by default. You could certainly add a click event handler to the table cells and just do everything in JavaScript, but here’s a method to keep most of the work in CSS:

// Whatever kind of mobile test you wanna do.
if (screen.width < 500) {
  
  // :hover will trigger also once the cells are focusable
  // you can use this class to separate things
  $("body").addClass("nohover");

  // Make all the cells focusable
  $("td, th")
    .attr("tabindex", "1")
    // When they are tapped, focus them
    .on("touchstart", function() {
      $(this).focus();
    });
  
}

Then in the CSS you add :focus styles as well.

td:focus::after,
th:focus::after { 
  content: '';  
  background-color: lightblue;
  position: absolute;  
  left: 0;
  height: 10000px;
  top: -5000px;
  width: 100%;
  z-index: -1;
}

td:focus::before {
  background-color: lightblue;
  content: '';  
  height: 100%;
  top: 0;
  left: -5000px;
  position: absolute;  
  width: 10000px;
  z-index: -1;
}

In my final demo, I got a little fancier with the CSS selectors ensuring that empty table cells didn’t trigger anything, table headers in the <thead> only selected columns, and table headers in the <tbody> only selected rows.

You can see that in the final demo. And here’s touch working:

Simple CSS-Only Row and Column Highlighting is a post from CSS-Tricks


How to Roll Your Own Simple WordPress Podcast Plugin

The following is a guest post by Geoff Graham. Geoff told me: “I love WordPress plugins but sometimes feel we rely on them without really understanding what they do.” Ain’t that true? Here, he walks us through how you might build this functionality yourself into WordPress. This might be just the ticket for those of you who resolved to start a podcast in 2015!

Let’s say you plan to get into podcasting. You have the recording equipment, an interesting topic, and a good voice that other people want to hear. You seem well on your way to filling earbuds everywhere.

Then there’s the issue of hosting your podcast. iTunes requires an RSS feed so it can distribute your episodes to subscribers when they’re available, but how do you do that? The good news is that there are plenty of ways to host a podcast. For example, you could use a hosting service that provides you storage and distribution in one tidy place, usually for a fee. If you use WordPress and have looked into podcasting, you may have seen all the powerful podcasting plugins that are available there as well.

We’re going to skip over those options in this post and see how we can host our own podcast using nothing more than a WordPress site and two additional files. Specifically, we’re going to:

  • Set up a new plugin
  • Register a custom RSS feed
  • Make a custom post type for our podcast
  • Assign custom fields to our custom post type
  • Create the template for our RSS feed

The goal is not to overthink this too much. If you already have a WordPress site and all you need is a feed to submit to iTunes, then that’s exactly what we’re going to do. Let’s rock ‘n’ roll.

Setting Up the Plugin

Creating a plugin is a nice alternative to writing code in your theme’s `functions.php` file. In addition to keeping your theme’s functions clean and clutter-free, it keeps the podcast feed functionality in your `/wp-content/plugins/` directory which stays with you even if you change themes.

Create the Plugin Directory

First things first. Let’s create a new folder called `my-awesome-podcast` in our `/wp-content/plugins/` directory.

Create the Plugin

Now let’s make a new PHP file in the folder we just created and call it `my-awesome-podcast.php`. This will be the primary file that registers our plugin and where we write the functionality for our podcast.

With that file in place, we will add the following code comments that tell WordPress the name, description and version of the plugin. There are other bits of information we can add, but this will do.

/**
Plugin Name: My Awesome Podcast
Description: A really simple RSS feed and custom post type for a podcast
Version: 1.0
**/

// This is where we will start writing our plugin

Register the RSS Feed

Next up, we need to register a new RSS feed. Thankfully, the WordPress API has a handyadd_feed() function that we can hook into to make this relatively easy.

add_action('init', 'podcast_rss');
function podcast_rss(){
  add_feed('my-awesome-podcast', 'my_podcast_rss');
}

What’s happening here is we’ve defined a new function called podcast_rss() and are extending the WordPress add_feed() function to create a new RSS feed called “my_podcast_rss” that will live at `/feed/my-awesome-podcast` on our site.

Note: You can change “my-awesome-podcast” here to anything you want. This the URL slug of your feed, so it could be the title of your podcast or whatever else you fancy.

Register a Podcast Custom Post Type

Once we have our feed established, we’ll need to set up a new post type that we can use to publish the posts for our episodes. So instead of a “Post” or “Page” that are default to WordPress, we’ll create a brand new one called “Podcast”. The WordPress Codex does a good job of explaining how to create custom post types, so there’s no need to rehash that here. There are even a handful of plugins that will do this, if that’s how you prefer to roll. In any case, let’s assume we’re doing it without the help of a plugin and make the Podcast custom post type here in our file.

function custom_post_type() {

  $labels = array(
    'name'                => _x( 'Podcasts', 'Podcast General Name', 'text_domain' ),
    'singular_name'       => _x( 'Podcast', 'Course Singular Name', 'text_domain' ),
    'menu_name'           => __( 'Podcasts', 'text_domain' ),
    'parent_item_colon'   => __( 'Parent Podcast:', 'text_domain' ),
    'all_items'           => __( 'All Podcasts', 'text_domain' ),
    'view_item'           => __( 'View Podcast', 'text_domain' ),
    'add_new_item'        => __( 'Add New Podcast', 'text_domain' ),
    'add_new'             => __( 'Add New', 'text_domain' ),
    'edit_item'           => __( 'Edit Podcast', 'text_domain' ),
    'update_item'         => __( 'Update Podcast', 'text_domain' ),
    'search_items'        => __( 'Search Podcasts', 'text_domain' ),
    'not_found'           => __( 'Not found', 'text_domain' ),
    'not_found_in_trash'  => __( 'Not found in Trash', 'text_domain' ),
  );
  $args = array(
    'label'               => __( 'podcasts', 'text_domain' ),
    'description'         => __( 'Podcast Description', 'text_domain' ),
    'labels'              => $labels,
    'supports'            => array( 'title', 'editor', 'thumbnail' ),
    'taxonomies'          => array( 'category', 'post_tag' ),
    'hierarchical'        => false,
    'public'              => true,
    'show_ui'             => true,
    'show_in_menu'        => true,
    'show_in_nav_menus'   => true,
    'show_in_admin_bar'   => true,
    'menu_position'       => 5,
    'menu_icon'           => 'dashicons-format-audio',
    'can_export'          => true,
    'has_archive'         => true,
    'exclude_from_search' => false,
    'publicly_queryable'  => true,
    'capability_type'     => 'page'
  );
  register_post_type( 'podcasts', $args );
}

add_action( 'init', 'custom_post_type', 0 );

This is a lot of code, but it’s just configuration to register a new post type called Podcasts. It defines the various labels for it in the WordPress dashboard, and tells WordPress how to handle it. Again, the WordPress Codex explains these things much more exhaustively, if you’re interested.

At this point in time, we can head into the Plugins section of our WordPress admin and seeMy Awesome Podcast listed as an available plugin. Go ahead and activate it.

Create Custom Fields for Podcast Posts

WordPress posts do a lot for us right out of the box, but sometimes we need additional fields that allow us to publish specific content. In this case, iTunes has a very specific format for what kind of information needs to be available in our RSS feed.

There is a way to add custom fields to our custom post type with extra development, but I actually prefer using the Advanced Custom Fields plugin for this sort of thing. It allows us to have a nice clean custom UI for each field we add, rather than the generic key/value pair UI you get with default custom fields.

Using Advanced Custom Fields, let’s set up a new field group called Podcasts, assign them to the Podcast post type and create the following fields:

  • podcast_file: Use the “File” field type so we can upload our podcast file directly to the post. Set the field to Return Value to “File ID” because this will help us auto-detect the file size later.
  • podcast_duration: This is a simple text field that we’ll use to publish the length of our episode in HH:MM:SS format.

Note: While I used the “File” field type in this example, you could theoretically use a text field if you plan on hosting your podcast files somewhere other than your server (say Amazon S3 or something like that), and paste the URL directly in there. However, we won’t be able to auto-detect the file size this way, though we could use another text field for that purpose.

Create the RSS Template

We’ve done a lot so far. The last thing to do is create the template that will be used to display the data for our podcast posts.

Apple has outlined the specs for an acceptable podcast RSS feed and it’s very specific. Using that outline as a guide, let’s create one more file in our plugin folder and call it `podcast-rss-template.php`. The name says it all, right?

The nice thing is that our RSS template is technically no different from any other WordPress template. We will query our posts, create a loop, and plug our data in where it needs to go.

/** 
Template Name: Podcast RSS
**/

// Query the Podcast Custom Post Type and fetch the latest 100 posts
$args = array( 'post_type' => 'podcasts', 'posts_per_page' => 100 );
$loop = new WP_Query( $args );

// Output the XML header
header('Content-Type: '.feed_content_type('rss-http').'; charset='.get_option('blog_charset'), true);
echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>';
?>

<?php // Start the iTunes RSS Feed: https://www.apple.com/itunes/podcasts/specs.html ?>
<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
  
  <?php 
    // The information for the podcast channel 
    // Mostly using get_bloginfo() here, but these can be custom tailored, as needed
  ?>
  <channel>
    <title><?php echo get_bloginfo('name'); ?></title>
    <link><?php echo get_bloginfo('url'); ?></link>
    <language><?php echo get_bloginfo ( 'language' ); ?></language>
    <copyright><?php echo date('Y'); ?> <?php echo get_bloginfo('name'); ?></copyright>
    
    <itunes:author><?php echo get_bloginfo('name'); ?></itunes:author>
    <itunes:summary><?php echo get_bloginfo('description'); ?></itunes:summary>
    <description><?php echo get_bloginfo('url'); ?></description>
    
    <itunes:owner>
      <itunes:name><?php echo get_bloginfo('name'); ?></itunes:name>
      <itunes:email><?php echo get_bloginfo('admin_email'); ?></itunes:email>
    </itunes:owner>
    
    <?php // Change to your own image. Must be at least 1400 x 1400: https://www.apple.com/itunes/podcasts/creatorfaq.html
    <itunes:image href="http://your-site.com/path/to/podcast/image.png" />
    
    <itunes:category text="Technology">
      <itunes:category text="Tech News"/>
    </itunes:category>
    
    <?php // Start the loop for Podcast posts
    while ( $loop->have_posts() ) : $loop->the_post(); ?>
    <item>
      <title><?php the_title_rss(); ?></title>
      <itunes:author><?php echo get_bloginfo('name'); ?></itunes:author>
      <itunes:summary><?php the_excerpt_rss(); ?></itunes:summary>
      <?php // Retrieve just the URL of the Featured Image: http://codex.wordpress.org/Function_Reference/wp_get_attachment_image_src
      if (has_post_thumbnail( $post->ID ) ): ?>
        <?php $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'full' ); ?>
        <itunes:image href="<?php echo $image[0]; ?>" />
      <?php endif; ?>
      
      <?php // Get the file field URL and filesize
        $attachment_id = get_field('podcast_file');
        $fileurl = wp_get_attachment_url( $attachment_id );
        $filesize = filesize( get_attached_file( $attachment_id ) );
      ?>
      
      <enclosure url="<?php echo $fileurl; ?>" length="<?php echo $filesize; ?>" type="audio/mpeg" />
      <guid><?php echo $fileurl; ?></guid>
      <guid><?php the_field('podcast_file'); ?></guid>
      <pubDate><?php the_time( 'D, d M Y G:i:s T') ?></pubDate>
      <itunes:duration><?php the_field('podcast_duration'); ?></itunes:duration>
    </item>
    <?php endwhile; ?>
  
  </channel>

</rss>

Note: the code above assumes you’re uploading the MP3 file to your own site/server. When that’s the case, it can get the file size in bytes, which iTunes requires as part of the RSS feed, which is super handy. However, if you’re hosting the MP3 file elsewhere (can be smart, most web hosts aren’t built for serving large assets), this won’t work. Instead, add an additional field with ACF for the byte size and output it where we’re outputting$filesize above.

Now let’s call this RSS template in our `my-awesome.podcast.php` file by adding the following:

function my_podcast_rss(){
  require_once( dirname( __FILE__ ) . '/podcast-rss-template.php' );
}

Putting it All Together

Let’s recap how everything fits together.

The Files

In short, we now have a new folder in our plugin directory called `my-awesome-podcast`.

WordPress Root Directory
└── wp-content
    └── plugins
        └── my-awesome-podcast
            ├── my-awesome-podcast.php
            └── podcast-rss-template.php
  • my-awesome.podcast.php: This registers our plugin, creates a custom RSS feed, defines a new custom post type and calls our RSS template.
  • podcast-rss-template.php: This contains the template for our RSS feed, providing the information from our Podcasts posts in a format that iTunes can read and use to deliver our content to subscribers.

Publishing a Podcast

Go ahead and publish a new Podcast post. The option will be in your WordPress menu under Podcasts.

  • Give the podcast a title
  • Upload the podcast episode file
  • Specify the episode length (in HH:MM:SS format)
  • (if not hosting locally) Specify the episode file size (in bytes)
  • Provide a summary of the episode in the content area

Awesome, we just published your first podcast episode!

Submit the Podcast to iTunes

Finally, go visit the URL of the feed at: `[your-site]/feed/[slug]`, where `[slug]` is what we defined in the add_feed() function back in the second step. It wouldn’t hurt to validate the feed just to make sure it’s healthy and happy. This is the URL you will submit to iTunes, which you can do from the iTunes app under iTunes Store > Podcasts > Quick Links > Submit a Podcast.

If you’re getting a Page Not Found (404), try flushing your permalinks. This can be done by heading to Settings > Permalinks from your WordPress dashboard and doing nothing more than clicking the Save Settings button. Strange, but true.

Go Forth and Podcast

There you go! A simple, but effective way to host your podcast using resources you probably already have lying around. Sure, there may be more powerful or even more elegant solutions, but this gives us exactly what we need with nothing more and nothing less.

How to Roll Your Own Simple WordPress Podcast Plugin is a post from CSS-Tricks


Stairway Navigation (A jQuery Plugin?) by Chris Coyier

On a whim the other day I thought I’d build out an idea for navigation I had. It’s nothing but a visual effect in which the hovered (or active) navigation item becomes the tallest “stair” and other items before and after it step down. It’s simple, but it’s not something you see very often. Probably for one major reason: you can’t select “previous” elements in CSS.

 

stairwaynav View Demo 

You can select “next” elements in CSS. You’d use the general sibling combinator  to get all the next elements or theadjacent sibling combinator  to get the very next one (which you could chain). Neither of those allow you to get the previous elements which, as you can see by the image above, is needed to do this effect justice.

In pseudo code, we’re trying to do this:

/* Not Real Code */

a:hover { /* top stair stuff */ }

a:hover-1,
a:hover+1 { /* second stair stuff *}

a:hover-2,
a:hover-2 { /* third stair stuff *}

Rather than get too tricky for our own good with CSS, let’s rely on a technology that can select previous elements: jQuery. jQuery has a .prev()  function (and a few other related functions) that we can use to get what we need. Our psuedo code would become more like this real code:

$("nav a").hover(function() {
  $(this)
   .addClass("stair-1")
   .prev()
     .addClass("stair-2")
     .prev()
       .addClass("stair-3")
       .end()
     .end()
   .next()
     .addClass("stair-2")
     .next()
       .addClass("stair-3");  
});

Presumably we’d clear all classes on all nav elements on a mouseleave event as well. That means to be most efficient we’d already have a pointer to all those elements.

var navEls = $("nav a");

navEls
  .on("mouseenter", function() {
     // add classes as above
  })
  .on("mouseleave", function() {
     navsEls.removeClass("stair-1 stair-2 stair-3);
  })

So now that we have a set, we might as well get a bit more efficient. Using .next() and .prev() means a lot of jQuery going back out to the DOM to figure out what to select (I think, correct me if I’m wrong there). Rather than do that, we can just select based on the set we already have selected based on it’s position within that set. The .index() function helps us figure that out and .eq() let’s us grab the element based on its index.

navEls
  .mouseenter(function() {

    $(this).addClass("stair-1");

    var index = $(this).index();
    
    allLinks.eq(index+1).addClass("stair-2");
    allLinks.eq(index-1).addClass("stair-2");

    allLinks.eq(index+2).addClass("stair-3");
    allLinks.eq(index-2).addClass("stair-3");

  })

That’ll do the trick.

CSS does the design work

Notice that all the jQuery is doing is adding and removing classes. That’s how UI and JavaScript should hang out the majority of the time. JavaScript is in charge of knowing about and changing states – CSS does the work of making the page look different.

The entire “stairway” visual effect comes in now, when we apply styles based on those classes.

.stair-1 {
  transform:
    scale(1.10)
    translateX(24px)
  box-shadow: 0 0 10px rgba(black, 0.75);
  z-index: 3;
}
.stair-2 {
  transform:
    scale(1.07)
    translateX(12px)
  box-shadow: 0 0 10px rgba(black, 0.5);
  z-index: 2;
}
.stair-3 {
  transform:
    scale(1.04)
    translateX(4px)
  z-index: 1;
}

The “top” stair (stair-1) enlarges, moves to the right, and has a deep shadow. Each of the subsequents stairs does a bit less of all those things. You could also change colors here or do anything else that would make sense to your own application.

A jQuery Plugin?

I put those words in the title of this post because I think this is interesting territory.

Does this kind of thing “deserve” to be pluginized? For one thing – this is heavily dependent on CSS. Calling it a “Stairway Navigation” plugin isn’t descriptive of what the actual jQuery code is doing. It also doesn’t make use of any of jQuery’s built-in features that are built for this, like it’s ability to animate things – we instead leave that to CSS.

Anyway – we are going to pluginize it because it makes things more interesting.

Plugin Options

We’ll make it the simplest set of options possible: how many stairs do you want stepping down? You’ll call it on a navigation element that contains only anchor links:

$(".main-nav").stairwayNav({
  stairs: 2
});

Then in the plugin, we make sure we have access to a “stairs” variable that is either the passed in value or some default.

$.fn.stairwayNav = function(options) {
  
  var defaults = {
     stairs: 3
  };
  this.options = $.extend({}, defaults, options);
  var stairs = this.options.stairs;

I love that pattern. It means we don’t have to do any fancy crap checking if the object contains certain keys and ensuring they aren’t blank and blah blah. If you pass in a value for “stairs”, that’s what ends up in the options object. If you don’t, it gets a default value. Cool.

Looping

To honor that option, we now just run a little for loop as many times as there are stairs. We adjust the index value the more iterations it runs, just never selecting negative values.

navEls
  .mouseenter(function() {
    $(this).addClass("stair-1");
    var index = $(this).index(), i, bef, aft;
    for(i = 1; i < stairs; i++) {
      
      bef = index - i;
      aft = index + i;
     
      allLinks.eq(aft).addClass("stair-" + (i+1));
      if (bef > 0) {
        allLinks.eq(bef).addClass("stair-" + (i+1));
      }
    }   
  })

Stairway Navigation Demo

Here is the demo on CodePen .

 

Stairway Navigation (A jQuery Plugin?)  is a post from CSS-Tricks

 

Enhanced by Zemanta

About normalize.css

…things by Nicolas Gallagher

Normalize.css is a small CSS file that provides better cross-browser consistency in the default styling of HTML elements. It’s a modern, HTML5-ready, alternative to the traditional CSS reset.

Normalize.css is currently used in some form by Twitter Bootstrap,HTML5 BoilerplateGOV.UKRdioCSS Tricks, and many other frameworks, toolkits, and sites.

Overview

Normalize.css is an alternative to CSS resets. The project is the product of 100′s of hours of extensive research by @necolas and @jon_neal on the differences between default browser styles.

The aims of normalize.css are as follows:

  • Preserve useful browser defaults rather than erasing them.
  • Normalize styles for a wide range of HTML elements.
  • Correct bugs and common browser inconsistencies.
  • Improve usability with subtle improvements.
  • Explain the code using comments and detailed documentation.

It supports a wide range of browsers (including mobile browsers) and includes CSS that normalizes HTML5 elements, typography, lists, embedded content, forms, and tables.

Despite the project being based on the principle of normalization, it uses pragmatic defaults where they are preferable.

Normalize vs Reset

It’s worth understanding in greater detail how normalize.css differs from traditional CSS resets.

Normalize.css preserves useful defaults

Resets impose a homogenous visual style by flattening the default styles for almost all elements. In contrast, normalize.css retains many useful default browser styles. This means that you don’t have to redeclare styles for all the common typographic elements.

When an element has different default styles in different browsers, normalize.css aims to make those styles consistent and in line with modern standards when possible.

Normalize.css corrects common bugs

It fixes common desktop and mobile browser bugs that are out of scope for resets. This includes display settings for HTML5 elements, correctingfont-size for preformatted text, SVG overflow in IE9, and many form-related bugs across browsers and operating systems.

For example, this is how normalize.css makes the new HTML5 searchinput type cross-browser consistent and stylable:

/*
 * 1. Addresses appearance set to searchfield in S5, Chrome
 * 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof)
 */

input[type="search"] {
    -webkit-appearance: textfield; /* 1 */
    -moz-box-sizing: content-box;
    -webkit-box-sizing: content-box; /* 2 */
    box-sizing: content-box;
}

/*
 * Removes inner padding and search cancel button in S5, Chrome on OS X
 */

input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button {
    -webkit-appearance: none;
}

Resets often fail to bring browsers to a level starting point with regards to how an element is rendered. This is particularly true of forms – an area where normalize.css can provide some significant assistance.

Normalize.css doesn’t clutter your debugging tools

A common irritation when using resets is the large inheritance chain that is displayed in browser CSS debugging tools.

A common sight in browser debugging tools when using a CSS reset

This is not such an issue with normalize.css because of the targeted styles and the conservative use of multiple selectors in rulesets.

Normalize.css is modular

The project is broken down into relatively independent sections, making it easy for you to see exactly which elements need specific styles. Furthermore, it gives you the potential to remove sections (e.g., the form normalizations) if you know they will never be needed by your website.

Normalize.css has extensive documentation

The normalize.css code is based on detailed cross-browser research and methodical testing. The file is heavily documented inline and further expanded upon in the GitHub Wiki. This means that you can find out what each line of code is doing, why it was included, what the differences are between browsers, and more easily run your own tests.

The project aims to help educate people on how browsers render elements by default, and make it easier for them to be involved in submitting improvements.

How to use normalize.css

First, download normalize.css from GitHub. There are then 2 main ways to make use of it.

Approach 1: use normalize.css as a starting point for your own project’s base CSS, customising the values to match the design’s requirements.

Approach 2: include normalize.css untouched and build upon it, overriding the defaults later in your CSS if necessary.

Closing comments

Normalize.css is significantly different in scope and execution to CSS resets. It’s worth trying it out to see if it fits with your development approach and preferences.

The project is developed in the open on GitHub. Anyone can report issues and submit patches. The full history of the project is available for anyone to see, and the context and reasoning for all changes can be found in the commit messages and the issue threads.

Related reading

Detailed information on default UA styles: WHATWG suggestions for rendering HTML documentsInternet Explorer User Agent Style Sheets andCSS2.1 User Agent Style Sheet Defaults.

Translations

Enhanced by Zemanta

Another CSS image replacement technique

…things by Nicolas Gallagher

A new image replacement technique was recently added to the HTML5 Boilerplate project. This post explains how it works and how it compares to alternative image replacement techniques.

Here’s the CSS behind the recent update to the image replacement helper class in HTML5 Boilerplate. It has also made its way into the Compassframework.

.ir {
    font: 0/0 a;
    text-shadow: none;
    color: transparent;
}

What does each declaration do?

  • font:0/0 a – a shorthand property that zeros out the font size and line-height. The a value acts as a very short font-family (an idea taken from theBEM implementation of this method). The CSS validator complains that using 0/0 in the shorthand font property is not valid, but every browser accepts it and this appears to be an error in the validator. Usingfont:0px/0 a passes validation but it displayed as font:0/0 a in the code that the validator flags as valid.
  • text-shadow:none – makes sure that any inherited text shadow is removed for the text. This prevents the chance of any text shadow colors showing over the background.
  • color:transparent – needed for browsers than don’t completely crush the text to the point of being invisible. Safari 4 (extremely rare) is an example of such a browser. There may also be mobile browsers than require this declaration. IE6/7/8 don’t recognise this value for color, but fortunately IE7/8 don’t show any trace of the text. IE6 shows a faint trace.

In the HTML5 Boilerplate image replacement helper, we’ve also removed any border and background-color that may be on the element. This makes it easier to use the helper class on elements like button or with links that may included background or border properties as part of a design decision.

Benefits over text-indent methods

The new technique avoids various problems with any text-indent method, including the one proposed by Scott Kellum to avoid iPad 1 performance problems related to large negative text indents.

  • Works in IE6/7 on inline-block elements. Techniques based on text indentation are basically “broken”, as shown by this test case:http://jsfiddle.net/necolas/QZvYa/show/
  • Doesn’t result in any offscreen box being created. The text-indentmethods result in a box being drawn (sometimes offscreen) for any text that have been negatively or positively indented. It can sometimes cause performance problems but the font-based method sidesteps those concerns.
  • No need to specify a text-alignment and hide the overflow since the text is crushed to take up no space.
  • No need to hide br or make all fallback HTML display:inline to get around the constraints of using a text indentation. This method is not affected by those problems.
  • Fewer styles are needed as a result of these improvements.

Drawbacks

No image replacement hack is perfect.

  • Leaves a very small trace of the text in IE6.
  • This approach means that you cannot use em units for margins on elements that make use of this image replacement code. This is because the font size is set to 0.
  • Windows-Eyes has a bug that prevents the reading of text hidden using this method. There are no problems with all other screenreaders that have been tested. Thanks to @jkiss for providing these detailed results and to@wilto for confirming this technique works for JAWS 12 in IE 6/7/8 and Firefox 4/5/6.
  • Like so many IR methods, it doesn’t work when CSS is loaded but images are not.
  • Text may not be hidden if a visitor is using a user style sheet which has explicitly set important font-size declarations for the element type on which you have applied the IR class.

It’s worth noting that the NIR image replacement technique avoids these drawbacks, but lacks support in IE6/7.

Closing comments

I’ve been using this technique without significant problems for nearly a year, ever since Jonathan Neal and I used it in a clearfix experiment. The BEM framework also makes use of it for their icon components. The core idea was even proposed back in 2003 but the browser quirks of the day may have prevented wider use.

If you come across any problems with this technique, please report them at the HTML5 Boilerplate GitHub issue tracker and include a test case when appropriate.

Translations

 

Enhanced by Zemanta

Web Standards Update for Visual Studio 2010 SP1

The Web Platform and Tools team is very pleased to announce the first Web Standards Update for Visual Studio SP1. It updates the HTML5 intellisense and validation to reflect the latest W3C specifications and fixes some bugs bugs in the current SP1 support for HTML5. Also JavaScript intellisense it updated to reflect many of the new browser capabilities such as Geolocation and DOM storage. Finally, this update adds comprehensive CSS3 intellisense and validation based on the latest specifications from W3C.

As the HTML5 and CSS3 specifications mature we will make updates available accordingly to ensure that ASP.NET web developers always have the latest standards to work with. This is at the same time an invitation to report any bugs or features you would like to see in future updates. Please write a comment with any bugs or suggestions.

Now let’s take a look at some of the features.

HTML 5

WAI-ARIAThe WAI-ARIA standard enables web developers to make their websites more accessible to e.g. screen readers. This update contains a rather comprehensive support for WAI-ARIA by adding all the aria-* attributes along with new intellisense for the role attribute.

image

The aria-* attributes shows up in the intellisense list as well as the values.

image image

Microdata

HTML 5 has an additional way of adding meaning to the markup called Microdata. This allows web developers to mark different elements with meta data that is readable by e.g. search engines. Bing, Google and Yahoo are all supporting Microdata and more specifically the schema.org vocabularies. This update will therefore add intellisense to the most popular vocabularies including schema.org and data-vocabulary.org.

image

If you are interested in search engine optimization you might find this Microdata support particularly useful.

CSS 3

If you don’t get intellisense after installing the update, you might have to select the CSS 3.0 schema manually on the Style Sheet toolbar.

image

Multi-columns

It is much easier to read lines of text that aren’t too long. Newspapers have always kept their columns rather narrow and with CSS 3 this becomes possible very easily on websites as well. This update brings full intellisense for both properties names and values for multiple columns.

image

For more info on multi-columns, check out this introduction to to the CSS3 Multi-Column Module.

Border-radius

There is no way around this. It’s impossible to talk about CSS3 without giving The Rounded Corners™ example because it is the quintessential CSS3 feature. The CSS3 support brought by this update does of course contain full support for rounded corners aka. border-radius.

image

Animation, transitions and transforms

CSS3 introduces some new and features that could seem a little complicated to learn. With both validation and intellisense to guide you through all these new features, it has never been easier to explore what CSS3 has to offer.

image

JavaScript

The update to JavaScript is very comprehensive. You will immediately start noticing a lot more values in the intellisense.

Geolocation

One of the most talked about features of modern web browsers is their location awareness. In JavaScript you can hook into this knowledge by using the geolocation API. This is also supported in all newer browsers.

image

DOM storage

Using the DOM storage mechanisms you can eliminate the need for cookies to persist user data and settings. Both localStorage and sessionStorage are fully supported by this udpate.

image

Read an introduction to DOM storage.

Also notice…

The HTML 5 support included in SP1 added intellisense and validation for a lot of new elements such as the and elements. However, there were bugs and one of them were the error you would see when adding elements inside elements. This is being fixed by this update so you now also get intellisense for the element. The type attribute is also no longer required in <script> elements.

image

We also added missing elements such as <bdi>, <s> and <u> and a lot of new attributes such as dropzone for drag ‘n drop.

image

Known issues

Though this update contains a lot of new CSS3, HTML5 and JavaScript support, there are certain things that we haven’t been able to do. Since we don’t make any changes to the running code of Visual Studio, we are not able to change the way CSS, HTML and JavaScript gets parsed and validated. That means that even though we are continuing to bring you updates as the W3C standards changes, we will not be able to get it 100% right in Visual Studio 2010.

We do encourage you to report any bugs you find to us directly as a comment here on this blog post. We do take this very seriously and want to get as close to 100% as we possibly can.

Read more

More demos and run trough’s can be found at Scott Hanselman’s blog post and a behind-the-scenes story can be found at Mads Kristensen’s blog