Blog

Posts tagged with “code” and “HTML”

Mobile Browsers lost their :FOCUS

 

Alright,
I had been hoping to display a CSS user interaction technique that would make context sensitive drop-down menus, but it unfortunately doesn't work on current mobile phones (webkit based ones, at any rate). The problem is the mobile browsers don't recognize :FOCUS on any element other than text entry areas.

See, according to W3C's HTML5 recommendation (and implemented in all modern desktop browsers), any element can receive user focus if they have a "tabindex" attribute assigned to them. If that value is a positive number, they then also enter the tab sequence for keyboard navigation. It also means that, in desktop browsers, clicking on the element allows the client to render special :FOCUS selector, that is normally reserved mostly for form elements and links. With a little bit of work, one can create a nice little context menu as follows:

HTML:

<div tabindex="1" class="opt-sel">Options
  <ul tabindex="0"><!-- this needs a tabindex too, to allow styling it's :ACTIVE state to allow for a complete "click" of it's children -->
    <li><a href="#1">Option 1</a></li>
    <li><a href="#2">Option 2</a></li>
    <li><a href="#3">Option 3</a></li>
    <li><a href="#4">Option 4</a></li>
  </ul>
</div>

CSS (the effective bits):

.opt-sel UL {
   position:absolute;
   list-style:none;
   padding:0;
   margin:0;
}
.opt-sel:NOT(:FOCUS) UL { /* only hide the sub-menu in modern browsers */
  display:none;
}
.opt-sel:FOCUS UL,
.opt-sel UL:ACTIVE { 
/*
A child element's mousedown event causes said element to pull focus away 
from the parent div and disappear immediately, and disables any "click" 
from occurring. Styling the UL's :ACTIVE state keeps the child elements 
around until mouseup, and lets the click happen.
*/     
  display:block;
}

And, on desktop browsers, this works great. Click on the word "options", and a list of options appears and stays open until you click somewhere else. If you click one of the available options, the desired action occurs and the list nicely disappears. Now, it's not perfect — you can't tab through the options, for example (though, you should be able to) but it's no worse than current :HOVER menus.

Now, one would expect this to work beautifully on a touchscreen/mobile environment. Unfortunately it doesn't. Instead, what happens is clicking (or touching) on a tabindex'ed element results in the rendering of a :HOVER selector — :FOCUS is completely ignored. Not only that, but :FOCUS doesn't even effect the usual suspects. Only elements that accept keyboard interaction are allowed to use :FOCUS state — and only when they do need a keyboard; setting readonly="readonly" removes the :FOCUS state. I assume that the reason for this is that many pre-mobile site's navigation systems broke when :HOVER disappeared. And it makes sense. Touch screens can't tell you if you're hovering, only if you're touching. So, instead of following standards, mobile browsers rewarded laziness, and changed the rules. Problem is, the only way to make something recognize :HOVER is by setting a tabindex value, which means it still won't be used by the lazy coders this change was trying to appease — and it hijacks the first click on an element to set :HOVER, requiring users to click (or touch) twice.

What should happen, in my opinion (and the W3C's as well, if I read the latest recommendation correctly) is that :HOVER should be ignored (or at least mimic :ACTIVE) on touch screens, since they don't use "pointing devices" and :FOCUS should work on any element that accepts tab navigation. Don't break things to appease lazy coding. That's what made IE6 and quirks mode happen to us.

Tags: , ,
2013.02.04 09:51 AM | Permalink 0 Comments

CSS3 Pie Charts Revisited

Quite a while back I figured out how to create pie charts using nothing but CSS and a handful of HTML tags.

In the original method, I used at least two nested elements to create each segment of the pie chart. Well, turns out I figured out how to make it use even less HTML. I now use BEFORE: and (occasionally) :AFTER pseudo elements.

<div class="pie" data-start="0" data-value="30"></div>
<div class="pie highlight" data-start="30" data-value="30"></div>
<div class="pie" data-start="60" data-value="40"></div>
<div class="pie big" data-start="100" data-value="260"></div>

The other thing I did differently with the HTML was to remove ID's for each element in favour of adding data- attributes. You could just as easily use class names like s30 and v30, but I will explain why I like the data attributes later. I was also able to remove the clip workaround to WebKit's now fixed changing an element's transform-position negates border-radius bug.

The technique remains essentially the same. for each piece; convert the inner element (or pseudo element in this case) into a half circle, and hide it from view by setting the outer element to overflow:hidden. Rotate both outer and inner elements to place and size the pie piece. For pieces larger than 50% of the entire pie's volume, use a second (pseudo) element as filler.

as for why I prefer data- attributes over classes, it's so I can complain about the lack of support for the proposed W3C CSS3 attr() function, which would make this technique truly awesome. Instead of creating custom style rules for each possible value of data-start and data-value, I could replace them with two rules:

.pie {
   transform:rotate(attr(data-start,deg,0);
}
.pie:BEFORE {
   transform:rotate(attr(data-value,deg,0);
}

Check out the code in action, or even play with it yourself on Code Pen

Tags: , , ,
2013.01.26 04:09 PM | Permalink 0 Comments

Stupid CSS Tricks: The Simple Sticky Footer

Ok, I've seen a lot of techniques for Sticky footers, but haven't seen one as simple as mine. It uses the bare minimum mark-up and CSS possible.

First, here is the HTML required:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Sticky Footers Rock</title>
<link rel="stylesheet" type="text/css" href="[where you store css]" />
<!--[if lte IE 6]>
<link rel="stylesheet" type="text/css" href="[where you store IE6 specific css]" />
<![endif]-->
</head>

<body>
<div id="header"></div>
<div id="content"></div>
<div id="footer"></div>
</body>
</html>

As you can see, there's nothing special in there. Besides the conditionally commented IE6 stylesheet, there are three DIVs to split the layout, and that's it. Nothing a decent web designer wouldn't already have in a page anyway. In fact, only two of those DIVs are required. The "header" DIV is only there because it usually exists in a design. It's superflous to this example. One thing that is vitally important though — assuming you care about IE6 — is the <!DOCTYPE> decleration. What doctype you use is up to you, so long as it triggers "almost standards mode" in IE6.

Next we will look at the base CSS required. You can add more as you see fit. I've commented the code to explain why each line needed:

HTML {
height:100%;
/* allows body to grow to full window height */
}
BODY {
position:relative;
/* otherwise footer will position itself in relation to window height */
min-height:100%;
/* makes page start out at least as tall as the browser window */
margin:0;
padding:0;
/* not strictly required but useful. reset to push body to edges of browser window */
}
#footer {
position:absolute;
bottom:0px;
/* these two lines will force footer to the bottom of the page. */
height:XXX;
/*set to whatever you want */
}
#content {
padding-bottom:XXX;
/* must match or exceed the footer height, so bottom-most content doesn't float bellow footer */
overflow:hidden;
/* this will contain any floated elements and push the footer down below them
NOTE: do not add a height to this element, or this will fail */
}

Next, we add a single rule to the conditionally commented IE6 stylesheet:

BODY {
height:100%;
/* hack for IE6 that doesn't recognize min-height. */
}

That's it. We're done. Here's a demo with some minimal extra CSS and content to illustrate the technique.

One caveat with IE6: this will work as is on static content pages, but IE6 will not move the footer down when extra content is added or removed dynamically. Instead it will float where it originally sat regarless of the new content size. To work around this, simply pop the footer's style position to 'static' and back (either directly with <element>.style.position, or by adding then removing a new class) after making the dynamic changes and IE6 will behave as expected.

Also, some more knowledgeable of you may be tempted to skip the conditionally commented CSS and instead "hack" the original BODY rule decleration as follows:

BODY {
position:relative;
/* otherwise footer will position itself in relation to window height */
min-height:100%;
/* makes page start out at least as tall as the browser window */
height:auto !important;
/* make non-IE6 browsers ignore the next line */
height:100%;
/* hack for IE6 that doesn't recognize min-height. */
margin:0;
padding:0;
/* not strictly required but useful. reset to push body to edges of browser window */
}

While this will work, it does add unneeded CSS that other browsers need to parse. It's my personal oppinion that IE6 should be the only one doing heavy lifting, CSS wise, since it's the one we're having to work around.

Tags: , ,
2010.02.08 12:00 PM | Permalink 0 Comments