Layout of pages¶
The reahl.web.bootstrap.grid
module provides tools with which
you can control the basic layout of a page. Layout is responsive,
meaning that it adapts depending on the size of the device used to
view the page.
The basic tools for laying out a page are
reahl.web.bootstrap.grid.Container
,
reahl.web.bootstrap.grid.ColumnLayout
and
reahl.web.bootstrap.grid.ResponsiveSize
.
Containers¶
Some web sites present all their contents in an area of fixed size, with the entire “content area” itself centered on the browser viewport.
On other sites, the contents of the site span the entire width of the viewport instead:
A Container
manages the layout of an HTMLElement
and its contents
to conform to one of these schemes.
A Container
is by default “fixed”, which means its contents will be
confined to a fixed-size area that is centered on the viewport. The
size of this fixed-size area does change if a browser is resized –
but it changes only at fixed intervals and stays centered on the
viewport.
When constructing a Container
it can be set to be “fluid” in order
to make it behave like the second example above where the contents of the
HTMLElement
will fill the available width.
Different areas of a site may be laid out using different
Container
s. For example, you might want your pages to have a
header and footer that both stretch the entire viewport width, but
with a content area inbetween that has a fixed width and is centered.
Bootstrap requires that all Widgets laid out with a ColumnLayout
be
nested somewhere (no matter how deeply) in another which is laid out
by a Container
.
Responsive grids¶
A ColumnLayout
is used to turn an HTMLElement
such as a Div
into
one row of an invisible grid with a number of columns inside that one
row. The Widget
s added as children to a particular column are then
positioned inside that (otherwise invisible) column.
When adding a column, you need to specify the size of that
column. This is done using a ResponsiveSize
. A ResponsiveSize
lets
you specify how wide the column should be on each possible size of
user device. User device sizes (called device classes) can be one of:
- xs (extra small)
- sm (small)
- md (medium)
- lg (large)
- xl (extra large)
In the code below, 12 columns of 1/12th the page width are added to a
Div
. Each column is a Div
itself and all have the same text in
them. Note that the ResponsiveSize
is only set up with a size for medium
devices. This means that the columns will be 1/12th of the page on
medium (or larger) devices. On devices smaller than medium, each column
will expand to the full width with all the columns stacked on top of
one another. (On small devices it is better to have to scroll down
further to see content than to have to scroll right).
def add_twelve(self):
div = Div(self.view).use_layout(ColumnLayout())
self.body.add_child(div)
for i in range(1, 13):
column = div.layout.add_column(ResponsiveSize(md=1))
column.add_child(P(self.view, text='1/12th on md and larger'))
A ColumnLayout
can also be constructed with a list of tuples stating
what columns it should have and what each one should be called. In
this case, it will add all the specified columns (each a Div
itself)
to the Div
you apply it to and make these available as a
dictionary. An example is shown here:
def add_two(self):
layout = ColumnLayout(('left', ResponsiveSize(md=4)),
('right', ResponsiveSize(md=8)))
div = Div(self.view).use_layout(layout)
self.body.add_child(div)
div.layout.columns['left'].add_child(P(self.view, text='4/12ths on md and larger'))
div.layout.columns['right'].add_child(P(self.view, text='8/12ths on md and larger'))
In order to really appreciate the power of ResponsiveSize
, you will
have to fire up the example and play around with it. The example here
includes different Views – this View is the first called “Grid
basics”.
Here is a screenshot of what the page looks like:
See how the layout changes if you change the size of the window when running the example yourself. On displays that are medium sized or larger (with your browser maximised), you will see two rows: one with 12 equal sized columns, and another with two columns that are not equally sized.
As soon as you make the browser window smaller than “md” size, things change: All the columns now stack on top of one another and fill the whole width of the screen to make them more usable on the smaller sized screen.
Laying out a whole page¶
It is often useful to layout an entire page with a header area at the top, a footer at the bottom, and a content area in between. The content area is also often divided into different columns.
You can layout a page in this fashion by using PageLayout
in
conjunction with a suitable ColumnLayout
to be used for its content
area.
The “Page layout” view in our example shows how this works:
class PageLayoutPage(HTML5Page):
def __init__(self, view):
super(PageLayoutPage, self).__init__(view)
column_layout = ColumnLayout(('left', ResponsiveSize(md=4)),
('right', ResponsiveSize(md=8)))
self.use_layout(PageLayout(document_layout=Container(), contents_layout=column_layout))
self.layout.header.add_child(P(view, text='The header'))
self.layout.footer.add_child(P(view, text='The footer'))
left = column_layout.columns['left']
left.add_child(P(view, text='To the left'))
right = column_layout.columns['right']
right.add_child(P(view, text='To the right'))
Notice how the same responsive properties hold for such pages too – go ahead and make your browser window smaller on this example.
You can nest the usage of a ColumnLayout
inside others (like the
columns on this page), thereby creating complex grid structures that
resize on all levels.