Holy Grail 圣杯布局详解

2024-04-10 09:58
文章标签 布局 详解 圣杯 holy grail

本文主要是介绍Holy Grail 圣杯布局详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Introduction

I’m sorry. Really. I didn’t name it. I don’t mean to overstate its importance or trivialize the other and rather weightier Holy Grails.

But the name’s out there, and we all know what it means.

Three columns. One fixed-width sidebar for your navigation, another for, say, your Google Ads or your Flickr photos—and, as in a fancy truffle, a liquid center for the real substance. Its wide applicability in this golden age of blogging, along with its considerable difficulty, is what has earned the layout the title of Holy Grail.

Many articles have been written about the grail, and several good templates exist. However, all the existing solutions involve sacrifices: proper source order, full-width footers, and lean markup are often compromised in the pursuit of this elusive layout.

A recent project has brought my personal grail quest to an end. The technique I’ll describe will allow you to deploy the Holy Grail layout without compromising your code or your flexibility. It will:

1.have a fluid center with fixed width sidebars,
2.allow the center column to appear first in the source,
3.allow any column to be the tallest,
4.require only a single extra div of markup, and
5.require very simple CSS, with minimal hacks patches.

On the shoulders of giants

The technique presented here is inspired by Alex Robinson’s brilliant One True Layout. Alex even addressed the Holy Grail problem in his article, but his solution requires two wrappers and makes padding difficult without a further layer of divs within each column.

Another lead came from Eric Meyer’s adaptation that uses positioning to mix multiple unit types. His example also yields a three-column layout with fixed sidebars and a liquid center. Unfortunately, it relies on approximate percentages and fills a portion of the viewport that varies widely with different screen resolutions.

Enough talk—let’s see some code

The required HTML is intuitive and elegant.

(For the sake of clarity in demonstrating this technique, we are intentionally using the non-semantic ids “center,” “left,” and “right.” We recommend you use semantic ids in any application of this technique. —Ed.)

<div id="header"></div>
<div id="container"><div id="center" class="column"></div><div id="left" class="column"></div><div id="right" class="column"></div>
</div>
<div id="footer"></div>

That’s it. A single extradiv to contain the columns is all that you need; this satisfies even my obsessive compulsive markup habits.

The stylesheet is almost as simple. Let’s say you want to have a left column with a fixed width of 200 pixels and a right column with a fixed width of 150 pixels. To simplify the comments, I’ll abbreviate the left, right, and center columns as LC, RC, and CC, respectively. The essential CSS is here:

body {min-width: 550px;      /* 2x LC width + RC width */
}
#container {padding-left: 200px;   /* LC width */padding-right: 150px;  /* RC width */
}
#container .column {position: relative;float: left;
}
#center {width: 100%;
}
#left {width: 200px;          /* LC width */right: 200px;          /* LC width */margin-left: -100%;
}
#right {width: 150px;          /* RC width */margin-right: -150px;  /* RC width */
}
#footer {clear: both;
}
/*** IE6 Fix ***/
* html #left {left: 150px;           /* RC width */
}

Simply replace the values with your desired dimensions and the grail is yours. The technique works in all modern browsers: Safari, Opera, Firefox, and (with the single-rule hack at the bottom) IE6. IE5.5 support would require at least a box-model hack, which is left as an exercise to the reader.

Take a look and marvel at the elegance.

How it works

The strategy is straightforward. The container div will have a liquid center and fixed-width padding on the side. The trick is then to get the left column to line up with the left padding and the right column with the right padding, leaving the center column to fill the liquid width of the container.

Let’s build this up step by step.

STEP 1: CREATE THE FRAME

Start with the header, footer, and container.

<div id="header"></div>
<div id="container"></div>
<div id="footer"></div>

We pad the container with the width we want our left and right columns to occupy.

#container {padding-left: 200px;   /* LC width */padding-right: 150px;  /* RC width */
}

Our layout now looks like this:
在这里插入图片描述

STEP 2: ADD THE COLUMNS

Now that we have our basic frame, we’ll stick in the columns.

<div id="header"></div>
<div id="container"><div id="center" class="column"></div><div id="left" class="column"></div><div id="right" class="column"></div>
</div>
<div id="footer"></div>

Next we add the appropriate widths and float them to get them in line. We’ll also need to clear the footer to keep it beneath the floated columns.

#container .column {float: left;
}
#center {width: 100%;
}
#left {width: 200px;  /* LC width */
}
#right {width: 150px;  /* RC width */
}
#footer {clear: both;
}

Note that the 100% width on the center column refers to the width of the container div, exclusive of the padding. We’ll see this 100% width again as the layout comes together, and it will still refer to this central width of the container.

The columns now want to line up in order, but because the center column is taking up 100% of the available space, the left and right columns wrap.
在这里插入图片描述

STEP 3: PULL THE LEFT COLUMN INTO PLACE

The only thing left is to get the colums to line up with the padding on the container. The center column starts exactly where it needs to be, so we’ll focus on the left column.

It takes two steps to get the left column in place. First, we’ll pull it all the way across the center column with a 100% negative margin. Remember that the 100% refers to the central width of the container, which is also exactly the width of the center column.

#left {width: 200px;        /* LC width */margin-left: -100%;  
}

Now the left column is overlapping the center column, sharing its left edge. The right column floats left and nestles against right edge of the center column (but still wraps), leaving us with the following:
在这里插入图片描述
To push the left column the rest of the way over, we’ll use relative positioning with an offset that’s exactly the width of the left column.

#container .columns {float: left;position: relative;
}
#left {width: 200px;        /* LC width */margin-left: -100%;  right: 200px;        /* LC width */
}

The rightproperty pushes it 200px away from the right edge; that is, to the left. Now the left column lines up perfectly with the left padding of the container.
在这里插入图片描述

STEP 4: PULL THE RIGHT COLUMN INTO PLACE

The only task remaining is to pull the right column into place. To do that, we just need to pull it out of the container and into the container’s padding. We’ll again use a negative margin.

#right {width: 150px;          /* RC width */margin-right: -150px;  /* RC width */
}

Everything is now in its right place, and the wrapping disappears.
在这里插入图片描述

STEP 5: DESIGN DEFENSIVELY

If the browser window is resized so that the center becomes smaller than the left column, the layout breaks in a standards-compliant browser. Setting a min-width on the body keeps your columns in place. With IE6 this doesn’t happen, so the fact that it doesn’t support min-width isn’t a problem.

body {min-width: 550px;  /* 2x LC width + RC width */
}

Of course, no layout technique would be complete without requiring some sort of workaround in Internet Explorer. The negative margin pulls the left column too far to the left in IE6 (the full width of the browser window). We need to push it back to the right the full width of the right column—using the star-html hack to mask it from other browsers—and we’re ready to go.

* html #left {left: 150px;  /* RC width */
}

The reason we need to use the width of the right column involves a bit of algebra. I won’t bore you with the details; you can work it out for yourself or just consider it another one of IE’s many charms.

Padding, please

I’m no designer, but looking at the layout above offends even my aesthetic sensibilities. The unpadded columns are hard on the eyes and difficult to read. We need whitespace.

One of the drawbacks of using percentages with the One True Layout to create liquid columns that it makes padding the columns a bit tricky. Percentage paddings tend to look bad at some screen widths. Fixed paddings can be added, but only by cluttering the markup with a div nested inside each column.

With this technique, padding isn’t a problem. Padding can be added directly to the left and right columns; just adjust the width accordingly. To give a 10-pixel padding to the left column in the example above, but keep it’s full width (padding + width) at 200px, simply change the rule as follows:

#left {width: 180px;        /* LC fullwidth - padding */padding: 0 10px;right: 200px;        /* LC fullwidth */margin-left: -100%;
}

Padding the center requires a little more ingenuity, but no more markup and only a pinch of additional CSS.

The padding plus a width of 100% causes the center column to expand beyond the non-padded width of the container. In order to tame it back into place, we need to increase the right margin by the total amount of the padding. This ensures that the center column is only as large as we expect it to be.

Also, since the center column is now wider, the left column has a larger distance to move in order to get to the correct place. Increasing the offset by the total center padding does the trick.

To make this concrete, I’ll modify the example to add a 10-pixel padding to each side column (for a total of 20 pixels), and a 20-pixel padding to each side of the center (for a total of 40 pixels). The new CSS looks like this:

body {min-width: 630px;      /* 2x (LC fullwidth +CC padding) + RC fullwidth */
}
#container {padding-left: 200px;   /* LC fullwidth */padding-right: 190px;  /* RC fullwidth + CC padding */
}
#container .column {position: relative;float: left;
}
#center {padding: 10px 20px;    /* CC padding */width: 100%;
}
#left {width: 180px;          /* LC width */padding: 0 10px;       /* LC padding */right: 240px;          /* LC fullwidth + CC padding */margin-left: -100%;
}
#right {width: 130px;          /* RC width */padding: 0 10px;       /* RC padding */margin-right: -190px;  /* RC fullwidth + CC padding */
}
#footer {clear: both;
}/*** IE Fix ***/
* html #left {left: 150px;           /* RC fullwidth */
}

Of course, top and bottom padding can be added without any problems. See this nicely padded version for the full template.

This technique works just as well for ems. Unfortunately, you can’t mix-and-match ems and pixels, so choose, but choose wisely.

Equal-height columns

This technique really comes together when the columns are given equal heights. The method I’m using is adapted wholesale from the One True Layout, so I won’t go over it in detail. To deploy it, simply add the following CSS:

#container {overflow: hidden;
}
#container .column {padding-bottom: 20010px;  /* X + padding-bottom */margin-bottom: -20000px;  /* X */
}
#footer {position: relative;
}

Here, I’ve given the columns an extra padding of 10px on the bottom.

The usual caveats apply. Be aware that Opera 8 has a bug withoverflow: hidden that leaves all of your columns huge. A workaround is detailed on the One True Layout page; you can use that, or wait for Opera 9 (which fixes the bug) to come out of beta.

One additional problem unique to this layout is that IE doesn’t clip the column backgrounds at the bottom of the container. They spill out over the footer if the page is not as tall as the viewport. This isn’t a problem if you don’t have a separate footer, or if your pages are tall enough to ensure that you’ll always take up the whole viewport.

If you need that footer, though, never fear. This, too, is fixable, but requires one more div. Add a wrapper to the footer, like so:

<div id="footer-wrapper"><div id="footer"></div>
</div>

Now re-use the same trick with the equal columns to make the footer wrapper extend beyond the page, leaving the footer itself for you to do with as you please.

* html body {overflow: hidden;
}
* html #footer-wrapper {float: left;position: relative;width: 100%;padding-bottom: 10010px;margin-bottom: -10000px;background: #fff;         /* Same as body background */
}

This solves the problem, and leaves us with the desired result and a minimum of cruft.

Oh, and there’s one more thing

The extremists out there might be wondering to themselves whether there’s not an even better way to do this. After all, the method I’ve illustrated introduces a non-semantic container div. Surely we can’t have one extra div cluttering up our otherwise flawless markup.

If you, like me, have been wondering this very thing, wonder no more. As a special bonus, I present to you the wrapper-free Holy Grail, in all its minimalist glory. One div for each section of the code—no more, no less. Semantic bliss, almost worthy of the title of “Holy Grail.”

The principle behind the CSS is the same. The padding has been applied directly to the body, eliminating the need for any containers. Negative margins stretch the header and footer to ensure that they take up the entire space.

This tiny version works in all the aforementioned browsers, even (almost shockingly) Internet Explorer. Equal-height columns do not work, however, and this layout will break down for very small window widths. Use it with caution.

So what now?

While this particular application of the Holy Grail is rather specific, the technique can be generalized considerably. Why not have two liquid columns? Why not switch up the column orders? These applications are beyond the scope of this article, but achievable with minor modifications. Use the grail wisely, and it can be a particularly handy (and clutter-free) addition to your bag of CSS tricks.

Article source

Matthew Levine

这篇关于Holy Grail 圣杯布局详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/890738

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建      首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件、动态链接库文件、可执行文件、脚本文件、配置文件等。      我们在编写hellowor

LabVIEW FIFO详解

在LabVIEW的FPGA开发中,FIFO(先入先出队列)是常用的数据传输机制。通过配置FIFO的属性,工程师可以在FPGA和主机之间,或不同FPGA VIs之间进行高效的数据传输。根据具体需求,FIFO有多种类型与实现方式,包括目标范围内FIFO(Target-Scoped)、DMA FIFO以及点对点流(Peer-to-Peer)。 FIFO类型 **目标范围FIFO(Target-Sc

019、JOptionPane类的常用静态方法详解

目录 JOptionPane类的常用静态方法详解 1. showInputDialog()方法 1.1基本用法 1.2带有默认值的输入框 1.3带有选项的输入对话框 1.4自定义图标的输入对话框 2. showConfirmDialog()方法 2.1基本用法 2.2自定义按钮和图标 2.3带有自定义组件的确认对话框 3. showMessageDialog()方法 3.1

脏页的标记方式详解

脏页的标记方式 一、引言 在数据库系统中,脏页是指那些被修改过但还未写入磁盘的数据页。为了有效地管理这些脏页并确保数据的一致性,数据库需要对脏页进行标记。了解脏页的标记方式对于理解数据库的内部工作机制和优化性能至关重要。 二、脏页产生的过程 当数据库中的数据被修改时,这些修改首先会在内存中的缓冲池(Buffer Pool)中进行。例如,执行一条 UPDATE 语句修改了某一行数据,对应的缓

lvgl8.3.6 控件垂直布局 label控件在image控件的下方显示

在使用 LVGL 8.3.6 创建一个垂直布局,其中 label 控件位于 image 控件下方,你可以使用 lv_obj_set_flex_flow 来设置布局为垂直,并确保 label 控件在 image 控件后添加。这里是如何步骤性地实现它的一个基本示例: 创建父容器:首先创建一个容器对象,该对象将作为布局的基础。设置容器为垂直布局:使用 lv_obj_set_flex_flow 设置容器