Historical Reference: the <hgroup> element

Note: The <hgroup> element has been made obsolete.

This post was pulled from the original version of my book Mobile HTML5. I have added it to the blog for historical reference. At the time of this posting, the title and subtitle of my blog are in an hgroup.

————–

The <hgroup> groups a series of <h1> to <h6> elements when the heading has more than one level, such as a heading with a subheading, alternative headline and / or tagline. This may seem like a useless element, but it does serve an important purpose: <hgroup> enables a subheading to be associated with a related heading, so you can include more expressive content, like a subtitle or tagline, without the subheading being added to the document outline.

Many designers will create a main header with a tagline directly underneath.  In the past, developers have ‘incorrectly’ included an <h1> for the main title, followed by a <h3> for the much smaller tagline, providing for two main headers in non-sequential order, when in actuality, only the contents of the <h1> was the real title of the page. Another markup tactic involved including a <span> within the <h1> to stylize part of the heading as a tagline or subheading, even thought the tagline did not have the same importance as the rest of the heading in which it was incased.

For example, in previous versions of HTML, we may have written:

<h1>Sectioning Elements in HTML5 <span>Dividing your pages semantically with new HTML5 sectioning elements</span></h1>

we can now write:

<hgroup>
<h1>Sectioning Elements in HTML5 </h1>
<h2>Dividing your pages semantically with new HTML5 sectioning elements</h2>
</hgroup>

The document outline will then only show the contents of the <h1>.  Breaking the document up into semantic sections allows HTML5 to create an explicit outline for the document, with the table of contents delineated by the header of each section. In previous versions, including <h1> thru <h6> determined the document outline. With HTML5 you can now add headers without adding to the outline, and you can add to the outline without adding headers. To check out the outline created by the semantic markup in your documents, add the HTML5 Outliner plug-in (http://code.google.com/p/h5o/) to your browser.

For example, a web page may contain code similar to the following:

 

<h1>Standardista</h1>
<h2>CSS3, JavaScript and HTML5 explained</h2>
<section>
     <h2>CSS3 Selectors &amp; Browser Support</h2>
     <h3>Which CSS selectors are well supported by which browsers</h3>
<p> ...content here ....</p>
</section>

In creating a table of contents for content of the site, the above would include all of the headers, which is too many, creating an outline that looks like the following:

Standardista …………………. …………………. …………… ……………………………. page 1

CSS3, JavaScript and HTML5 explained………. …………. … … …………….. page 1

CSS3 Selectors & Browser Support…… ………….. ………… … ………………. page 1

Which CSS selectors are well supported by which browsers… page 1

The above creates an outline that is more detailed than our actual content. By encompassing actual headers with their tagline or subtitle, we can create a more appropriately detailed outline:

 

<hgroup>
     <h1>Standardista</h1>
     <h2>CSS3, JavaScript and HTML5 explained</h2>
</hgroup>
<section>
<hgroup>
     <h2>CSS3 Selectors &amp; Browser Support</h2>
     <h3>Which CSS selectors are well supported by which browsers</h3>
</hgroup>
<p> ...content here ....</p>
</section>

Grouping header content within an <hgroup> creates a much more appropriate site outline:

Standardista …………………. …………………. …………… ……………………………. page 1

CSS3 Selectors & Browser Support…… ………….. ………… … ………………. page 1

The purpose of <hgroup> is to enable outlining based on header levels, masking all but the highest-ranking heading element within an <hgroup> from the outline algorithm. Using <hgroup>, the subheading is associated with the heading and does not get added to the outline.

Responsive Images: Clown Car Technique

Adaptive images are the current hot topic in the Adaptive Design and Responsive Web Design conversations. Why? Because no one likes any of the solutions. New elements and attributes are being discussed as a solution for what is, for most of use, a big headache.

We have foreground and background images. We have large displays and small displays. We have regular resolution and high resolution displays. We have good bandwidth and low bandwidth connections.

Some choose to “waste bandwidth” (and memory) by sending high-resolution images to all devices. Others send regular resolution images to all devices which look less crisp on high resolution displays.

When it comes to background images, we have media queries. This makes it (almost) simple to send the right size and resolution images based on the device pixel ratio, size and / or orientation of the screen.

Proposed solutions with new technology

With content images, it’s a bit more difficult. Most believe that there is no mechanism for the <img> tag to download the right size and resolution image. Polyfills have been created. Services have been formed.

The <picture> element leveraging the semantics of the HTML5 <video> elements, with its support of media queries to swap in different source files was proposed:

<picture alt="responsive image">
     <source src=large.jpg media="(min-width:1600px), (min-resolution: 136dpi) and (min-width:800px) ">
     <source src=medium.jpg media="(min-width:800px), (min-resolution: 136dpi) and (min-width:400px) ">
     <source src=small.jpg>
        <!-- fallback -->
        <img src=small.jpg alt="responsive image">
  </picture>

Another method, using a srcset attribute on the <img> element has also been proposed. The above would be written as:

 <img alt="responsive image"
           src="small.jpg"
           srcset="large.jpg 1600w, large.jpg 800w 1.95x, medium.jpg 800w, medium.jpg 400w 1.95x">

Possible Solutions with Existing Tech: SVG

What many people don’t realize is we already have the technology to serve responsive images. We have had browser support for responsive images for a long, long time! SVG has supported media queries for a long time, and browsers have supported SVG for … well, not quite a long time, but still. Most browsers support media queries in the SVG (test your browser). The main issue is terms of mobile is old Androids lack of support until 3.0..

We can use media queries within SVG to serve up the right image. The beauty of the "Clown Car" technique is that all the logic remains in the SVG file. I’ve called it the "Clown Car" technique since we are including (or stuffing) many images (clows) into a single image file (car).

When you mark up your HTML, you simply add a single call to an SVG file.

<img src="awesomefile.svg" alt="responsive image">

Now isn’t that code simple?

The magic is that SVG supports both media queries and rasterized images.

In our SVG file, using the <image> element, will include the all the images that we may need to serve, and include all the media queries.

Here is the code for one of the SVG files:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="329">
  <title>The Clown Car Technique</title>
    <defs>
    <style>
    image {display: none;}
    #small {display: block}
     @media screen and (min-width: 401px) and (max-width: 700px) {
        #medium {display: block}
        #small {display: none}
    }
      @media screen and (min-width: 701px) and (max-width: 1000px) {
        #big {display: block}
        #small {display: none}
    }
     @media screen and (min-width: 1001px)  {
      #huge {display: block}
      #small {display: none;}
    }
    </style>
  </defs>
  <g>
    <image id="small"  height="329" width="300" xlink:href="images/small.png" />
    <image id="medium" height="329" width="300" xlink:href="images/medium.png" />
    <image id="big"    height="329" width="300" xlink:href="images/big.png" />
    <image id="huge"   height="329" width="300" xlink:href="images/huge.png" />
  </g>
  </svg>

Unfortunately, when this file is used, all 4 PNGs are retrieved from the server. To solve this issue, we can use background images instead:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 329" preserveAspectRatio="xMidYMid meet">
 <title>Clown Car Technique</title>
 <style> 
  svg {
    background-size: 100% 100%;
    background-repeat: no-repeat;
  } 
 @media screen and (max-width: 400px) {
  svg {background-image: url(images/small.png");}
 } 
 @media screen and (min-width: 401px) and (max-width: 700px) {
  svg {background-image: url(images/medium.png);}
 } 
 @media screen and (min-width: 701px) and (max-width: 1000px) {
  svg {background-image: url(images/big.png);}
 } 
 @media screen and (min-width: 1001px) {
  svg {background-image: url(images/huge.png);}
 }
 </style>
</svg>

This version only downloads the images required, thereby solving the multi-HTTP and waste of bandwidth concerns. However, it seems to trigger mor Content Security Policy issues than the previous SVG.

The SVG file has it’s own declared size, but when included in HTML, the media query size is based on the proportions of the DOM node in the HTML –. it reflect thespace provided to it.

Open the first SVG file or the second SVG file in your browser, then grow and shrink your browser window. As the window grows and shrinks the image the SVG displays changes. The image size appears to stay the same — because it is the same. In the SVG, all the images to have the same dimensions. Its when we include the SVG in a flexible layout that the magic happens. You’ll note that the first time you load the second one there may be flickers of white as the browser requests the next required PNG.

When you include the SVG in your HTML <img> with a flexible width, such as 70% of viewport, as you grow and shrink the container, the image responds to the changes. The "width" media query in the SVG is based on the element width in which the SVG is contained, not the viewport width.

I have included the first SVG and the second SVG so you can see SVG with both foreground and background images. These foreground images work perfectly in Opera. In Chrome and Safari, I need to open the SVG file first, after which the HTML file containing the foreground SVG image works perfectly*. In Firefox, the SVG works. Firefox supports SVG and supports SVG as background image, but blocks the importing of external raster images due to their content security policy (CSP).

The content security policy does make sense: you don’t want a file to be pulling in untrustworthy content. SVG technology is supported. It is just being prevented from pulling in external raster image. Firefox prevents it altogether. Safari and Chrome work if the SVG is preloaded. We can work with the browser vendors to get this CSP lifted.

The browsers do all support the media queries with the SVG. They all support SVG as foreground or content images. They all support SVG as background images. The support just isn’t all the same.

Responsive SVG for foreground images works. It simply works right out of the box. For background images, it works, but I am still tweaking the code to make the background responsive (in Chrome it works if background-size is declared, but Opera and Safari are using the declared SVG size as the image size… still working on combinations that work everywhere.)

The drawback of the first SVG is that the SVG file is making 4 http requests. So, while we are displaying the right image, we are not saving bandwidth. In the second, the raster images are background image. Only the required image is downloaded.

Another pro for this technique: similar to how we separate content from presentation from behavior: this method enables us to also separate out images — all the logic is in the SVG image instead of polluting our CSS or HTML.

With <object> tag: up Next

<object> can take care of Content Security Policy drawback we see with <img> that disallows the importing of images or script into an <img> file. <object> allows both. I am working on that angle now.

The main question is: should we attempt this with <object>, or should we get browser vendors to change their content security policy?

Note:

* Interestingly, the SVG works best when the raster images are pulled cross domain rather than same origin. You would think, with CSP, it would be the exact opposite.

Death by 1,000 Cuts

Anita Hill was telling the truth. How do I know she was telling the truth? Because what she accused Clarence Thomas of was, in many people’s eyes, inane. He made a really, really bad sexual joke. Something to the effect of “That looks like a pubic hair in your coke.”

Anita Hill was offended. I wouldn’t have been offended. You might not have been offended. But Anita Hill was.

It is not our role to tell others that they are wrong in finding something offensive. What makes them wrong and me right? My upbringing, life experiences and religious beliefs are different from yours. Our senses of humor and tolerance levels for potty humor, puns and racist humor are likely different as well. My tolerance level for off-color humor also differs by who is delivering the “joke”. If Carlos Mencia and Dick Cheney make the same joke, I may find one funny and the other completely offensive: intention of the speaker matters.

Adria Richards was telling the truth. There is no doubt about it. The persons she accused of making offensive jokes admitted to making at least some of the jokes. They were sexual jokes. Not sexist jokes. She was offended.

Did she handle it the way you or I would have handled it? Unlikely. You may have laughed at the joke. I might have turned around and glared at them. Pat (I am using gender neutral, imaginary people.) may have asked them to tone it down. Chris may have reported it to the conference organizer. Adria chose to tweet it.

Whether or not we would be offended doesn’t matter here. She was offended, and that is what matters.

Most people’s gut reaction may not be to tweet it. Most people rationally arguing against Adria’s handling of the situation state that she should have turned around and asked them to stop, or, if she was fearful of their reaction, to speak directly with the conference organizers. Both of these would have been good reactions — likely better reactions — but this is not what happened.

Let’s dig deeper into why it didn’t go down like this.

For most men, this may be the first time they hear of someone being reproached for making sexual jokes. For many women in the tech industry, they’ve either reproached someone for making a sexual joke, or consciously made a decision to “not make a fuss.” Just because the person sitting in front of you doesn’t give you the death stare, doesn’t mean they’re not offended, they don’t find your jokes inane, or they just want you to shut up so they can hear the speaker.

We know the dongle joke happened. There is debate about whether the forking joke happened too. Whether or not the forking joke happened or not doesn’t really matter in this story. Since the reaction was based on hearing a forking sexual innuendo joke, a joke was heard whether or not it was intentionally made.

This is not the first time a “private” offensive joke has been overheard. If others can hear you, like when you’re on your cell at Starbucks, it’s not private. The first few times we let such things slide. The next few times we give a “if looks could kill” stare. The next few times, we inform the perpetrator that we’re offended. For the comedically inclined, the next few times we mock the perpetrator. The next few times we ask them to shut up. The next time we tweet.

So, when you want to argue that she just should have asked them to stop making jokes she found offensive, how many times do we have to ask boys to behave?

I vividly remember when I was three years old I asked my black baby-sitter how come her hands didn’t get clean when she washed them. Most of you may think it’s OK for a three year old to ask that question. Some people think it is kind of cute. It’s not.  If you have sensitivity outside of your own life experience, you may find it mildly offensive. It is offensive. Can you imagine being that baby sitter and having to answer questions like that every day of your life, in every one of your jobs, not just from 3 year old children. It’s tiresome when you’ve heard it 1,000 times.

Let me reiterate: when I asked the question one time, it doesn’t seem racist. When my babysitter was being asked the same question for the 1,000th time, it felt racist.

It’s tiresome when you’ve heard inappropriate sexual jokes in a professional setting 1,000 times. It’s ‘Death By A Thousand Cuts’. At some point the micro-aggression kills your spirit.

Adria was tired of confronting directly. Many people argued “why didn’t she just confront them.” Is that our job? How many times do we have to repeat this chore?

Many people are too scared to confront people. When was the last time you confronted a mother who was smacking her child? Or a police officer who was harassing a black teenager? Why do people think it’s OK for them to insist that Adria have confronted the men behind her when they themselves don’t confront when they’re offended.

Some argue she should have told the organizers directly. She should have left her seat, and the session, to find the organizer to make a formal complaint, missing the session she wanted to hear, instead of Tweeting?

She posted a picture to Twitter, with the facts as she saw them, and the hashtag #PyCon. That is a perfectly reasonable thing to do if you think about it. It might not be what I would have done. It might not have been what you would have done. But it is what she chose to do. It worked. The conference organizers knew exactly what was going on and exactly who was involved immediately, and immediately dealt with the situation. It was effective.

PlayHaven chose to terminate one of their employees.  They didn’t post their reasons online. This is NORMAL. Companies are not supposed to divulge when or why they terminate an employee. (They later posted a clarification, but no identifying information).

If they chose to terminate their employee based solely on the PyCon interaction, I think they sorely over reacted. Perhaps they terminated the employee not for the joke but for the fact that he was being paid to learn at a conference and instead was bantering: not paying attention and hindering those around him from paying attention.  A lot of people goof around at work and at conferences, so that might be an over reaction for some work environments. For others, that might be an expected reaction.

The man who was terminated chose to post the experience on HackerNews. To me, that is a TOTAL overreaction. To you that might be a normal thing to do.  This is definitely not what I would have done, but it is the option he chose.

He apologized, which I think was awesome. I just don’t think HackerNews, being a troll Eden, is a place to post personal information about yourself or others.

Then a shit storm blew up.

No one at PyCon is to blame for this fiasco. Bad jokes were made, but unless we start firing people for puns (which I sometimes think we should, but that’s just me hating on puns), there was no fire-able offense there. I am purposely not using their names since I don’t think there should be a witch-hunt there. Adria was offended. I am using her name, since her name has already been thrown out there beyond recapture. The organizers handled the situation very well and didn’t publicize.

So, who is to blame? I don’t think it really matters anymore. All I know is that this week has been horrible. It all started because of an off-color sexual joke. There was nothing sexist, and no one was accused of sexism. But the reaction was sexist, racist, homophobic, misogynistic and outright hateful.

I know so many people who had a hard time sleeping this week. I know several who love the web, love their profession, love what they do and the people they code with who have fallen out of love this week.

It doesn’t matter if you like Adria or you don’t like Adria. For most of you reading this, you’ve never met her. Why and how do you even have an opinion on her? Because of a coward using a fake name on a Change.org petition? Because of a conference organizer who respected Adria enough to invite her to speak repeatedly, but decided to hash their issues out in public several years later?

Every time I get an alarming story on Facebook I check Snopes.com to see if it’s true. In this case we have one-sided stories. Adria is rightfully staying out of the spotlight. So, we really only do have hearsay to go on. We don’t have a Snopes. We shouldn’t be formulating opinions.

Who should have been professionally disciplined? How about the SendGrid sysAdmins who couldn’t handle a DDoS attack? Seriously! SendGrid focused on the wrong staff people when their site went down. Even Adria’s site stayed up. CloudFlare anyone? How about the SendGrid CEO for publically terminating an employee. That is completely inappropriate.

But the real culprit is the anonymity of the Internet. Privileged people from their parent’s basement think they can say anything. Some stated it was illegal for Adria to post the picture on Twitter, followed by posting “rights reserved” pictures from her flickr stream. They felt they could threaten her and bully her, then threatened lawsuits when called out. They can tweet, but we can’t call them out on their hateful speech?

4Chan, Reddit, HackerNews? They are not fact checked. They are not safe places.

I just hope that all the people who suffered hundreds of cuts this week — a cut for each sexist, racist, homophobic, xenophobic, misogynistic and outright hateful tweet, article, and comment — heals before they lose faith in our industry and in our society.

Pseudo or not-so-pseudo Click Mobile Events

When you ‘click’ with your finger there is no ‘right click’ event. Because of this, mobile devices react when you hold and click instead. Because there is no keyboard, mouse or right click, mobile browsers have some built in behaviors.

Tap Highlight Color

There is no such thing as hover on a touch device. Because of this, we have link tap highlight color which we can control with tap-highlight-color. You can style the highlight color to match your design. While the value transparent will get rid of the often-times unsightly effect, remember that removing the appearance of a tap effect negatively impacts accessibility.

#content a {
  -webkit-tap-highlight-color: #bada55;
}
#game a {
  -webkit-tap-highlight-color: transparent;
}

The above would make the background of any link #bada55 in our content, except for the links in the game board, which would show no effect on tap, other than the ones we controlled separately.

Kill the Selection Dialog

When you touch and hold on text copy, or touch and drag, you may have noticed the appearance of a selection diologue allowing you to copy or define the selected text. You can control this in WebKit browsers with:

-webkit-user-select: none;

When user-select is set to none on a DOM node, like a paragraph or even the <body>,  no copy/define selection dialog will appear.

The pointer-events: none; property / value pair is inappropriate in some settings, like games. While it prevents the user from getting the copy/define dialogue, it would also prevent any other touch events from occurring on the user-select targeted DOM node.

Kill the Images Dialog

Similarly to the selection dialog above, when a user touches and holds an image an image save / copy panel appears.

img {
  -webkit-touch-callout: none;
}

Adding touch-callout: none; to all images will ensure that no image dialog appears when images are touched.

For best user experience and accessibility, do not use the above CSS properties in content sites. The above should be reserved for games and other entertainment, productivity and tool applications.

Kill panning

Sometimes you don’t want your users to accidentally pop up an operating system menu. With CSS you are able to disable panning. You don’t want to completely disable panning all the time, but you can use touch-action: none; to prevent accidental panning if accidental panning is likely to occur.

.active #game {
  -ms-touch-action: none; /* disable panning */
}

You might be thinking “why not just use JavaScript’s preventDefault();. You could likely get that to work. However, using the four CSS properties above performs better than preventDefault(). CSS is almost always more performant than JavaScript. And, in this case, there is up to a 400ms lag in firing touch events, so it’s best to prevent the panning, dialoging, etc., before it ever happens.

Web Development Tips

My Twitter account, WebDevTips, has been reactivated. Follow @webDevTips to get (almost) daily Web Development tips in your timeline.


Register to vote for the 2012 Presidential Election

Download the National Voter Registration form (PDF)

Below is a list of all the states, with links to more information about voting in that state. We’ve included information about voter registration deadlines, with what that deadline is for 2012 presidential election. This information is what we garnered to the best of our knowledge, but don’t trust it. Look it up your self. The right column has links to registration forms and online applications.

If you find any errors, please visit http://github.com/estelle/vote and do a pull request.

 

State
(voter information)

Voter Registration Deadline 2012 General Election Deadline Register
(links to application forms or online forms)
Alabama Voter registration is closed during the 10 days before an election. Applications must be postmarked or delivered 11 days prior to the election. October 26, 2012 Register to vote »
Alaska Received 30 days before the election More information » October 6, 2012 Download application »
Arizona Postmarked 29 days before the election October 9, 2012* Download Application »
Arkansas Postmarked 30 days before the election October 6, 2012 Download Application »
California Postmarked 15 days before the election October 22, 2012 Register to vote »
Colorado Received 29 days before the election.  If received in the mails without a postmark, it must be received within 5 days of the close of registration. October 9, 2012* Register to vote »
Connecticut

Postmarked 14 days before the election (by mail).

Received 7 days before the election (in person)

October 23, 2012 (mailed).

October 30, 2012 (in person)

Download Application »
Delaware

Postmarked by the 4th Saturday before the election.

Postmarked 10 days before for a special election

October 13, 2012 Register online »
District of Columbia

Postmarked 30 days before the election.

You can register in person on Election Day if you can prove residency.

October 9, 2012 (by mail)*

November 6, 2012 (in person)

Register online »
Florida Postmarked 29 days before the election October 9, 2012* Download Application »
Georgia Postmarked by the fifth Monday before the election October 6, 2012* Register online »
Hawaii Received at least 30 days before the election October 8, 2012 Download application »
Idaho

Postmarked 25 days before the election

You may also register in person on Election Day.

October 12, 2012 (by mail)

November 6, 2012 (in person)

Download application »
Illinois

Postmarked 28 days before the election

There is "Grace period" registration up to 3 days before the election

October 9, 2012 Register to vote »
Indiana Postmarked 29 days before the election October 9, 2012 Register online »
Iowa

Postmarked 15 days before an election (by mail).

Received 10 days before General and Primary Elections (in person).

Received 11 days before all other elections (in person).

You may also register in person on Election Day.

October 22, 2012 (by mail)

October 27, 2012 (in person)

Download application »
Kansas

Postmarked 15 days before the election xxx

October 16, 2012 Register online »
Kentucky Postmarked 29 days before the election October 8, 2012 Download Application »
Louisiana Received 30 days before the election October 7, 2012 Vote Online »
Maine

Received 21 days before the election if by mail, but you can register in person upto and including Election Day.

October 21, 2012 (by mail)

November 6, 2012 (in person)

Download »
Maryland Received by 9:00 pm, 21 days before the election. October 16, 2012 Register online »
Massachusetts Postmarked 20 days before the election. October 17, 2012 Download »
Michigan Postmarked 30 days before the election October 9, 2012 download »
Minnesota

Received 21 days before the election.

You can register in person on Election Day with proof of residency.

October 16, 2012 (by mail)

November 6, 2012 (in person)

Download »
Mississippi Postmarked 30 days before the election October 6, 2012 Download »
Missouri

Received 5pm or the normal close of business 28 days before the election

October 10, 2012 Register to vote »
Montana

Postmarked 30 days before the election (by mail).

You may also register in person at the County Clerk’s office up to – and including – Election Day.  

October 9, 2012 (by mail)*

November 6, 2012 (in person)

Download »
Nebraska

Postmarked the third Friday before the election (by-mail) or by 6pm on the second Friday before the election (in-person).

October 19, 2012 (by mail).

October 26, 2012 (in person)

Download »
Nevada

Postmarked by the fifth Saturday before the election (by mail) or until 9:00 p.m. on the third Tuesday before the election (in person) by appearing at the office of the County Clerk/Registrar of Voters.

October 16, 2012 Register online »
New Hampshire

Received 10 days before the election (by mail).

You may also register in person on Election Day.

October 27, 2012 (by mail)

November 6, 2012 (in person)

Absentee ballots » or go in person
New Jersey Received 21 days before the election October 16, 2012 Register to vote »
New Mexico Postmarked 28 days before the election October 9, 2012* Get more information » or go to county clerk’s office
New York

Postmarked 25 days before the election. 

October 12, 2012 Register to vote »
North Carolina

Received 25 days before the election (by mail)

You can also register in person and vote early during the “one-stop” voting period 55 days before the election (55 days? WTF!)

October 12, 2012. (by mail)  

You can also register in person and vote early during the “one-stop” voting period from October 18 – November 3, 2012.

Download »
North Dakota North Dakota does not have voter registration Show up on election day. Does not have voter registration
Ohio Received 30 days before election.  October 9, 2012* Register to vote »
Oklahoma Postmarked 25 days before the election October 12, 2012 Register to vote »
Oregon Postmarked 21 days before the election October 16, 2012 Register online »
Pennsylvania Received 30 days before the election October 9, 2012 Download »
Rhode Island

Received 30 days before the election.

Supposedly you can register in person on election day, but only for Presidential elections.

October 6, 2012 (by mail)

November 6, 2012 (in person)

Register to vote »
South Carolina Postmarked 30 days before the election October 6, 2012 Download »
South Dakota Received 15 days before the election October 22, 2012 Download »
Tennessee Postmarked 30 days before the election October 6, 2012 Register to vote »
Texas Postmarked 30 days before the election October 9, 2012 Register to vote »
Utah

Postmarked 30 days before the election (by mail) or 15 days before the election (in person and online)

October 9, 2012 (by mail)*

October 22 (in person or online)

Register to vote »
Vermont Received 5pm on the Wednesday before the election October 31, 2012 Download »
Virginia Received 29 days before the election October 15, 2012 Register to vote »
Washington

30 days before the election or 15 days before the election if delivered in person to the local voter registration office

October 6, 2012 (by mail).

October 8, 2012 (online).

October 29, 2012 (in person)

Dowload »
Register online »
West Virginia Postmarked 21 days before the election October 16, 2012 Download »
Wisconsin

Postmarked 20 days before the election, or the day before by 5:00 pm if handed in in person.

You may also register in person on Election Day.

October 17, 2012 (by mail)

November 6, 2012 (in person)

Register to vote »
Wyoming

Does not accept the national voter registration form. State form must be received 14 days before the election.

You may also register in person on Election Day.

October 22, 2012

November 6, 2012 (in person)

Register to vote »
Download the Forms

Make Twitter DMs appear as if read in all browsers

Edited July 5, 2015

While the DMs no longer appear unread forever (thanks for the fix, Twitter), the ads are still annoying. Simply drag the Add Killer link to your tool bar and click when necessary.

————————— End Edit —————————

I use Twitter.com to access my tweets. I do so from several different computers and several different browsers on each of those computers. Since Direct Messages read/unread status is stored in local storage, I have to ‘read’ my DMs in every browser on every computer to make them appear read in each of those browsers. I hate that.

What I hate even more is that I have to click on my account drop down, then on direct messages link, then I have to individually open each DM thread to make them appear read, and back out of it before clearing the next.

This was driving me crazy. So, I created a little bookmarklet. I simply added the bookmarklet to each of my browsers. Now, whenever I see that little blue glow I simply click on the little bookmarklet, and the blue glow disappears until I actually get a new DM.

You can get the bookmarklet from my Github

This bookmarklet will mark all of you Twitter direct messages as read simply by deleting the entry in local storage.

The Code:

//Get the URL
var urlistwitter=window.location.href.split('/')[2].split('.'); 

// Check to see if the domain is twitter
if(urlistwitter[urlistwitter.length-2]==='twitter') {

   // remove the local storage item of unread DM references
   window.localStorage.removeItem('dm_threads');
}

// remove the icon that makes them appear unread
document.querySelector('#user-dropdown-toggle .nav-new').classList.remove('nav-new');

Drag this link to your toolbar. When you need to, click it when your Twitter window has focus to remove the localStorage entry and that annoying blue ‘unread’ icon:

Mark DMs as Read

details and summary polyfill

var summaryClick = function(elem){
  if (!('open' in document.createElement('details'))){
    var deetails = elem.parentNode;
    if(deetails.hasAttribute('open')){
     deetails.removeAttribute('open');
    } else {
     deetails.setAttribute('open', 'open')
    }
  }
}

add the summaryClick to your <summary> click event listeners

And then in my CSS I put something similar to:

details:not([open]) {
   height: 2em; 
   overflow: hidden;
}
details[open]  {
   height: auto;
}
summary::before {
   content: "▶ ";
}

Only browsers that understand the JS used will understand the selectors used. So, this isn’t fool proof, but it’s nice, quick and dirty.

SpeciFISHity: CSS Specificity

Some people are confused by CSS Specificity, especially with all of the (not-so) new CSS3 Selectors. The image below may help make sense of CSS Specificity.

X-0-0: The number of ID selectors, represented by Sharks
0-Y-0: The number of class selectors, attributes selectors, and pseudo-classes, represented by Fish
0-0-Z: The number of type selectors and pseudo-elements, represented by Plankton a la Spongebob
*: The universal selector has no value

Download the specificity chart and read the rest of the SpeciFISHity article here