Fixed-in-parent

Hi all,

There's a layout pattern I'm starting to see on more an more web pages
(and in some UI) that CSS is currently lacking support for, but that I
think would be nice to add.

One example is:
http://www.yelp.com/search?find_desc=sushi&ns=1&rpp=10&find_loc=San+Francisco%2C+CA

The page contains some search-UI, and below it lists some search
result. On the side of the search results is a map indicating the
geographical location of all the results. As you scroll down on the
page to see results further down the map changes position from being
positioned next to the first search result to being positioned at the
top of the screen. This allows you to look at any search result while
still being able to see the map.

And if you make your window small enough, you'll notice that if you
scoll far enough down, the map eventually stops being fixed and never
positions further down than a certain point, approximately at the last
search result.

position:fixed is almost the solution here, but would cause the map to
be positioned covering parts of the search-UI when the top of the
viewport is at the UI, or would force the map to always be positioned
sufficiently far down in the viewport that it never covers the
search-UI, even when the viewport is only showing search results. This
would be extra problematic if the search-UI is larger than the
viewport.

Another example is
http://perldoc.perl.org/index-functions.html
The main contents of the page is a list of links, and at the top of
the list is a header with a title and some navigational links. If you
scroll down on the page you'll notice that the header changes position
such that it's always visible at the top of the visible part of the
list of links. In this case it actually looks like the pages uses
script to switch between position:static to position:fixed depending
on the scroll position of the viewport.

Here are a few more examples:

http://www.whatwg.org/specs/web-apps/current-work/
(Warning! Takes a long time to load in some browsers)
The page shows status for each section next to the section. The status
indicator is located next to the start of the section if visible, or
at the top of the viewport if the start of the section isn't visible.

http://www.examiner.com/finance-examiner-in-national/1-billion-bet-july-of-us-downgrade-brings-questions-of-insider-information
The "share" panel on the side stays with you as you scroll down.
However in order to prevent it from obscuring parts of the page
header, it's never positioned higher than a certain distance from the
top of the page.

gmail
While reading a mail thread, if you scroll down, the panel letting you
manage the thread (archive, delete, labels, next, previous, etc) stays
with you at the top of the screen. However it never goes outside the
area which displays threads, so if you scroll to the top of the page,
the panel doesn't obscure the search box or the generic google header.

The iPhone contact list
The contact list is sectioned by first letter of the name of the
contacts in the list. Each section has a header indicating the first
letter of the contacts in the section. The header is generally
displayed at the top of the section, but if not visible there it stays
on top of the viewport. However the header never goes further down
than the bottom of its section. When at the bottom of the section it's
generally edge-to-edge with the header for the section below it.


In all these cases the position of an element switches between fixed
positioning and something else depending on where the user has
scrolled. Specifically, if the element isn't visible, due to
scrolling, at its normal position, the positioning changes to fixed.
However it only stays fixed within a certain area of the page, never
positioning above or below it.


Here is an initial proposal for how to support this. Apologies for it
being in pretty poor shape. I'm not a layout person which surely
shows. I propose two new values to the "position" property:

static-fixed-in-parent
absolute-fixed-in-parent

When position is static-fixed-in-parent the box's position is
calculated according to the normal flow. If the box ends up partially
or wholly hidden due being inside overflow in a containing block (or
the containing block's containing block etc), the box is moved to
become visible. When moving the box, the box is never moved outside
its containing block. I.e. the top edge of the box is never moved
further up than the top edge of the containing block, the left edge of
the box is never moved further to the left than the left edge of the
containing block, etc.

If the box needs to be moved upwards in order to be displayed, but
moving it to the top edge of the containing block still doesn't fully
display it, the box should still be moved to the top edge of the
containing block. This happens even if this results in no part of the
box displaying (this in order to get computed values to be correct
when queried through the DOM. Same thing applies to other directions.


When position is absolute-fixed-in-parent the box taken out of the
flow and positioned as if the position property was "absolute". If the
box ends up partially or wholly hidden due being inside overflow in a
containing block (or the containing block's containing block etc), the
box is moved to become visible in the same way as for
static-fixed-in-parent.


A few open questions:
Should this happen if a box is hidden due to being inside overflow
that is "overflow:hidden"? Or just if the overflow is
"overflow:scroll"?
What happens if the box is bigger than the containing block?
Do we need to allow moving the box only vertically or only
horizontally? The HTML5 spec would seem to need that in order not to
the status indicator over the text of the spec if the user scrolls
horizontally.
What happens if the box's position before being moved is outside its
containing box?
What happens if there are multiple containing blocks with overflow?

/ Jonas

Received on Tuesday, 9 August 2011 03:52:01 UTC