圆角是最常用的CSS技术之一。 与CSS中的许多内容一样,可以通过多种方法来解决此问题。 在本文中,我将介绍一些常用技术的优缺点,并介绍一种同时利用CSS和JavaScript的新技术。
在开始使用CSS之前,让我们想起解决此问题的老式方法,该方法使用布局表:
<table width="200" cellpadding="0" cellspacing="0">
<tr>
<td width="15"><img src="tl.gif" alt="" /></td>
<td bgcolor="#1b5151"></td>
<td width="15"><img src="tr.gif" alt="" /></td>
</tr>
<tr bgcolor="#1b5151">
<td> </td>
<td>Content goes here</td>
<td> </td>
</tr>
<tr bgcolor="#1b5151">
<td><img src="bl.gif" alt="" /></td>
<td></td>
<td><img src="br.gif" alt="" /></td>
</tr>
</table>
几年前,这是一个可以接受的解决方案。 如今,这是一个丑陋的骇客:对于相对不重要的视觉装饰,这是很多多余的标记。 实际上,上述代码甚至无法在使用严格doctype的文档中按预期方式工作-由于图像是内联元素,因此在图像下方会出现小间隙,这是因为图像是内联元素,因此在图像下方留有空间字母“ y”和“ j”上的“尾巴”。 正如Eric Meyer在“ 图像,表格和神秘间隙”中所解释的,该解决方案是在样式表中添加以下规则:
td img { display: block; }
这产生所希望的结果,如图这里 。
但是,现在我们正在使用CSS hack来修复丑陋的表格hack! 让我们看看仅使用CSS来实现相同效果的方法。
通常,任何装饰图像都应在现有页面元素上实现为CSS背景图像,而不是使用<img>
标记正确放置到页面中。 很容易确定图像是装饰性的还是包含实际内容:问自己是否缺少图像会对页面的整体内容有任何影响。 如果是圆角,答案显然不是。
CSS背景图片非常强大。 您只需要查看CSS Zen Garden上展示的许多精彩设计,就可以证明这一点。 使用CSS,可以将背景图像应用于页面上的任何元素。 此外,它可以水平,垂直或根本不重复; 它可以使用绝对测量值定位在图像的背景区域内,也可以相对于四个角之一定位; 当元素的内容滚动时,甚至可以将其固定在适当的位置。 不幸的是,CSS 2施加了一个小但重要的限制:您只能将单个背景图像应用于页面上的每个元素。 为了在<div>
上正确渲染圆角,我们需要应用四个背景图像,每个角上一个。
定宽框
如果我们要应用装饰角的盒子的宽度固定,那么一半的问题已经解决。 如果我们知道该框将始终为200像素宽,而不是创建四个背景图像(每个角一个),则可以创建两个:一个用于框的顶部,一个用于框的底部。 现在的挑战减少到将两个背景图像应用于我们的<div>
。 现在是时候利用我们的标记了。
如果一个圆角的盒子不包含任何内容,那将不会很有趣。 考虑以下:
<div class="rounded">
<h3>Exciting features!</h3>
<p>Your new Widget2000 will...</p>
<ul>
<li>... clean your shoes</li>
<li>... walk your dog</li>
<li>... and balance your cheque book!</li>
</ul>
</div>
很简单吧? 框的标题位于<h3>
(我假设<h1>
和<h2>
在页面的层次结构中已被使用过),其后的内容是一个段落和一个无序列表。 解决我们两个背景问题的关键在于<h3>
,它位于框顶部。 我们要做的就是在<h3>
的顶部应用背景图像,在包含的<div>
的底部应用背景图像,效果就完成了:
div.rounded {
width: 200px;
background: #1b5151 url(200pxbottom.gif) no-repeat bottom center;
padding-bottom: 15px;
}
div.rounded h3 {
padding-top: 15px;
background: transparent url(200pxtop.gif) no-repeat top center;
}
单击此处查看结果。
结构良好的文档通常到处都是这样的钩子,可以仔细利用它们以应用多个背景并实现特定的视觉效果。 学会识别它们是使用CSS的重要部分。
嵌套元素
将四个背景应用于单个div仍然无法实现。 但是,如果我们嵌套四个div,每个背景一个,该怎么办? 这样做可以解决我们的问题,但是要以没有结构价值的附加标记为代价:
<div class="rounded"><div><div><div>
Content goes here
</div></div></div></div>
并且,在CSS中:
div.rounded {
width: 200px;
background: #1b5151 url(tr.gif) no-repeat top right;
}
div.rounded div {
background: transparent url(tl.gif) no-repeat top left;
}
div.rounded div div {
background: transparent url(br.gif) no-repeat bottom right;
}
div.rounded div div div {
background: transparent url(bl.gif) no-repeat bottom left;
padding: 15px;
}
代码显示如图这里 。
应该清楚这里发生了什么。 四个div中的每个div被分配一个圆角背景图像,分别位于右上角,左上角,右下角和左下角。 尽管包含div的宽度设置为200像素,但可以很容易地将其设置为更灵活的方式以用于液体设计-无论包含div的大小如何,拐角仍将起作用。
现在,我们有了一个解决问题的方法,该方法比原始表示例使用的标记少得多。 但是,它仍然不是完美的:它使用了三个额外的div,这对整个文档结构没有任何价值。 我们可以做得更好吗? 现在该看看JavaScript。
使用DOM
使用JavaScript和DOM,可以在浏览器加载文档后操纵文档的结构。 圆角是一种呈现效果,可以对非JavaScript用户代理隐藏,而不会显着降低其网站的整体体验,因此使用JavaScript进行这种转换不会产生道德问题。 我们的最终解决方案只需要源文档中的单个<div>
。 我们将使用JavaScript动态添加圆角效果所需的三个多余的div。
这是标记:
<div class="rounded">
Content goes here.
</div>
我认为您会同意,除了将内容在结构上更好地定义为段落之外,也许可以将<div>
替换为<p>
,我们没有什么能使它变得更简单了。 进行此切换留给读者练习。
现在是JavaScript:
function roundedCorners() {
var divs = document.getElementsByTagName('div');
var rounded_divs = [];
/* First locate all divs with 'rounded' in their class attribute */
for (var i = 0; i < divs.length; i++) {
if (/broundedb/.exec(divs[i].className)) {
rounded_divs[rounded_divs.length] = divs[i];
}
}
/* Now add additional divs to each of the divs we have found */
for (var i = 0; i < rounded_divs.length; i++) {
var original = rounded_divs[i];
/* Make it the inner div of the four */
original.className = original.className.replace('rounded', '');
/* Now create the outer-most div */
var tr = document.createElement('div');
tr.className = 'rounded2';
/* Swap out the original (we'll put it back later) */
original.parentNode.replaceChild(tr, original);
/* Create the two other inner nodes */
var tl = document.createElement('div');
var br = document.createElement('div');
/* Now glue the nodes back in to the document */
tr.appendChild(tl);
tl.appendChild(br);
br.appendChild(original);
}
}
/* Run the function once the page has loaded: */
window.onload = roundedCorners;
该脚本分为两个逻辑部分。 第一部分遍历文档中的所有<div>
元素,构建一个在其class
属性中包含'rounded'
元素的数组(请记住,元素可以具有多个由空格分隔的类)。 脚本的第二部分依次遍历这些元素中的每一个,创建了三个附加的div,并将它们包装在原始元素周围。 让我们更详细地看一下代码:
original.className = original.className.replace('rounded', '');
在这里,我们从原始<div>
完全删除了"rounded"
类。 原因将在CSS中明确; 本质上,我们不希望应用原始样式再影响该元素。
var tr = document.createElement('div');
tr.className = 'rounded2';
我们创建了最外面的<div>
,它将用于应用右上角的背景图像以及盒子的整体宽度。 注意,我们已经将该类设置为'rounded2';
这将在我们的CSS中定义,与提供给未启用JavaScript的客户端的'rounded'
类的细微差别。
/* Swap out the original (we'll put it back later) */
original.parentNode.replaceChild(tr, original);
W3C DOM没有提供将文档中的节点替换为另一个节点的直接方法。 相反,您必须使用节点的replaceChild()
方法将其子节点之一替换为另一个节点。 替换您要查看的节点的有用技巧是使用parentNode
属性访问其自身的父节点,然后使用/#c#.replaceChild将该节点交换为其他节点。 如果这对您没有意义,请不要担心-只需将上述行视为将我们的原始节点替换为我们刚刚创建的新tr
节点即可。
/* Create the two other inner nodes */
var tl = document.createElement('div');
var br = document.createElement('div');
/* Now glue the nodes back in to the document */
tr.appendChild(tl);
tl.appendChild(br);
现在,我们创建了三个新的<div>
元素并将其插入到文档中。 剩下的就是重新插入我们的原始节点,并完成其内容:
br.appendChild(original);
在这一点上,我们的实际文档树几乎与上面四个嵌套的<div>
示例中的树相同,唯一的区别是外部元素的类为'rounded2'
而不是'rounded'
。 这是CSS:
div.rounded {
width: 170px;
padding: 15px;
background: #1b5151;
}
div.rounded2 {
width: 200px;
background: #1b5151 url(tr.gif) no-repeat top right;
}
div.rounded2 div {
background: transparent url(tl.gif) no-repeat top left;
}
div.rounded2 div div {
background: transparent url(br.gif) no-repeat bottom right;
}
div.rounded2 div div div {
background: transparent url(bl.gif) no-repeat bottom left;
padding: 15px;
}
这是结果。
第一组规则div.rounded
仅在不执行JavaScript的浏览器中使用。 请注意,宽度为170像素,填充为15像素,这总计为200像素(宽度加上左右填充)。 如果您需要在IE 5 / Windows中使用此方法(对填充值的解释不同),则需要应用臭名昭著的Box Model hack 。 您已经在上一个示例中看到了第二组规则。
展望未来
以上技术将在所有现代浏览器以及所有将来支持CSS2和DOM 2标准的浏览器中使用。 CSS 3引入了许多实现此效果的新方法,这将使上述技术过时。 CSS不仅具有本机圆角支持 (已在Mozilla系列浏览器中提供),还具有强大的:: outside伪元素 ,该伪元素允许以类似于本文所示JavaScript示例的方式插入其他可样式化元素。 如果这还不够的话, 边框图像将几乎允许您想到的任何边框装饰。
不幸的是,要获得CSS 3支持还需要很多年。 在此之前,JavaScript能够胜任某些工作。
From: https://www.sitepoint.com/rounded-corners-css-javascript/