Re: Tabbed Interfaces in CSS

On Apr 20, 2009, at 10:31 AM, Brad Kemper wrote:

>
> On Apr 20, 2009, at 10:19 AM, Tab Atkins Jr. wrote:
>
>> On Mon, Apr 20, 2009 at 12:15 PM, Brad Kemper  
>> <brad.kemper@gmail.com> wrote:
>>>
>>> On Apr 20, 2009, at 9:51 AM, Tab Atkins Jr. wrote:
>>>
>>>> However, you can only have a
>>>> single accordion per page (to be precise, all the accordions will  
>>>> act
>>>> like one big distributed accordion) and if you try to use a hash- 
>>>> link
>>>> for anything else on the page it will close the accordion.
>>>>
>>>> In other words, it suffers from the exact same problems that I
>>>> outlined for my pure-CSS tabbed display.
>>>
>>> With my pure-CSS tabbed display, you could have more than one set  
>>> of tabs
>>> per page.
>>
>> Yes, but it suffers from tab display problems.  Unless you can  
>> arrange
>> your html to alternate tab-card-tab-card (so that a given tab and  
>> card
>> can both use the same radio element for :checked targeting),
>
> It feels pretty natural to me to have the LABEL surrounding the  
> element (like input labels often do), or just inside the element  
> (like table captions or fieldset legends), instead of in a separate  
> box. But with the "for" attribute of LABEL, it seems like you could  
> have it both ways.

And actually, the more I think about it, the more appropriate I  
believe it is to have the "tab" near or within the "card" it is  
associated with. You have to consider that without styling the HTML  
should still make sense, and it doesn't so much if all the labels for  
each card are separated from the blocks representing the cards.

My idea is that if anything can have a "checked" state or not, then  
you could have several fieldsets, for instance, and style them  
something like this:

fieldset { radio-group:mytabs; appearance:tab-card;  }
fieldset:not(:checked) { appearance:none; position:relative; z- 
index:-1; }
fieldset:not(:checked) * { display:none; }
fieldset:not(:checked) legend { appearance: tab-top-back;   
display:inline-block;  }
fieldset:checked legend { appearance: tab-top-front; }

And that would be pretty much all it took to turn a few fieldsets into  
set of tabbed panels. This only requires a tiny amount of magic, in  
that the "appearance: tab-top-back" and "appearance: tab-top-front"  
would be responsible for the left-to-right positioning of the tabs in  
that group. Otherwise, you would need something like named flows[1] to  
move them into an area just above the first fieldset where they could  
naturally flow one after the other.

If "checked" on one of the fieldsets was not set in the HTML (perhaps  
for conformance reasons), then the default state would be for the  
first child of any radio-group to have a default checked state. To  
have a different item in a default checked state, then we could have  
something like this:

fieldset:nth-of-type(2) { default-checked:checked; }

Which would be useful for this if the markup language did not allow  
"checked" attributes on anything but inputs, but could also lead to  
changing the default checked state of inputs via CSS, which might be  
going too far (but the rest of this proposal does not depend on this  
last property). Otherwise, presentation is clearly separated from  
content, because without the styling the fieldset/legend markup still  
has the same meaning as before (as would table/caption, div/h3, etc.).

Note that with a little leeway on the FOR attribute of LABEL, you  
could put all the tabs together in one place, with the "card" DIVs (or  
Ps or whatever) they reference below the whole group of labels. Then  
you'd have something like this instead:

.tabcard { radio-group:by-class; appearance:tab-card;  }
.tabcard:not(:checked) { appearance:none; position:relative; z- 
index:-1; }
.tabcard:not(:checked) * { display:none; }
label { appearance: tab-top-back;  display:inline-block;  }
label[for=*:checked] { appearance: tab-top-front; }

For label to work this way, I am adding a pseudo-class to the  
attribute value, so that if the value matches in the attribute  
selector then it treats that value like an ID that can have the pseudo- 
class of that ID matched too (not yet allowed in current CSS 2 or 3).

On Apr 20, 2009, at 9:23 AM, Tab Atkins Jr. wrote:
> Frex, would
> clicking on an element alter the :checked state for all ancestors of
> the clicked element as well?

So, in the model described above, the answer would be yes. Clicking on  
the LEGEND would change the :checked state of its FIELDSET.


[1] http://www.w3.org/TR/2006/WD-css3-gcpm-20060612/#named0

Received on Tuesday, 21 April 2009 16:49:00 UTC