RSS
 

Posts Tagged ‘Article’

One Page Apps I Actually Use

29 Jun

There is a zillion one-page apps focused on making some little aspect of front end development easier. I think they are great. They exemplify the wonderful culture of sharing and ingenuity that our industry is known for. Each of us has slightly different jobs and slightly different skill sets. That means a little helper app that is useful to you might not be to me and vice versa. So of the probably-hundreds of these one-page apps that I've seen over the years, there are only a handful that find myself using on a regular basis. I thought I'd share those, and maybe you can share yours in the comments.

CSS3Please.com

Why type out all five property/value pairs for a transition when you could just come here and copy it quick in nice formatting with comments. Even if you have it memorized, coming here will ensure you have the latest and greatest syntax as browsers evolve.

Border-Radius.com

Every time I need to round some of the corners of an element but not all of them I end up here. I start at the first box, enter the value, and tab around to the other four entering values. The vendor prefixes between moz and webkit are different for specific corners (e.g. radius-topleft vs. top-left-radius) and I can never remember.

HTML-Ipsum.com

I created this one for myself. Just really common bits of HTML markup filled with "lorem ipsum" filler text. Sometimes I need a couple of average length paragraphs of text or a quick unordered-list navigation. Those things are now just a click-to-copy-to-clipboard away.

ScriptSrc.net

I gotta drop jQuery on this page... what's that long funky URL of where it's hosted on Google's CDN again? It's impossible to remember but through this site, you can just click on the library you need and get the script tag copied to your clipboard.

CopyPasteCharacter.com

Ever need a really common symbol for a tweet or an email or website? Just come here and click to copy them. Hold alt to get multiple. Click the link at the top to toggle between encoded and unencoded.

Button Maker

If I just need some quick CSS3 to make a button I usually use this (another one by me). The style doesn't fit every scenario, but I think it's a pretty nice generic customizable style.

One of the sparks that inspired this post was that I just helped a friend slap a design on STRFTIME, a one-page app for getting those placeholder symbols for date formatting (e.g. %Y = 2011).


Advertise here with BSA

One Page Apps I Actually Use is a post from CSS-Tricks

 
 

Screen Resolution ≠ Browser Window

17 Jun

When I tweeted this and then followed up with this, I got comments like this. That comment has a perfectly valid point.

We often talk about screen resolution, which is not the relevant statistic when thinking about what space our website's visitors have available. The relevant statistic is browser window size. So why do we talk about screen resolution so much? Well probably because in the most popular analytics software in the world, Google Analytics, it's the only data you get.

(The Google Analytics team is aware of this)

And so, what are we to do? Well, start measuring browser size, for one.

But first, a word.

What if we figured out all kinds of data about our visitors browser sizes. What is to be done with this data once we have it? If @beep has taught us anything, it's that we can and should accomodate to browsers of any shape and size.

But still, having information is never a bad thing. Smarter men and women than me may see things I do not and think of reasonable actions to take based on this data.

Getting the Data

Since Google Analytics can't currently help us, we'll need to run some JavaScript on the page ourselves to get the data. jQuery makes it easy to measure sizes as well as make and Ajax call to POST the data to a script that can save it:

$.ajax({
  type: "POST",
  url: "/savedata.php",
  data: {
    width        : $(window).width(),
    height       : $(window).height(),
    screen_width : screen.width,
    screen_height: screen.height
  }
});

Now we just need that script savedata.php to be ready to accept and save that data. First we need a database, so here's a simple structure for one:

I'm no MYSQL expert, but this is what exporting the structure from phpMyAdmin gave me:

CREATE TABLE `data` (
  `id` int(11) NOT NULL auto_increment,
  `width` int(11) NOT NULL,
  `height` int(11) NOT NULL,
  `screen_width` int(11) NOT NULL,
  `screen_height` int(11) NOT NULL,
  KEY `id` (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=72141 DEFAULT CHARSET=utf8 AUTO_INCREMENT=72141 ;

And now my wicked primitive script for saving the POSTs:

<?php

	$dbhost = 'localhost';
	$dbuser = 'db_user_name';
	$dbpass = 'db_password';

	$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die ('Error connecting to mysql');

	$dbname = 'db_name';
	mysql_select_db($dbname);

	$width         = mysql_real_escape_string($_POST['width']);
	$height        = mysql_real_escape_string($_POST['height']);
	$screen_width  = mysql_real_escape_string($_POST['screen_width']);
	$screen_height = mysql_real_escape_string($_POST['screen_height']);

	$sql = "INSERT INTO data ( width,  height,  screen_width,  screen_height)
	      VALUES           ($width, $height, $screen_width, $screen_height)";

	if (!mysql_query($sql, $conn)) {
		die("Error:" . mysql_error());
	}

	echo "1 Record Added";

	mysql_close($conn);

?>

That's what I did on CSS-Tricks for one day. If you'd like, here's the complete data I collected as SQL.

Looking At The Results

Remember: ALL of this data was collected from css-tricks.com. So it's a bunch of designer nerds, probably. It's only relevant to this site and sites with very similar audiences.

First, the borin' ol screen resolution data. I got this by querying 500 random samples of data and laying div's of that size on top of each other with as light of gray as I could make. Incidently, its rgba(0,0,0,0.004), because rgba(0,0,0,0.003) is pure white (weird).

Notice the rather hard lines. Monitors only come in so many sizes. Makes sense. Here's what happens when we do the same thing with browser window sizes though:

Much more blurry. Also makes sense. Even as I write this my browser is at some very arbitrary sizing, probably about 80% of my screen resolution. Click those images above to see them bigger. You'll notice that whatever visible hard edges there are in the browser size version, they are exactly 20px narrower than the screen size counterpart. Interesting.

If I tint the screen sizes red and the browser sizes green and put them on top of each other, this is what we get:

Notice on the outside edges the tint stays red. Not a lot of people who have extremely wide monitors have their browser window open that wide. I know I don't. Let's look at the stats for "full screen" browsers. How many people browser full screen, or with their browser window "maximized" so to speak. Well if you query only for entries where the window and the screen resolution are exactly the same, very few, less than 1%, but it get's interesting:

Totally full screen0.85%
Within 50px of full screen1.06%
Within 100px of full screen9.67%
Within 200px of full screen61.18%

So very few people browse full screen, but the majority of people browse pretty close to full screen. As speculation, it's likely the Windows folks are the ones browsing full screen, as that's much more natural behavior on that operating system. But now "full screen" is a big deal in OS X Lion, maybe that will start effecting this stuff.

If we put this stuff to a spread and use the entire data set, here's one way to break it down:

Width RangeBrowser WindowScreen Resolution
0px - 500px1.13%1.02%
501px - 800px2.01%1.06%
801px - 1000px2.84%0.07%
1001px - 1200px14.91%6.86%
1201px - 1400px40.65%35.57%
1401px - 1600px17.38%17.17%
1601px - 2000px20.41%34.34%
2000px+0.66%3.91%

So where is mobile in all this? Despite reports of massive growth in mobile browsing, which I do not doubt, CSS Tricks has very little mobile traffic.

Let's wrap it up with some quick hits:

  • The most popular screen resolution is 1680 x 1050 with almost 13% of visits having a monitor of that size.
  • Predictably, there is no one browser window size that is far above all others, but leading the pack is 1349 x 667 at 0.75% of visits.
  • The most popular screen resolution ratio is 16:10 with 46% of visits having that. Maybe because a lot of video is 16:9 and monitor makers wanted people to watch that but still have room for some OS chrome? 16:9 is next with 29%, 5:4 with 12%, and 4:3 with 8%.
  • All of those ratios are wider than tall. Turns out only 2% of visitors have screens that are taller than wide (or at least that report that way).
  • Actual browser windows also tend to be wider than tall, with only 3% of visits having dimensions that are taller than wide.
  • Average number of pixels per screen = 1,539,515
  • Average screen resolution = 1526 x 967
  • Average browser window size = 1366 x 784

Huge Thanks

To Jamie Bicknell of Rentedsmile Web Design for helping me wrassle together the MYSQL queries and PHP needed to do anything useful with the data.


Advertise here with BSA

Screen Resolution ≠ Browser Window is a post from CSS-Tricks

 
 

Window Inactive Styling

06 May

You can customize the text color and background color of text when it's selected with ::selection and ::-moz-selection. We've covered that a number of times here in various forms and it's a cool little trick.

Even the HTML5 Boilerplate has it in there by default, using super hot pink, which is the easiest way to spot a boilerplate site =).

But when you change text selection styling away from its default, you lose the default styling's ability to desaturate itself when the window goes out of focus. See:

I rather like how the default desaturates and becomes less visually intense. After all, chances are you are focused on another window right now and don't need a background window fighting for attention.

Perhaps a little known fact, but you can use a pseudo selector in conjunction with ::selection to apply styling when the window is in it's inactive state. It uses the :window-inactive pseudo selector, like this:

::selection {
  background: hsl(136,65%,45%);
  color: white;
}
::selection:window-inactive {
  background: hsl(136,25%,65%);
}

Using HSL for color value there, I was able to lower the saturation and increase the lightness to get a less intense version of the same hue.

Remember Firefox has it's own version of ::selection, ::-moz-selection. It also has it's own version of :window-inactive, :-moz-window-inactive. Unfortunately using these things together doesn't work.

/* Does work */
::-moz-selection {
  background: rgba(255,0,0,0.9);
  color: white;
}
/* Doesn't work */
::-moz-selection:-moz-window-inactive {
  background: rgba(255,0,0,0.3);
}
/* Nor this */
:-moz-window-inactive::-moz-selection {
  background: rgba(255,0,0,0.3);
}

So anyway, you can at least get a custom text selection color in Firefox (3.6+ ?) but you can't style it specially for window inactive. However, Firefox (3.6 and 4 tested) automatically make your text selection gray on when the window is out of focus.

It's important to note that it's not because :-moz-window-inactive doesn't work, it does, you can use it on any element, actually, like making a div change background color in that state. It's just using them together that doesn't.

This is not a case where we can shake our fists at the browser vendors. None of this is standardized. ::selection isn't standard. :window-inactive isn't standard. In fact, ::selection is actually technically a pseudo element not pseudo selector so it should have to come last in the selector, but if you switch them around it doesn't work.

More than just text selection

If :window-inactive was standardized and more widely supported, you could do way more with it than just deal with text selection colors. Think of gray-scaling a whole website or stopping animations.


Advertise here with BSA

 
 

Custom Scrollbars in WebKit

02 May

Way back in the day, you could customize scrollbars in IE (5.5) with non-standard CSS properties like scrollbar-base-color which you would use on the element that scrolls (like the <body>) and do totally rad things. IE dropped that.

These days, customizing scrollbars is back, but it's WebKit this time. It's a bit better now, because the properties are vendor-prefixed (e.g. ::-webkit-scrollbar) and use the "Shadow DOM". This has been around for a couple of years. David Hyatt blogged it in early 2009 and put together an example page of just about every combination of scrollbar possibilities you could ever want.

The Goods

The Different Pieces

These are the pseudo elements themselves. The actual parts of the scrollbars.

::-webkit-scrollbar              { /* 1 */ }
::-webkit-scrollbar-button       { /* 2 */ }
::-webkit-scrollbar-track        { /* 3 */ }
::-webkit-scrollbar-track-piece  { /* 4 */ }
::-webkit-scrollbar-thumb        { /* 5 */ }
::-webkit-scrollbar-corner       { /* 6 */ }
::-webkit-resizer                { /* 7 */ }

The Different States

These are the pseudo class selectors. They allow for more specific selection of the parts, like when the scrollbar is in different states.

:horizontal
:vertical
:decrement
:increment
:start
:end
:double-button
:single-button
:no-button
:corner-present
:window-inactive

I'm going to steal this whole section from David's blog post on the WebKit blog because it explains each part well:

:horizontal – The horizontal pseudo-class applies to any scrollbar pieces that have a horizontal orientation.

:vertical – The vertical pseudo-class applies to any scrollbar pieces that have a vertical orientation.

:decrement – The decrement pseudo-class applies to buttons and track pieces. It indicates whether or not the button or track piece will decrement the view’s position when used (e.g., up on a vertical scrollbar, left on a horizontal scrollbar).

:increment – The increment pseudo-class applies to buttons and track pieces. It indicates whether or not a button or track piece will increment the view’s position when used (e.g., down on a vertical scrollbar, right on a horizontal scrollbar).

:start – The start pseudo-class applies to buttons and track pieces. It indicates whether the object is placed before the thumb.

:end – The end pseudo-class applies to buttons and track pieces. It indicates whether the object is placed after the thumb.

:double-button – The double-button pseudo-class applies to buttons and track pieces. It is used to detect whether a button is part of a pair of buttons that are together at the same end of a scrollbar. For track pieces it indicates whether the track piece abuts a pair of buttons.

:single-button – The single-button pseudo-class applies to buttons and track pieces. It is used to detect whether a button is by itself at the end of a scrollbar. For track pieces it indicates whether the track piece abuts a singleton button.

:no-button – Applies to track pieces and indicates whether or not the track piece runs to the edge of the scrollbar, i.e., there is no button at that end of the track.

:corner-present – Applies to all scrollbar pieces and indicates whether or not a scrollbar corner is present.

:window-inactive – Applies to all scrollbar pieces and indicates whether or not the window containing the scrollbar is currently active. (In recent nightlies, this pseudo-class now applies to ::selection as well. We plan to extend it to work with any content and to propose it as a new standard pseudo-class.)

All together now

These pseudo elements and pseudo class selectors work together. Here are some random examples:

::-webkit-scrollbar-track-piece:start {
   /* Select the top half (or left half) or scrollbar track individually */
}

::-webkit-scrollbar-thumb:window-inactive {
   /* Select the thumb when the browser window isn't in focus */
}

::-webkit-scrollbar-button:horizontal:decrement:hover {
   /* Select the down or left scroll button when it's being hovered by the mouse */
}

Very Simple Example

To make a really simple custom scrollbar we could do this:

::-webkit-scrollbar {
    width: 12px;
}

::-webkit-scrollbar-track {
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
    border-radius: 10px;
}

::-webkit-scrollbar-thumb {
    border-radius: 10px;
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
}

In which we'd get this on a simple div with vertically overflowing text:

In The Wild

Check out the very subtle and nice scrollbars on Tim Van Damme's blog Maxvoltar:

The particularly nice bit here is that the scrollbar is on the body element, yet the scrollbar isn't stuck to the top, bottom, or right edge of the browser window as scroll bars normally are. I made a test page with copy-and-pasteable code to achieve that a similar effect:

View Demo

On Forrst, they use custom scollbars on code snippets which are also pretty nice. They are less visually intense and so don't fight as much with the code highlighting.

Related


Advertise here with BSA

 
 

Responsive Data Tables

27 Apr

Garrett Dimon:

Data tables don't do so well with responsive design. Just sayin'.

He has a good point. Data tables can be quite wide, and necessarily so. A single row of data needs to be kept together to make any sense in a table. Tables can flex in width, but they can only get so narrow before they start wrapping cells contents uncomfortably or just plain can't get any narrower.

Responsive design is all about adjusting designs to accomodate screens of different sizes. So what happens when a screen is narrower than the minimum width of a data table? You can zoom out and see the whole table, but the text size will be too small to read. Or you can zoom in to the point of readability, but browsing the table will require both vertical and (sad face) horizontal scrolling.

So here's what we are gonna do...

We're going to use "responsive design" principles (CSS @media queries) to detect if the screen is smaller than the maximum squishitude of our table. If it is, we're going to reformat the table.

We're being good boys and using Plain Ol' Semantic Markup here for our table. Bare bones example:

<table>
	<thead>
	<tr>
		<th>First Name</th>
		<th>Last Name</th>
		<th>Job Title</th>
	</tr>
	</thead>
	<tbody>
	<tr>
		<td>James</td>
		<td>Matman</td>
		<td>Chief Sandwich Eater</td>
	</tr>
	<tr>
		<td>The</td>
		<td>Tick</td>
		<td>Crimefighter Sorta</td>
	</tr>
	</tbody>
</table>

Our regular CSS is nothing special:

/*
Generic Styling, for Desktops/Laptops
*/
table {
	width: 100%;
	border-collapse: collapse;
}
/* Zebra striping */
tr:nth-of-type(odd) {
	background: #eee;
}
th {
	background: #333;
	color: white;
	font-weight: bold;
}
td, th {
	padding: 6px;
	border: 1px solid #ccc;
	text-align: left;
}

The small-screen responsive stuff comes in now. We've already figured out our minimum table width is about 760px so we'll set up our media query to take affect when the narrower than that. Also, we'll target iPads as they are right in that zone.

The biggest change is that we are going to force the table to not behave like a table by setting every table-related element to be block-level. Then by keeping the zebra striping we originally added, it's kind of like each table row becomes a table in itself, but only as wide as the screen. No more horizontal scrolling! Then for each "cell", we'll use CSS generated content (:before) to apply the label, so we know what each bit of data means.

/*
Max width before this PARTICULAR table gets nasty
This query will take effect for any screen smaller than 760px
and also iPads specifically.
*/
@media
only screen and (max-width: 760px),
(min-device-width: 768px) and (max-device-width: 1024px)  {

	/* Force table to not be like tables anymore */
	table, thead, tbody, th, td, tr {
		display: block;
	}

	/* Hide table headers (but not display: none;, for accessibility) */
	thead tr {
		visibility: hidden;
		height: 0;
	}

	tr { border: 1px solid #ccc; }

	td {
		/* Behave  like a "row" */
		border: none;
		border-bottom: 1px solid #eee;
		position: relative;
		padding-left: 50%;
	}

	td:before {
		/* Now like a table header */
		position: absolute;
		/* Top/left values mimic padding */
		top: 6px;
		left: 6px;
		width: 45%;
		padding-right: 10px;
		white-space: nowrap;
	}

	/*
	Label the data
	*/
	td:nth-of-type(1):before { content: "First Name"; }
	td:nth-of-type(2):before { content: "Last Name"; }
	td:nth-of-type(3):before { content: "Job Title"; }
	td:nth-of-type(4):before { content: "Favorite Color"; }
	td:nth-of-type(5):before { content: "Wars of Trek?"; }
	td:nth-of-type(6):before { content: "Porn Name"; }
	td:nth-of-type(7):before { content: "Date of Birth"; }
	td:nth-of-type(8):before { content: "Dream Vacation City"; }
	td:nth-of-type(9):before { content: "GPA"; }
	td:nth-of-type(10):before { content: "Arbitrary Data"; }
}

And so, desktops get the regular table experience, mobile (or otherwise small screens) get a reformatted and easier to explore table:

Hey what about IE?

Sigh. Here's the deal. IE (even 9 and 10 preview) don't like you setting table elements as display: block; It does weird stuff and doesn't work right. But those versions of IE do support media queries. So my solution thus far is just to wrap the media query styles in conditional comments.

<!--[if !IE]><!-->
<style>
   /* table-related media query stuff only */
</style>
/* Or an external stylesheet or whatever */
<!--<![endif]-->

If the problem was only that older versions of IE don't support media queries, we could use the css3-mediaqueries-js project (polyfills support for all media queries) or Respond (also polyfill, way smaller, but only does min/max-width). They both work very well. But this isn't our problem in this case.

See it

There are two pages to the demo, one the "regular" table so you can see the problem. Then a link there to the responsive table so you can see the solution.

View Demo

In the demo I use a couple of extra media queries for mobile to force the body to certain widths so they don't get feisty. View source to snag.

This isn't perfect...

This is just one potential solution to the problem to data tables on small screens. It's not perfect. There may be some accessibility concerns (or maybe not, I'm really not sure). It's likely there are some fancy JavaScript solutions that could approach things differently and also work great. If other solutions to this come along, I'll keep this page updated.

UPDATE: Other ideas

Scott Jehl created two alternative ideas that are both very cool and very different from this. This highlights an important point: it's all about the specific context of your data table that dictates what solution to go with.

One of them makes a pie graph from the data in the chart. On narrower screens, the pie graph shows and the table hides, otherwise only the more information-rich table shows. Arguably, the mobile version is more useful!

View Demo

The next idea (Scott credits Todd Parker) is to turn the table into a mini graphic of a table on narrow screens, rather than show the whole thing. This shows the user there is a data table here to be seen, but doesn't interfere with the content much. Click the table, get taken to a special screen for viewing the table only, and click to get back.

View Demo


Advertise here with BSA

 
 

IEMobile Conditional Comment

21 Mar

Did you know you can target the Internet Explorer browser on mobile Windows Phone 7 devices?

<!--[if IEMobile]>
   Displayed only on Internet Explorer Mobile on Windows Phone 7
<![endif]--> 

<![if !IEMobile]>
  Anything else
<![endif]>

You totally can1. Hearts to Allison Wagner for telling me about it.

It's a bit more en vogue to handle mobile styling via media queries, which I generally agree is a better way to handle things (browser agnostic), but has the classic problem of a the browser needing to downloading resources it doesn't need (e.g. CSS for desktop version when on a mobile device).

You know what would be super radical? If we could do media queries within conditional comments.

<!-- [if (min-device-width: 481px)]>

<![endif]—>

That would combine the syntax and power of media queries, with the ability of conditional comments to load only the specific resources we need, staying streamlined in terms of bandwidth.


1 Notice in the first block of conditional comments above the slightly different syntax. The former is called a downlevel-hidden comment and the latter is a downlevel-revealed comment. Nerdgrammer.

 
 

Show and Edit Style Element

02 Mar

Kind of a classic little trick for ya'll today. You know the <style> blocks you can put in the <head> of your HTML to do styling? You don't actually have to put those in your head, they can be anywhere on the page. It's not valid (or good practice) but it works.

What's more? It's just an element like any other. The default stylesheet of all browers makes it display: none;.

If you move it down into the body and reset it to display: block; you can see the very code which is applying style to that page. Might as well make it look nice and code-y to eh?

body style {
	display: block;
	background: #333;
	color: white;
	font: 13px/1.8 Monaco, Mono-Space;
	padding: 20px;
	white-space: pre;
}

What's more? You can give it the HTML5 attribute of contenteditable and you can literally edit the CSS right there and watch it effect the page.

<style contenteditable>body {
  background: green;
}</style>

View Demo

That's how all the code on The Shapes of CSS page is done. Not only is it just kinda neat, but it's very useful on a page like that so you don't have to maintain the CSS in two places.

 
 

Poll Results: HTML5 Features in Use on Production Sites

17 Feb

As a follow up to asking people if they are using HTML5 or not, I asked the people who are:

What features of HTML5 have you used on production sites?

These are the levels of popularity, from almost 3,000 voters:

Not a big surprise that using the new semantic elements (like <nav>) is the most common use of production HTML5. It's easy, it's hip, it feels good.

Right behind that are the new form features. I'm happy to see that, as these things are also very easy to implement and usability tremendously, as well as replace clunky-ish JavaScript methods (I'm thinking of things like range inputs and the placeholder attribute).

Third place is the audio and video features. I'm sure iDevices helped push that along, as using HTML5 is really easy and works on those devices. Fallbacks are now also easy to implement.

The least popular feature is cross document messaging. Also not a huge surprise as it's not all that common of a thing to need. I do think this is super duper cool though, especially as I've been working on a thing that uses it.

"Other" came in ahead of a number of other features, so apparently I've missed a number of HTML5 features that people are actively using. Please share!

 
 

Moving Highlight

09 Jan

I recently noticed a subtle and nice effect in the Google Chrome UI. As you mouse over inactive tabs, they light up a bit, but also have a gradient highlight that follows your mouse as you move around on them.

The guys from DOCTYPE told me it was their inspiration for the navigation on their website. They are doing it just like I would have, with CSS3 gradients and jQuery. So I decided to snag their code and play around with it.

Radial Gradient

The highlight itself will be created from a radial gradient. One possible way to do that would be to create an alpha transparent PNG image and use that. We like to be all hip and progressive around here though. Radial gradients can be created through CSS3, which saves us a resource request and allows easier changing of colors.

Webkit and Mozilla based browsers (only) can do radial gradients. The syntax:

background: -webkit-gradient(
  /* radial, <point>, <radius>, <point>, <radius>, <stop>,  [<stop>, ] <stop> */
  radial, 500 25%, 20, 500 25%, 40, from(white), to(#ccc)
);

background: -moz-radial-gradient(
  /* [<position>,] [<shape> || <size>,] <stop> [, <stop>], <stop> */
  500px 25%, circle, white 20px, #ccc 40px
);

JavaScript Mouse Postion

Now we know how to apply a CSS3 gradient, but the point of this is to apply the gradient highlight where the mouse is. CSS isn't capable of giving us mouse position coordinates, we'll need JavaScript for that. So here is the plan:

  1. When the mouse moves over the area
  2. Detect mouse position
  3. Apply gradient to area in that position
  4. Remove gradient when mouse leaves

We'll be using jQuery.

var x, y;

$('#highlight-area').mousemove(function(e) {

  x  = e.pageX - this.offsetLeft;
  y  = e.pageY - this.offsetTop;

  // apply gradient using these coordinates

}).mouseleave(function() {			

  // remove gradient

});

The Trouble With Vendor Prefixes in Values

Vendor prefixes as properties is fine. You want to rotate something cross-browser (with a dynamic JavaScript value), you need to use -webkit-transform, -o-transform, and -moz-transform. If you need to do it with jQuery, you could do:

var angle = 30;

$(".rotate-me").css({
  "-webkit-transform" : "rotate(" + angle + "deg)",
  "-moz-transform" : "rotate(" + angle + "deg)"
  "-o-transform" : "rotate(" + angle + "deg)"
});

That works because each of the properties is different. With gradients, the property is always the same, the background-image property. So just like this won't work:

$(".wont-make-purple").css({
  "color" : "red",
  "color" : "blue" // overrides previous
});

This won't work either:

$("#highlight-area").css({
  "background-image" : "-webkit-gradient(radial, " + xy + ", 0, " + xy + ", " + gradientSize + ", from(" + lightColor + "), to(rgba(255,255,255,0.0))), " + originalBG;
  "background-image" : "-moz-radial-gradient(" + x + "px " + y + "px 45deg, circle, " + lightColor + " 0%, " + originalBGplaypen + " " + gradientSize + "px)"
});

But somehow, inexplicably (and thankfully) this does work:

var bgWebKit = "-webkit-gradient(radial, " + xy + ", 0, " + xy + ", " + gradientSize + ", from(" + lightColor + "), to(rgba(255,255,255,0.0))), " + originalBGplaypen;
var bgMoz    = "-moz-radial-gradient(" + x + "px " + y + "px 45deg, circle, " + lightColor + " 0%, " + originalBGplaypen + " " + gradientSize + "px)";

$(this)
	.css({ background: bgWebKit })
	.css({ background: bgMoz });

There must be some magic smarts worked in there somewhere were it doesn't override the previously set values.

Highlighted Tabs

So let's give ourselves the actual tabs in which to highlight. Nothing special in the markup:

<ul class="nav clearfix">
   <li><a href="#">Home</a></li>
   <li><a href="#">About</a></li>
   <li class="active"><a href="#">Clients</a></li>
   <li><a href="#">Contact Us</a></li>
</ul>

And the CSS to make them tab-like:

.nav {
	list-style: none;
	border-bottom: 1px solid #a0a0a0;
	padding: 10px 10px 0 10px;
}
.nav li { display: inline; }
.nav li.active a {
	position: relative;
	z-index: 1;
	bottom: -2px;
	margin-top: -2px;
	background: #eee;
	padding-top: 8px;
	padding-bottom: 8px;
}
.nav li a {
	float: right;
	text-decoration: none;
	position: relative;
	padding: 7px 50px;
	margin: 0 0 0 -8px;
	color: #222;
	background: #d8d7d8;
	-webkit-border-top-right-radius: 20px 40px;
	-webkit-border-top-left-radius: 20px 40px;
	-moz-border-radius-topleft: 20px 40px;
	-moz-border-radius-topright: 20px 40px;
	-webkit-box-shadow: inset 1px 1px 0 white;
	-moz-box-shadow: inset 1px 1px 0 white;
	border: 1px solid #a0a0a0;
}

So now each of those tabs is the area in which we plan to apply the highlight. For every non-active tab, we'll put together all the things we've covered:

var originalBG = $(".nav a").css("background-color");

$('.nav li:not(".active") a')
.mousemove(function(e) {

    x  = e.pageX - this.offsetLeft;
    y  = e.pageY - this.offsetTop;
    xy = x + " " + y;

    bgWebKit = "-webkit-gradient(radial, " + xy + ", 0, " + xy + ", 100, from(rgba(255,255,255,0.8)), to(rgba(255,255,255,0.0))), " + originalBG;
    bgMoz    = "-moz-radial-gradient(" + x + "px " + y + "px 45deg, circle, " + lightColor + " 0%, " + originalBG + " " + gradientSize + "px)";

    $(this)
      .css({ background: bgWebKit })
      .css({ background: bgMoz });

}).mouseleave(function() {
	$(this).css({ background: originalBG });
});

View Demo   Download Files

 
 

WebKit Image Wipes

18 Dec

It's not "spec," but WebKit browsers support image masks. If you are familiar with Photoshop, they work like that. You declare an image to use as as mask. The black parts of that image hide what it is over, white parts of that image show what is underneath, gray is partially transparent. So if you had this image:

<img src="orig.jpg" alt="trees" class="circle-mask">

And you had this image you created as a mask:

You'd apply it to the image in CSS like:

.circle-mask {
  -webkit-mask-box-image: url(mask.png);
}

And this would be the result:

You Don't Need Actual Images

The first trick we're going to utilize here is that the image we delcare for the -webkit-mask-box-image doesn't need to be an actual graphic image. Instead we can use -webkit-gradient to create that image. Yes, we could just make an image that is a gradient as well, but creating the gradient mask programmatically means that it's far easier to adjust on the fly and requires one less HTTP request.

-webkit-mask-position: 0 0;
-webkit-mask-size: 200px 200px;
-webkit-mask-image: -webkit-gradient(linear, left top, right bottom,
   color-stop(0.00,  rgba(0,0,0,1)),
   color-stop(0.45,  rgba(0,0,0,1)),
   color-stop(0.50,  rgba(0,0,0,0)),
   color-stop(0.55,  rgba(0,0,0,0)),
   color-stop(1.00,  rgba(0,0,0,0)));

In the above CSS, we've created a 200px by 200px image which fades from fully opaque in the top left and fading and about half-way point at a 45deg angle, fades to fully transparent. That would look a little something like this:

Moving The Mask

Notice we set the position of the mask with -webkit-mask-position. Because we can set the position, we can move the position. We could move it on a :hover -

.circle-mask {
	-webkit-mask-position: 0 0;
}
.circle-mask:hover {
	-webkit-mask-position: -300px -300px;
}

Or we could use a -webkit-animation to automatically move that mask.

@-webkit-keyframes wipe {
	0% {
		-webkit-mask-position: 0 0;
	}
	100% {
		-webkit-mask-position: -300px -300px;
	}
}
.circle-mask {
	-webkit-animation: wipe 6s infinite;
	-webkit-animation-delay: 3s;
	-webkit-animation-direction: alternate;
}

Creating The Wipe

I'm sure all you smarties have already put all this together. The idea is that we have one image on top of another image. The image on top gets the mask, and then we move the mask as needed.

<div id="banner">
	<div><img src="images/banner-1.jpg" alt="Skyline 1"></div>
	<div><img src="images/banner-2.jpg" alt="Skyline 2"></div>
</div>
#banner {
	width: 800px;        /* Size of images, will collapse without */
	height: 300px;
	position: relative;  /* For abs. positioning inside */
	border: 8px solid #eee;
	-webkit-box-shadow: 1px 1px 3px rgba(0,0,0,0.75);
}

#banner div {
	position: absolute; /* Top and left zero are implied */
}

/* Second one is on top */
#banner div:nth-child(2) {
	-webkit-animation: wipe 6s infinite;
	-webkit-animation-delay: 3s;
	-webkit-animation-direction: alternate;
	-webkit-mask-size: 2000px 2000px;
	-webkit-mask-image: -webkit-gradient(linear, left top, right bottom,
			color-stop(0.00,  rgba(0,0,0,1)),
			color-stop(0.45,  rgba(0,0,0,1)),
			color-stop(0.50,  rgba(0,0,0,0)),
			color-stop(0.55,  rgba(0,0,0,0)),
			color-stop(1.00,  rgba(0,0,0,0)));
}

Demo and Download

In the download, there is another example where the wipe goes horizontally instead of at an angle, and happens using -webkit-transition rather than animation on a hover event.

View Demo   Download Files

More Than Two?

I spent more time than I probably should have trying to see if I could get the animation to wipe three images in succession. It's kind of possible but I wasn't able to get it smooth and consistent as I would have liked, so I scrapped it. I'm still fairly sure it's possible, probably using two different animations with different delays or the like. If you try it and get it worked, do show!

More

Check out the announcement from 2008 for more information about the masks themselves. There are useful bits to know in there, like the mask images can stretch (like full page backgrounds) and repeat. It actually works a lot like border-image, with the nine-box system for stretching/repeating.

Credit

I stole this idea from Doug Neiner who showed me a little demo of the idea. Posted with permission.