CSS框模型和定位

分享于 

23分钟阅读

Web开发

  繁體
CSS Box Model Image

介绍

CSS框模型和CSS定位是网页设计中的两个基本概念。 理解这些概念对于掌握页面布局和其他网页设计问题非常重要。

在本文中,我描述了一个带有一些JavaScript代码的演示web页面( 可以在这里运行 ),以帮助理解W3C模型和CSS定位。 演示工作在 Firefox 和 Chrome的最新版本中正常运行。

当我在 KFUPM的网页工程课程中展示这些概念时,我觉得需要一些交互过程来帮助理解这些概念,这就是这个概念的概念。

本文遵循同样的精神并提供解释和一些有用的例子。

本文分为三个部分:

  • 演示的工作原理
  • CSS框模型
  • CSS定位

演示的工作原理

下面是演示页面的源代码:

<html><head><title>CSS BOx Model</title><scripttype="text/javascript"> window.onload = function () { getStyleInfo(); placeShadowDiv(); };
 lastX=0; lastY=0;function getStyleInfo()
{
 var elem = document.getElementById("B");
 //alert(elem);var styleInfo = window.getComputedStyle(elem);
 outstr = " width:"+styleInfo.width;
 outstr += "; height:"+styleInfo.height;
 outstr += "; left:"+styleInfo.left;
 outstr += "; top:"+styleInfo.top;
 outstr += "; margin:"+styleInfo.marginLeft; // margin is"" for FireFox outstr += "; padding:"+styleInfo.paddingLeft; // padding is"" for FireFox outstr += "; border:"+styleInfo.borderLeftWidth;
 //document.write(elem.currentStyle);//alert(document.getElementById("styleInfo")); document.getElementById("styleInfo").innerHTML =outstr ;
}function handleClick(oEvent)
{
 //alert(this.tagName);var elem = document.getElementById("txt1");
 var distX = Math.abs(oEvent.pageX- lastX);
 var distY = Math.abs(oEvent.pageY- lastY);
 var distString = "";
 if (lastX!=0) distString = ";
 dist = (" + distX + "," + distY + ")";
 lastX = oEvent.pageX; lastY = oEvent.pageY;
 elem.value += "n At (" + oEvent.pageX + ",
" + oEvent.pageY + ")" + distString;
}function setPadding(e)
{
 //alert("button click"); document.getElementById("B").style.padding=
 document.getElementById("padding").value +"px";
 getStyleInfo();
 placeShadowDiv();
 e.stopPropagation(); // event.stopPropagation() works in chrome but fails in firefox// window.event.cancelBubble = true;//this dose not work in firefox}function setMargin(e)
{ document.getElementById("B").style.margin=document.
 getElementById("margin").value +"px";
 getStyleInfo();
 placeShadowDiv();
 e.stopPropagation();
 // e.cancelBubble = true;}function setBoxSizing(boxSize)
{ var is_firefox = navigator.userAgent.toLowerCase().indexOf('firefox')> -1;
 var elem = document.getElementById("B");
 if (is_firefox) elem.style.MozBoxSizing = boxSize; // For FireFoxelse elem.style.boxSizing = boxSize; // Works in Chrmoe placeShadowDiv();
}function placeShadowDiv()
{ var BstyleInfo = window.getComputedStyle( document.getElementById("B") );
 var B_width =parseInt(BstyleInfo.width);
 var B_height =parseInt(BstyleInfo.height);
 // alert(B_width +"/" + B_height);var B_topMargin = parseInt(BstyleInfo.marginTop);
 var B_leftMargin = parseInt(BstyleInfo.marginLeft);
 var B_bottomMargin = parseInt(BstyleInfo.marginBottom);
 var B_rightMargin = parseInt(BstyleInfo.marginRight);
 var B_topPadding = parseInt(BstyleInfo.paddingTop);
 var B_leftPadding = parseInt(BstyleInfo.paddingLeft);
 var B_bottomPadding = parseInt(BstyleInfo.paddingBottom);
 var B_rightPadding = parseInt(BstyleInfo.paddingRight);
 var B_border = parseInt(BstyleInfo.border ); // In FireFox, this gives NaNif (isNaN(B_border)) B_border = parseInt(BstyleInfo.borderLeftWidth);
 var width = B_width + B_leftPadding + B_rightPadding + 2 * B_border +
 B_leftMargin + B_rightMargin;
 var height = B_height + B_topPadding + B_bottomPadding + 2 * B_border +
 B_topMargin + B_bottomMargin;
 // alert( width +"/" + height); DivB_BoxSizing =BstyleInfo.boxSizing;
 // alert("DivB_BoxSizing:" + DivB_BoxSizing);if (DivB_BoxSizing == "padding-box") // padding is parts of width/height { width = B_width + 2 * B_border + B_leftMargin + B_rightMargin;
 height = B_height + 2 * B_border + B_topMargin + B_bottomMargin;
 }
 if (DivB_BoxSizing == "border-box") // padding and border are parts of width/height { width = B_width + B_leftMargin + B_rightMargin;
 height = B_height + B_topMargin + B_bottomMargin;
 }
 document.getElementById("shadowDiv").style.left= BstyleInfo.left;
 document.getElementById("shadowDiv").style.top= BstyleInfo.top;
 document.getElementById("shadowDiv").style.width= width +"px";
 document.getElementById("shadowDiv").style.height= height +"px";
}</script><styletype="text/css">body, td { font-size:14pt; }
 td { line-height:2.2em; }
 select { font-size:.9em; }
 input { margin:0;margin-left:16px;font-size:11pt;font-weight:bold;margin-top:6px;}
 input[type=button] { padding:4px 8px;width: 120px; }
 p { font-size:14pt;font-family:Tahoma; }
 div#A {z-index:-1;position:absolute;left:50px;top:320px;height:250px;width:600px;border: 1px solid #000;background-color:#CCC}div#B { -moz-box-sizing: content-box;box-sizing:content-box;z-index:2;position:absolute;left:50px;top:30px;width:400px;height:120px;border:10px solid lightblue;background-color:green;margin:30px;padding:20px;}
 div#shadowDiv {z-index:0;position:absolute;margin:0;padding:0;background-color:maroon;width:160px;height:150px}div#topDiv { position:absolute;margin:0;padding:0;top:0;left:100px;height:30px;border-left:1px solid black;}
 div#leftDiv { position:absolute;margin:0;padding:0;left:0;top:60px;width:50px;border-bottom:1px solid black;}</style></head><bodyonClick="handleClick(event)"><divid="A"><divid="B"><divstyle="background-color:yellow; margin:0;
 padding:0;width:100%;height:100%"> Yellow area is content of <b>div#B</b> (shows the extent of width and height of <b>div#B</b> for default box-sizing)<br/><br/> Green area is padding of <b>div#B</b></div></div><divid="shadowDiv"></div><divid="topDiv"> top (30px)</div><divid="leftDiv"> left (50px)</div></div><divonclick="event.stopPropagation()"style="border-bottom:1px solid gray"><table><tr><td><textareastyle="font-size:16pt;font-weight:bold;width:440px;
height:160px;"id="txt1"rows="5"cols="30"></textarea></td><td>Margin and padding for div#B:<br/><inputid="margin"size="5"/><inputtype="button"onclick="setMargin(event)"value="Set Margin"/><br/><inputid="padding"size="5"/><inputtype="button"onclick="setPadding(event)"value="Set Padding"/><br/><label>Box Sizing<selectonChange="setBoxSizing(this.value)"><optionvalue="content-box">Content Box (default)</option><!--<option value="padding-box"> Padding Box</option>--><optionvalue="border-box">Border Box</option></select></label></td></tr></table><p><b>Style Info for div#B:</b><spanid="styleInfo"></span></p><p><b><i>Note:</i></b> Offset (left,top,.. )
is measured <b>from </b><i>border of container</i><b>to </b><i>start of margin</i> (and not border) of the enclosed element.
Thus, the position of the"Margin Box"
of the enclosed block is not affected by margin or padding of the container.</p></div></body></html>

在HTML中,我们定义了两个分区: div#A 和 div#B ( 子部门),两者都是绝对定位。 因此( 阅读稍后给出的解释)的上。左像素值分别与左边界和左边界偏移,分别为和左边缘。

在JavaScript代码中,函数 handleClick() 跟踪鼠标点击的位置,并将( x,y ) -coordinates打印到 textarea ( 在页面的左上角)。 它还打印两个连续位置之间的水平/垂直距离。 这样,用户就可以验证div#B的位置和它的四个框的尺寸。 比如,通过单击黄色区域( div#B的内容框)的相对端,可以获得上面图中显示的坐标;因此"dist = ( 400,120 )"对应于的宽度和高度的大小。

使用的基本技术

为了区分div#B的内容框,我将div#B的内容设置为另一个除与div#B不同的背景颜色外的( 使用padding=margin=0和 width=height=100% )。

为了跟踪div#B的margin 盒,我使用了辅助除法( 使用 id="shadowDiv" )。 shadowDiv的左。顶。宽和高由 function placeShadowDiv() (the function is first called when the page is loaded and then every time the margin or padding of div#B is changed) 计算。

最后,使用函数 getStyleInfo() 计算div#B的( 显示) 样式信息。 在加载页时,只要 padding/margin/box-sizing 发生更改,就会首先调用这里函数。

CSS框模型

Box model image

CSS框模型定义了 HTML block 元素的布局,例如( <div> ) 和段落( <p> )。 它不适用于 inline 元素(。<span>,锚点( <a> ),也不适用于一组其他。

每个 block 元素都以( 按浏览器) 布局,并带有四个部分( 方框)的矩形框。 最里面的部分( 框) 是内容( 或者内容框),它被 padding ( 或者 padding 框) 包围。 边框( 或者边框框) 包含 padding ;最外层是 margin ( margin 框)。 在边界框中指定环绕内容的间距,而用于指定分隔元素与周围区域的间隔。 对于屏幕显示,通常以像素为单位指定 padding 和 margin。

在默认情况下,块元素会占用浏览器窗口的整个宽度,并在调整浏览器窗口的大小时调整大小。 元素( 如果未设置高度)的高度调整以适应它的内容( 用户可能必须滚动)。

当 block 元素被指定为宽度( 或者高度) 时,它将应用于内容框,而不是 border-to-border。 虽然这可以能是直观的,但是它是默认的行为( 默认的W3C方框模型)。 这里行为可以更改,但只能通过设置 CSS box-sizing 属性。 在CSS3中,这里属性可以设置为"内容框"。"填充框"或者"边框框"。

对于默认框模型,由 block 元素占用的区域将具有以下总宽度和高度:

总宽度 = 宽度+ 左 padding + 右 padding + 左边框+ 右边框+ 左 margin + 右 margin

总高度 = 高度+ 顶部 padding + 底部 padding + 上边框+ 下边框+ 顶部 margin + 底部 margin

CSS定位

以下 table 提供了有关 CSS位置属性和其他相关属性的基本信息。

属性价值和描述
位置static: 默认位置;根据正常流放置元素。
忽略属性 top/left/bottom/right。
relative: 元素被放置在与它的正常 static 位置的某些偏移处。
绝对: 元素放置在它的包含元素的固定位置。
固定: 元素放置在浏览器窗口的固定位置
( 滚动页面时,它不会滚动到视图中)。
,,左,右,右。这些属性决定了元素( margin 框) 角的位置。
这些值被解释为偏移( displacements )。
:垂直偏移( + 向下移动,向上移动)
左( 右): 水平偏移( + 向右移动,左向左)
右下角:水平偏移( 向上移动,向上移动)
右: 垂直偏移( + 向左移动,向右移动)
这里属性通常与 block 元素一起使用"位置:静态";
它用于将元素的左侧或者右侧浮动到它的容器的左侧或者右侧
浮动元素周围的内容环绕。
( 如果设置了这里属性,则位置和偏移设置将被忽略。)

要确定偏移特性( ,,。)的值定义元素的特定边缘与它的容器的相应边缘( 内部边框) 之间的偏移。 在上, top的值定义定位元素的顶部 [left] 边缘到它的包含的block 顶端 [left] 边缘的距离。 符号( + 或者- ) 指定位移( bottom bottom/are are top top top top/。)的direction。 因此,正值将元素移动到包含 block的中心;负值将元素移出包含的block 中。

绝对定位

绝对定位用于将定位的元素放置在相对于一些封闭容器的固定位置上,相对于某些容器。 top/left/right/bottom 被解释为容器边框的偏移形式。 容器块是最近封闭块,具有位置值 static,如果没有找到这样的块,那么假定容器是浏览器窗口。

绝对定位接受"正常流量"的元素;即,绝对定位元素将占用它指定的区域,而不管它的他元素。 因此,绝对定位的元素可能与( 或者封面) 其他元素重叠。 这种情况下,可以使用 z-index 属性控制前回显示顺序。

绝对定位的元素有边框和 padding。 它们还可以有边距( 相对于指定的父容器,上面 )。

绝对定位图

作为绝对定位的例子,请考虑以下HTML+CSS代码示例和相关图。

div#A {position: absolute; top: 25px; left: 40px;
width: 300px; height: 120px; border: 1px solid #000; background-color:#CCC}
div#B {position: absolute; top: 20px; left: 50px; right: 30px;
bottom: 40px; border: 1px solid #000; background-color:#666}<divid="A"><divid="B"></div></div>

Absolute Positioning example 1

在本示例中,我们有两个划分: div#A 和 div#B,其中div#B是一个子域。 这两个部分绝对定位,因这里,每个将出现在某个固定位置,top/left/right/bottom 偏移量为 relative。

假设div#A不包含在任何具有非静态位置的block 中。 因此,div#A的top/left/right/bottom 偏移量的解释将在浏览器窗口中显示为 relative。 另一方面,div#B的定位将是 relative 到 div#A。

绝对定位的一些例子

下面是使用CSS定位的一个很好的例子。 概念是重叠两个分割以创建阴影( 或者浮雕浮雕) 效果,如下图所示:

Absolute Positioning example 2

可以使用以下HTML+CSS生成。

<style>div { font-size:24pt;font-family:georgia;font-style:italic;color:indigo; }</style><divstyle="position:relative;"><divstyle="position:absolute;left:0; top:0;">CSS Positioning is great!</div><divstyle="z-index:-1;position:absolute;left:2px;
top:2px;color:gray">CSS Positioning is great!</div></div>

为了达到上述结果,我们需要它的中一个重叠的部分有它的左/顶偏移略微(。2像素向下和向右)。 当顶部和左边的relative 被测量为包含两个重叠部分的分区时,这个过程就变得更容易了。 封闭分区需要将它的位置设置为绝对或者 relative ( 后者更适合于包含正常流的封闭部分)。

相对或内联定位

位置位置位置位置定位元素的位置通常在 top/left/right/bottom 使用一些设置( 在正常流量中)。 如果未给出偏移值,则元素将保持它的正常位置,由浏览器确定。 当指定偏移值时,元素将按照给定的( 通常情况下"左。右"还有一个"。底"需要指定以避免冲突) 和右键偏移。 最初由元素占用的区域将保留为空白( 这是 relative 定位的一个显著特点)。

例如可以用HTML将上标表示为( 这可能是使用 <emp> <sup> 标签的替代方法):

A<spanstyle="position:relative; top:-.7em;font-size:smaller">2</span>

使用 relative 定位,可以将文本放置在它的他文本的顶部和底部,如下面的示例所示:

Relative positioning example

这是使用以下HTML+CSS生成的。

<style>div#myDiv { font-size:24pt;font-family:georgia;margin:1em; }span.smallText { font-size:70%;}</style><diVid="myDiv">∑ x<sub>i</sub><spanclass="smallText"style="position:relative; top:-1.2em;
left:-2.4em;"><i>n</i></span><spanclass="smallText"style="position:relative;
top:1.2em;left:-3.2em;"><i>i</i>=1</span></div>
relative 定位的常用用途

relative 定位的一个常见用途是改变坐标系的原点( 从浏览器窗口到其他元素的top/left/bottom/right) )。 这利用了以下事实。

元素设置为"位置:相对"( 或者非 static ),它将成为它的的坐标系统absolutely绝对定位子元素 elements。

下面的示例演示了如何将四个子部分插入到他们父节点的四个角。 HTML+CSS代码如下所示:

<style>div.childDiv { position: absolute;border:1px solid green;width:150px;height:150px;text-align:center;line-height:150px; }</style><divstyle="position:relative; width:300px; height:300px;
 border:1px solid black;margin-left:30px;"><divclass="childDiv"style="background:#FEE;
 left:0;top:0">left:0;top:0</div><divclass="childDiv"style="background:#EEF;
 right:0;top:0">right:0;top:0</div><divclass="childDiv"style="background:#EFE;
 left:0;bottom:0">left:0;bottom:0</div><divclass="childDiv"style="background:#EEE;
 right:0;bottom:0">right:0;bottom:0</div></div>

前面的代码呈现以下内容:

Relative positioning example

让我们强调几个关于前面例子的要点。

  • 如果父部分的位置未指定( 或者设置为" static"),则子部门的坐标将引用浏览器窗口( 它的当前高度将决定" bottom"偏移量)。

  • 在子分区的位置为" fixed"时,它们将被固定到浏览器窗口的4 个角,并且不会滚动到页面的第三个角。

  • 注意用于在每个子分区中居中对齐文本的CSS样式。 " text-align:center"将使文本居中居中," line-height:150px"将文本垂直居中。

另一个好的使用 relative 定位的方法是将一个元素插入到某个位置 relative 到它的容器,如下图所示。

Relative positioning example

使用以下CSS+HTML代码生成 上面。

<style>div.roundDiv { margin:40px 40px;font-size:14pt;font-family:Tahoma;-moz-border-radius:.5em;-webkit-border-radius:.5em;border-radius:.5em; }
 div#A { border: 1px solid #e6db61;padding:8px;background:#fcf3c5;width:450px;background: -webkit-gradient(linear, 0 0, 0 100%, from(#fcfcfc), to(#fcf3c5));background: -moz-linear-gradient(top, #fcfcfc, #fcf3c5); }div#B { position:relative;font-weight:bold;left:16px;top:-32px;border:1px solid lightgray;margin:0;padding:4px;background-color:#CEFEFE;width:200px;height:40px;line-height:40px;background: -webkit-gradient(linear, 0 0, 0 100%,
 from(#fcfcfc), to(#e6e6e6));background: -moz-linear-gradient(top, #fcfcfc, #e6e6e6); }</style><divid="Div1"class="roundDiv"><divid="Div2"class="roundDiv"> Relative Positioning</div><pstyle="margin-top:-10px;"> The div for the title is positioned
 relatively (left=16px; top=-32px)
 </p></div>

topleft的任何设置中,div#B将被放置在 div#A ( div#A的padding 决定偏移量)的左上角。 "顶部:-32px"的设置向上移动 32像素,"左:16px"的设置将它的移动到右侧的16像素。

注意div#B中的段落元素设置为负上边距,以便在div#B移动时将它的移到空的区域。

有用的链接


相关文章