Re: Tabbed Interfaces in CSS

On Apr 22, 2009, at 7:51 AM, "Tab Atkins Jr." <jackalmage@gmail.com>  
wrote:

> On Tue, Apr 21, 2009 at 9:20 PM, Brad Kemper <brad.kemper@gmail.com>  
> wrote:
>> On Tue, Apr 21, 2009 at 3:44 PM, Tab Atkins Jr.  
>> <jackalmage@gmail.com> wrote:
>>> How would this work?  Given the following markup:
>>>
>>> <fieldset>
>>>  <legend>foo</legend>
>>>  <div>card one</div>
>>> </fieldset>
>>> <fieldset>
>>>  <legend>bar</legend>
>>>  <div>card two</div>
>>> </fieldset>
>>> (You can alter the markup if necessary to better match your  
>>> proposal.)
>>>
>>> What CSS would your proposal require,
>>
>> Slightly modified from the first time I sent it:
>>
>> fieldset { radio-group:mytabs; appearance:tab-card; display:inline- 
>> block;
>> position:absolute; left:0; }
>> fieldset:not(:checked) { appearance:none; 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; display:inline- 
>> block; }
>>
>> See below for an explanation of each line and how it would affect the
>> rendering...
>
> ...snip explanation...
>
> That seems to depend a *lot* on very undefined behavior for the
> appearance property, which *shouldn't* have anything to do with
> behavior at all.  As Giovanni says, appearance is just a shorthand way
> of saying "set all these properties so that the element looks like X
> widget in the UA".

The main part of the proposal was about allowing a :checked state on  
other elements, to allow such things as tab behavior. Setting the  
appearance to look like a tab was not a requirement to get this  
behavior, just as a quick way for setting the visual style (and for  
making the example brief). As I mentioned, I'd hoped it might also  
take care of the alignment of one tab with another, but this was not a  
critical part of the proposal.

> You're relying on appearance to group tabs,

No, I wasn't. I proposed a new property called 'radio-group', that  
would accept an identifier. Any other element with the same identifier  
would be part of the same group.

> move them around the page,

I only said the it would be helpful if appearance could take care of  
the horizontal positioning to prevent improper overlap with a previous  
tab of the same group (some OS might prefer a certain amount of  
overlap or margin for it's tabs). But the propsal does not require it,  
and I mentioned a couple other ways to deal with that horizontal  
positioning of the tabs that could be used if appearance was not, or  
if appearance could not be made to work that way.

> and defeat a display:none applied to their parent.

I suggested no such thing.

>  In addition to all
> this behavior, it presumably applies a UA-default style to the tabs,
> and possibly cards, making it difficult/impossible to restyle them as
> desired.

No, applying the UA-default style would be the primary reason to use  
appearance. It would not be required. I could have given a sample with  
padding, border, margin, background, etc. But thought it would not be  
as clear and consise for an example for what I was trying to  
illustrate with the example. What I was trying to show was how a  
checked state could work for creating a tabbed interface, not to show  
all the ways a tab could be visually styled. Appearance could take  
care of the visual style (and theoretically the left positioning) in a  
much more concise way, provided you could use it to provide the  
diffent looks of a tab (front/selected, back/non-selected, top, side,  
bottom, etc.).

> It seems like Template Layout could solve this much more easily and
> extensibly, actually.

More easily than what? I did mention template layout as a method for  
handling the right and left positioning of the tabs.

> form { display: "a" "b"; }
> fieldset:not(:checked) { display:none; position:b; radio-group:my- 
> tabs; }
> fieldset legend { position:a; /* insert generic tab styling here */ }
> fieldset:checked legend { /* style the active tab */ }
> fieldset:not(:checked) legend { /* style the inactive tabs */ }

So you are basically agreeing with my main points. The styling you  
left out could be provided by appearance or my setting borders, etc.  
yourself, which is what I always said. The main changes I proposed  
(:checked elents other than inputs, and radio-group to group the  
selection behavior) are there. It seems like you are trying to argue  
with me, but your argument shows general agreement.

> The only potential problem is the display:none.  It hides the element
> and *all* children.

That's why I didn't do it that way. Just give it no height and width  
and no other styling that would be visible.

>  I presume that Template Layout doesn't interact
> with normal inheritance, so it would still cause problems.

I would not assume any changes in inhertance rules.

> You use
> appearance:none to address this issue in some unspecified way, but
> perhaps there's another way to say "hide the element and static-flow
> children"?

I am only using that to hide the appearance of the fieldset. I used  
the universal selector to hide it's children (as I explained), and  
then a legend selector with the same specificity to show that one  
part. You could just as well use the 'not' pseudo-class to hide all  
but the legend. A fieldset with no border, padding, or visible style,  
and no visible children except the legend gets me just what I was  
looking for.

> That seems useful to me in general - it would allow abspos
> elements who live outside of the parent anyway to possible stay
> visible.

Perhaps, but not required for this.

>>>> Yours requires a link behaviors spec to prevent unwanted
>>>> scrolling (or that people find it acceptable for clicking on a  
>>>> tab would
>>>> scroll the page).
>>>
>>> Maybe.  It's also possible that it just includes magic which would  
>>> fix
>>> the issue.  This magic also has the benefit of eventually being
>>> translatable into proper rules if Link Behaviors gets properly  
>>> adopted
>>> (and has this ability) - a simple ":tab{target:no-change;}" (or
>>> whatever) added to the UA default stylesheet would do it.
>>
>> Fair enough. I was trying to minimize magic-reliance in mine, but  
>> for the
>> best effect I have a little for appearance to do, or a reliance on
>> floating-to-a-named-spot-type-of-thing, or else a somewhat less ideal
>> presentation (see last part of my tabs example explanation).
>
> Floating to a named spot is more-or-less covered by template layout
> now, and can be done as I outlined above.

Fine. There are more than one way to skin a cat, and what I am  
proposing does not insist on one way or another for the positioning of  
the tabs themselves, although some ways would be handier than others,  
or have other advantages.

>  I find it much preferable
> to hacking appearance into doing this.

I do not consider it a hack that tab appearances can set some sort of  
'min-left' on itself internally to get the proper OS tab alignment  
with other tabs in it's group. But I do not require that; it would  
just be an appreciated nicety.

>>>> Mine has neither of these requirements, but just extends
>>>> an existing pseudo-class to more elements, and adds a couple  
>>>> properties
>>>> to
>>>> indicate radio groups and for defaults.
>>>
>>> But without some magic generation of tabs from card content, it has
>>> bad fallback behavior.
>>
>> Nope. Good fallback behavior is its best quality. It only prefers a  
>> little
>> magic for lining up the tabs, or using one of the other proposals  
>> for moving
>> things around. It might even be able to use template layout for  
>> that. So
>> magic is not an absolute requirement.
>
> Yes, once you've added the ability to extract tabs from the cards
> (solving the issue of hiding the card without hiding the extracted tab
> in the process), then fallback is just fine.

I did solve that in every example I provided, even the earliest version.

>  It still has bad
> fallback when you're doing a more complex tabbed layout with the tabs
> defined outside of the cards, though (which is why I based my proposal
> on links, which are still good in this case).

Only insomuch as if someone wants to put a defacto label far from the  
element it is labeling, I do notprevrnt you from doing so. If you want  
to put the label inide an anchor or vice versa, you can do that too.

> This can potentially be
> patched.
>
> ~TJ

Received on Wednesday, 22 April 2009 18:31:26 UTC