Re: Tabbed Interfaces in CSS

On Apr 22, 2009, at 2:15 PM, "Tab Atkins Jr." <jackalmage@gmail.com>  
wrote:

> On Wed, Apr 22, 2009 at 1:30 PM, Brad Kemper <brad.kemper@gmail.com>  
> wrote:
>> On Apr 22, 2009, at 7:51 AM, "Tab Atkins Jr."  
>> <jackalmage@gmail.com> wrote:
>>> 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.
>
> Oh, indeed, I recognize that :checked is the major part, and it's a
> good way to solve the problem.  But there's several good ways, and the
> devil is in the details surrounding the problem.  ^_^  Pulling tabs
> from the card content seems to have become a requirement, and the
> details of displaying tabs are very important as well.  If they won't
> display well, and there's no way to *make* them display well in a
> proposal, then it's a non-starter.  (I am not implying that this is
> the case for your proposal, mind.)

Actually I think you are. Unfairly, since I've so far described 2 or  
three resonable ways, and there are probably more:

1. Fixed width tabs and 'left' values.
2. One of the move things around proposals, such as Template Layout  
(which you more or less validated).
3. A proposed feature of appearance that could manage how much tabs of  
the same group were allowed or expected to overlap (according to the  
way the OS normally), and moved each successive one over to the right  
by enough to enforce that policy.
4.   You could use markup and style similar to what I showed in Feb  
2008, substituting, but using the radio-group property on the label,  
instead of an adjacent actual radio button. And if the 'for' attribute  
could be a CSS property to create label-like behavior, then you  
wouldn't need to use an actual HTML label.

>>> 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.
>
> Sorry, I didn't mean group them behavior-wise.  Appearance is being
> used in your example to group them visually.  I don't think that's a
> good idea.

I didn't do that either. I was saying that if appearance could  
regulate how much they overlap, according to the OS standards for  
tans, then it would take care of the 'left' property positioning in an  
easy way. Nowhere did I say that Appearance would group them visually.

>>> 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.
>
> It seems to me that the display of tabs is pretty critical to authors,
> so we need to make sure there are good options here.  Any tabbed
> display proposal needs to be paired with a way to, you know, *display
> the tabs* in a way that will be acceptable to authors.

The tabs would be displayed with what I discribed. And you have  
confirmed that Template Layout could be used for spacing them appart  
so that they don't overlap. And again, I have mentioned other ways to  
acheive the spacing. So I really don't know why you keep acting as  
though they would not be displayed without serious magic.

>>> and defeat a display:none applied to their parent.
>>
>> I suggested no such thing.
>
> Apologies; I see what you were doing now.  Appearance:none removes
> *all* default formatting from fieldset, but doesn't *hide* it.  Then
> you pull the legend out, and display:none all other children, leaving
> an empty fieldset with no other appearance properties set, which makes
> it effectively invisible.

Yes.

> This works.  ^_^
>
>>>  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.).
>
> Displaying a front/back tab in a UA-default way seems like an
> appropriate job for appearance, but you are using it as well to
> somehow move the tabs to the top/bottom/side/etc.

NO. I never said that. You are reading too much into it, and then  
arguing against your own conceptions. All I suggested is that the  
appearace of an OS tab is different for different sides, which I  
hardly thought was controversial. For instance, a tab that was  
intended for the bottom would look a lot like an upside-down version  
of a tab intended for the top, except that the text would be right- 
side up. This says nothing about where you actually put the tab.

If you wanted to actually move said tab to the bottom of the fieldset,  
it would be a fairly simple matter with absolute positioning. And you  
could move to sides with that and transformation, I imagine. But  
again, that's just more styling that goes beyond the simpler concept  
that I was trying to show (that extending checkbox and radio button  
'checked' states and behavior beyond just inputs would be useful, and  
could be used for things like tabs, which to programmers are generally  
just a sub-class of radio buttons anyway). I didn't think I would need  
to get into all the obvious stuff about how to use CSS 2.1.

> This is requiring
> appearance to handle positioning as well, which is bad.  If you are
> *relying* on the appearance-magic to handle tab positioning properly,

I am not. I merely suggested it would be useful if when using  
Appearance that Appearance be able to manage the left-right  
positioning. Think about how one OS might center the tabs and another  
might have them left alighned, or how one OS might need them to  
overlap a little and another might want them to have a little space  
between each. If the rest of the markup placed them into the same  
vertical area, then it would be nice if the OS adjusted the horizontal  
within the container according to it's own standards for that  
Appearance. That does not say that there are not other ways to move  
them right and left, ways that I mentioned in my first posts on the  
subject, in fact.

> then how does an author handle it when they don't want the UA-default
> style?

I have already answered this several times, and so have you.

> This really needs to be defined (or at least be possible to
> define) in a way without any recourse to magic.

I have.

> If you could provide a simple ugly example just using border, padding,
> and margin, while still achieving the desired tab *layout*, I'd be
> happier.  ^_^

Why? When you wrote an example you just wrote "/* insert generic tab  
styling here */", which pretty much describes how I was using  
appearance. But if you want to take your own example and fix the  
display:none part according to you newer understandind of how I was  
hiding inactive cards, then you'd have your answer. Or you could use  
fixed widths on the tabs and set the 'left' position of each according  
to the width of those that preceded it. Or use one of the other  
methods I've described already.


>>> 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.
>
> Well, it solves the problem that tabs may come from various places but
> have to gather in a single location.
>
> Frex, look at the fieldset/legend example.  Let's say the first
> fieldset is :checked currently.  In this case, then, the order of
> content is:
>
> fieldset-one content before the legend
> fieldset-one legend
> fieldset-one content after the legend
> fieldset-two legend
>
> That's... not really what you want.  It's basically an accordion,
> because the card contents will be distributed between the tabs.  I
> think you may have overlooked this,

No, I think you are overlooking that the fieldsets are  
position:absolute. So they don't take up space and this should all  
have the same x and y coordinates (I think I said this before).

There were some things in the code that wouldn't display quite right,  
since I didn't test before, so I'll post something new in a few  
minutes that will show the positioning that can be acheived with  
existing CSS.

> and thus not really understood why
> Giovanni and I keep harping on the degree of appearance magic you're
> depending on.

This is the first I've heard of this particular misunderstanding. I've  
always maintained from the start that I was not depending on any  
appearance magic. If something didn't make sense, it had little to do  
with Appearance.

> You *need* the ability to flow tabs out of their normal
> position to make this work properly as a tabbed layout;

Not if you are willing to have fixed tab widths, and I have seen  
designs that do. And not if tab appearance could include self  
management of left-right placement in a line for proper OS overlap/ 
spacing/alignment. .

> luckily
> Template Layout gives us a decent way to do this.  ^_^

Yep, or the other things I just mentioned, or maybe float-to and it's  
competitors.

>>> 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.
>
> Yes, I am (basically agreeing with you).  Sorry if that's not  
> obvious.  ^_^

You are forgiven.

>>> 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.
>
> Yup, got that now.
>
>>>  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.
>
> Good, neither would I.
>
>>> 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.
>
> Understood now.
>
>>> 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.
>
> Understood now.
>
>>>>>> 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.
>
> Nod.  We just need to make sure that there's at least *one* way to do
> it well.  Your proposal, by itself, didn't seem to offer that.
>
>>>  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.
>
> As expressed above, it's not the "min-left" or whatever that's the
> problem.  It's the fact that you have to flow the tabs out of their
> normal position into a new location, at least if you are extracting
> them from the card contents.  If you don't, you get accordion display
> instead.

Nope. See above, and my next post.

>>>>>> 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.
>
> Oh, yes, certainly.  Sorry, I'm reiterating that as much for my own
> benefit as anyone else's.  I want to make sure that we all agree on
> the same requirements, and that it is clear to outside observers just
> what those requirements driving our proposals are.  I've tried to
> follow conversations that don't do that - it gets difficult when
> you're not in the same design mindset as the original authors.  ^_^
>
>>>  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.
>
> Ah, yeah, that'd work.  Just use <a> *and* <label> together, the
> latter providing :checked interaction and the former providing good
> fallback behavior.  This would still require some sort of Link
> Behavior stuff to avoid scrolling, but at this point that's a minority
> concern (rather than being part of the core proposal, like it is in
> mine).
>
>
> Please understand that at this point I'm very happy with the
> possibilities of your proposal.  It seems to accomplish the necessary
> behavior in a simple way, it interacts with the existing event model
> in HTML well (just update :checked whenever a click event bubbles
> through) which should make it more attractive to implementors and easy
> to understand for authors, the default use provides good fallback
> naturally and it allows decent fallback in the next most common use,
> and another proposal currently in the pipeline and looking promising
> (Template Layout) provides us all the tools to style this well.  To
> top it all off, it even interacts well with javascript: you can change
> the active card in js by shooting a click event at the element, or
> *prevent* a card from raising by eating click events on its tab before
> they can bubble through to the card.
>
> All in all, this *feels* like a winner to me.
>
> ~TJ

OK thanks. Sorry if I come off as a little defensive. I've typed the  
above on an iPhone, and don't want to edit this message any more.

Received on Thursday, 23 April 2009 17:24:09 UTC