Re: Tabbed Interfaces in CSS

On Tue, Apr 21, 2009 at 3:44 PM, Tab Atkins Jr. <jackalmage@gmail.com>wrote:

> On Tue, Apr 21, 2009 at 5:21 PM, Brad Kemper <brad.kemper@gmail.com>
> wrote:
> > On Tue, Apr 21, 2009 at 2:52 PM, Tab Atkins Jr. <jackalmage@gmail.com>
> > wrote:
> >> On Tue, Apr 21, 2009 at 4:35 PM, Brad Kemper <brad.kemper@gmail.com>
> >> wrote:
> >> >> >> If tabs can be separated from cards in the markup, then I think
> the
> >> >> >> mechanism *has* to be link-target-based, so that it degrades into
> >> >> >> links to the appropriate section on the page, which is still
> >> >> >> sensical
> >> >> >> and somewhat useful.
> >> >> >
> >> >> > Using LABEL, with some small adjustments for the FOR attribute,
> would
> >> >> > also
> >> >> > allow that separation. Clicking on the label is like clicking on
> the
> >> >> > element
> >> >> > it either surrounds or is FOR.
> >> >>
> >> >> Nah, using <label> wouldn't degrade properly.  Without the CSS to
> >> >> control display based on the :checked state, you'd have a document
> >> >> with everything laid out, plus a couple of random section labels
> >> >> bunched together for no good reason.  The fact that there's a <label>
> >> >> wrapping them isn't obvious, and has no effect on the behavior of the
> >> >> page.  Links at least provide some useful functionality without the
> >> >> CSS - they'll direct you to the appropriate tab.
> >> >
> >> > It would be an authoring option for those who really want to be able
> to
> >> > write them all in one place, since there seemed to be a desire for
> that
> >> > on
> >> > this list. I prefer that they either wrap the item they are assoicated
> >> > with
> >> > (technically a no-no, since they are by default inlilne HTML
> elements),
> >> > or
> >> > are inside the item they are assoicated with (near the top), or that
> >> > headlines, captions, or legends (etc.) be used instead, since they
> would
> >> > naturally exist in existing layouts, in places where they label the
> >> > content.
> >>
> >> Can you give a markup example of exactly what you're proposing?  I'm
> >> really not understanding what structure you're trying to hint at here.
> >
> > Three fieldsets, each with a legend, could become a 3-tab panel using the
> > css example I provided earlier, with the  css changes I proposed earlier.
> > Did that not make it onto the mailing list?
>
> Ah, no, you did mention that, but it didn't seem significant enough
> for me to pay attention to, apparently.
>
> 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...


and what would be the expected
> rendering?  (I ask for this again just to ensure that I am absolutely
> comprehending your proposal properly.  I had the advantage of starting
> a thread with a formal proposal; yours developed somewhat organically
> within the thread.)  Make sure that there's a way to distinguish the
> active tab as well.


fieldset { radio-group:mytabs; appearance:tab-card; display:inline-block;
position:absolute; left:0; }

This first rule says that both fieldsets in your example are part of the
same radio group, given the identifier of "mytabs", and that they should
have the OS appearance for the display area of a tabbed display (an author
could specify their own style instead of using appearance if he wished). By
putting these into a radio group, the UA should track the "checked" state of
each one according to radio-button standards, not according to check-box
standards. By default, the first fieldset ("foo") has a "checked" state, and
any others ("bar") do not. The absolute positioning and the inline-block
display makes all the fieldsets appear at the same x/y coordinates.

fieldset:not(:checked) { appearance:none; z-index:-1; }

This second rule says that any of these fieldsets that do not have a checked
state would not have any OS appearance (including no shadows or borders in
OS X), and that they should be lower in the stacking order than fieldsets
with a checked state (an author might also want to explicitly remove any
borders, padding, etc. here that might be part of the default fieldset
styling).

fieldset:not(:checked) * { display:none; }

This third rule says that those non-checked fieldsets should not display any
of their contents. Combined with the previous rule, it means that only the
checked fieldset will be visible (but without using display or visibility on
the fieldset itself).

fieldset:not(:checked) legend { appearance: tab-top-back;
display:inline-block; }

These make an exception to the rule right before it: it allows the legend
element to be displayed (so far, only the unchecked version) and gives it an
OS appearance of an unselected ("back") tab of the variety that you see
along the top of a tabbed display. This is more specific than just
"appearance:tab", which does not seem to be enough to describe the different
states or positional types for tabs. Maybe there would be a better way to
indicate the appearance state, or maybe the UA would be able to figure this
out on its own as part of appearance magic, but I am trying to reduce the
reliance on magic. The author could also use non-appearance-based styling
here to indicate non-selected-tab instead, if he wished.

fieldset:checked legend { appearance: tab-top-front; display:inline-block;}

This is the actual tab for the tab that's in front. More appearance (or
other author-supplied styling) to indicate that it should look like a
clicked-on tab that goes on top of the box (not sides or bottom), and make
it display.

Now so far all the tabs are one above each other, instead of appearing in a
row. So the appearance would do some magic to set the 'left' of each
according to the intrinsic width of the one before it. Alternately, the
author who did not want to use appearance would have to rely on a different
spec for floating or moving the item to a different named location just
above the fieldsets. OR, less exotically but also less satisfyingly, the
author could just give each tab a set width and then set the left position
of each based on the width of the one before it, selecting each one via
':nth-of-type()' and LEGEND. This is the one place I have where some magic
is desirable, but there are other ways around it (such as using labels in a
way similar to my old pure-CSS example, if you have the option of editing
the source code).

Also, is there a way in your magic generation to handle both the tab
> and accordion cases?  The only distinction between the two is that the
> former collects the tabs together, while the latter distributes them
> with their card.


Accordion would be even easier. Imagine a div for each section of the
accordion, with a single H3 as the first child of each section:

div { radio-group:myaccordians; overflow:hidden; font-size:18px;
margin-top:2px; }
div:not(:checked) { height:1em; }
h3 { height:1em; background-color:black; color:white; }


<div>
<h3>Click me to open or close this div</h3>
<p>A bunch of text, etc.</p>
</div>
<div>
<h3>Me too!</h3>
<p>bla, bla, bla</p>
<p>More stuff to be hidden</p>
 </div>
<div>
<h3>Get the idea</h3>
<p>Hidable stuff for the third part</p>
 </div>



> >>> > Links are only one thing at a time, so using
> >>
> >> >> > them for tab-panel-showing would not allow a page with more than
> one
> >> >> > set
> >> >> > of
> >> >> > tabs to have a particular tab in the front.
> >> >>
> >> >> Hm?  I addressed this in my proposal.  Cards are *activated* by
> links,
> >> >> but they don't depend on links to *stay* activated.  The CSS engine
> >> >> would keep track of which card is active in each stack.
> >> >
> >> > Sorry, I guess I missed that you were adding more magic there. But
> then
> >> > there is no way to make one of the tabs other than the first as a
> >> > default,
> >> > other than by changing the URL to the page? And even then, only one of
> >> > the
> >> > sets of tabs could have a default?
> >>
> >> Right now, yes.  Is it important that a different tab than the first
> >> show as a default?
> >
> > Sometimes. Yes. Absolutely. Not as important, perhaps, but certainly
> > desirable.
>
>
> I suspect less often than you would think, especially when you
> consider that you can just make the default card be first in your
> markup.  The situations where you want a card to come first in the
> markup but *not* be the default displayed card would be very rare, I
> think.


I can easily imagine cases where some cookie remembers the last tab you have
open so that it will be open the next time. Or where you want to link to a
certain configuration of tabs showing. First on left would be most cases,
sure, but there would be enough other cases for it to be missed if it wasn't
an option.


> When this *does* happen to come up, my proposal would allow
> you to do this by targetting the card in the link.  The chances that
> you need *two* things to start with a card other than the first open
> by default are, I believe, *extremely* rare.


If you are using the tabs for navigation then that's no problem. If you are
doing something more complex, like emulating several open windows that might
have tabs in them, then it'd be a shame to not have that option.


> (Nevertheless, there exists possibilities for handling this within my
> proposal.  If it becomes necessary to customize the behavior of a
> stack (such as by altering the default displayed card), we can
> introduce a ::card-stack() pseudoelement which is nothing more than a
> centralized place to put properties that apply to a particular stack.)
>
> >> (I think your proposal would do this by making @checked a global
> >> attribute, right?  You'd need to change HTML for that.)
> >
> > See my last e-mail in response to Giovanni. I'm not above asking for a
> small
> > change to HTML, but I don't require it.
>
> Gotcha.
>
> >> >> > And wouldn't it also cause the
> >> >> > page to scroll to the tab, whether that was wanted or not?
> >> >>
> >> >> Yes it would.  This is currently a problem, but Giovanni suggested a
> >> >> solution in the link behaviors spec.
> >> >
> >> > I didn't see that, and still can't find it in skimming through what he
> >> > posted. Another dependency on a different spec?
> >>
> >> "Another" dependency?  I don't believe I currently rely on any other
> >> spec.  And the dependency only exists if (1) the author decides that
> >> the scrolling behavior is inappropriate, and (2) we don't just fold
> >> the anti-scrolling magic directly into this proposal.
> >
> > One propopsal for tabs requires display-roles and display-models, which
> is a
> > big can of worms.
>
> Not mine, though, so that dependency doesn't count against me.  ^_^


Yes I know that, but you did say you preferred it to my solution.


> > 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).



> > 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.


> You've indicated that your proposal can handle
> this, but I'm not entirely sure of how right now.  Luckily I asked for
> an example earlier in this email.  ^_^
>
> (Note that I would like to add magic generation of tabs into my
> proposal as well, and have an idea that will handle most reasonable
> cases.  Complex cases won't work, but at that point you're almost
> certainly putting your tabs in manually anyway.  It will at least
> cover the class of markup that the original Advanced Layout proposal
> could handle.)
>

Received on Wednesday, 22 April 2009 02:21:26 UTC