如何用css实现网页中装饰性圆角

如何实现网页中装饰性圆角

原文地址: http://www.sitepoint.com/article/rounded-corners-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>
几 年前 ,这可能还是相当流行的解决方法。但是今天,这就显得有些落后了:在一个相对不太重要的视觉装饰中充斥着太多没有用的标记。实际上,上面的代码在使用严格 的文本格式的页面中甚至不会起作用--在圆角图片的下面出现小间隙。这是因为图像使行内元素,因此要在图像的下面为诸如y和j这样的文字留出空间。解决方 法Eric Meyer在 Images, Tables and Mysterious Gaps一文中已经给出,就是在你的样式表中添加下面的代码:
td img { display: block; }

这就能产生预期的效果。点此查看

但是现在使用CSS就可以弥补这些表格的缺陷。下面我们来看看如何只用CSS就能产生同样的效果。
作 为一个通用的规则,任何装饰性的图片都应该设置成已有页面元素的CSS的背景图片,而不是简单的运用一个<img>标签。我们很容易判断一张 图片是装饰性的或者是包含了实际内容:考虑一下這張图片对于页面整体内容是否有影响。在装饰性圆角这种情况下,显然图片是没有什么用的。
css背景图片是相当有用的东西。你只要看看在CSSZengarden里面任何好的CSS设计,就会发现这一点。使用 CSS,背景图片可以运用到任何页面元素上。
固定宽度的Box
如 果我们要用到装饰边角的box的宽度是固定的,那么问题就已经解决一半了。如果我们知道Box总是200px宽的话,我们就不需要为四个边角都创建图片, 而只需要创建上面和下面两个边角。问题现在就降为运用两个背景图片到我们的<div>中。一个有圆角的box如果没有包含任何内容话那会很无 趣。所以我们先设置一些内容。
考虑以下代码:
<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>

相 当简单吧?!box的标题是<h3>的样式(我假设<h1>和<h2>已经被使用到了更高级别的文本样式),接下来 的内容是一个段落和一个无序的列表。解决我们背景问题的关键在于<h3>,它应该处在box的 顶部。我们所要做的就是运用背景图片到<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容器的宽度设置成200px,就很容易设置成更加灵活的宽度数值,而边角仍然可行,不论这个DIV容器多大多小。

我们现在有了对于上面所说问题的一个可行的方案,它不需要像表格那样使用很多的标记,但是仍然不是最好的方法。它使用了三个额外的DIV,而这点对于整个页面布局来说是没有意义的。我们如何才能做的更好呢?到了看看JavaScript的时候了。

使用DOM
使 用JavaScript和 DOM就可以控制浏览器载入后的网页。圆角是一个不会明显减少非JavaScript用户浏览体验的典型效果,所以这不会存在使用JavaScript来 进行转换的道德问题。我们的最终解决方法只需要在源文件中加入一个div。我们可以使用JavaScript来自动增加其余三个圆角。
下面是标记:

<div class="rounded">
Content goes here.
</div>


我想你应该同意我们不能做的比这个更为简单了,除非改变<div>为<p>,如果内容定义为段落更加合适的话。这个转换就留给读者作为练习吧。
下面是JavaScript代码:
Now here's the 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 (//brounded/b/.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;

The script is divided in to two logical sections. The first section iterates over all of the <div> elements in the document, building an array of those that contain 'rounded' in their class attribute (remember, elements can have multiple classes separated by spaces). The second part of the script goes through each of these elements in turn, creating three additional divs and wrapping them around the original. Let's look at the code for that in more detail:
代码分为两个部份。第一部分是初始化页面中的 <div>元素,建立一个包含“ 圆角” 属性的队列(记住,元素可以根据空间分划分为很多类)。第二部分是依次运行这些元素,创建三个额外的div并且使它们隐藏在第一个周围。下面是更为详尽的 代码解释(出于懒惰的原因,我没有翻下去)

点此查看效果

所有先进的浏览器和未来支持CSS2 和 DOM2的浏览器都支持上面的技术。CSS3引进了一些新的方法以达到上面的效果,这将使上面的方法都看起来落后了。
不幸的是,CSS3标准的普及还需要很长时间。在那时之前, JavaScript可能使最好的方法了。

Rounded Corners with CSS and JavaScript

By Simon Willison
May 28th 2004
Reader Rating: 8.7

Rounded corners are one of the most frequently requested CSS techniques. As with many things in CSS, there are various ways in which this problem can be approached. In this article, I'll look at the pros and cons of some common techniques and introduce a new technique that utilises both CSS and JavaScript.

Before we dive in to the CSS, let's remind ourselves of the old fashioned approach to this problem, which uses layout tables:

<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>&nbsp;</td>
 <td>Content goes here</td>
 <td>&nbsp;</td>
</tr>
<tr bgcolor="#1b5151">
 <td><img src="bl.gif" alt="" /></td>
 <td></td>
 <td><img src="br.gif" alt="" /></td>
</tr>
</table>

A few years ago this would have been an acceptable solution. Today, it's an ugly hack: that's an awful lot of redundant markup for a relatively unimportant visual decoration. In fact, the above code won't even function as intended in documents served using a strict doctype -- small gaps will appear beneath the corner images, caused by the fact that images are inline elements and, hence, leave space beneath the image for the "tails" on letters such as 'y' and 'j'. The solution, as explained by Eric Meyer in Images, Tables and Mysterious Gaps, is to add the following rule to your stylesheet:

td img { display: block; }

This produces the desired result, as shown here.

But, now we're using CSS hacks to fix ugly table hacks! Let's look at ways to implement the same effect using only CSS.

As a general rule, any decorative image should be implemented as a CSS background image on an existing page element, rather than being dropped in to the page proper using an <img> tag. It's easy to determine whether an image is decorative or contains actual content: ask yourself if the absence of the image would have any effect on the overall content of the page. In the case of rounded corners, the answer is obviously not.

CSS background images are remarkably powerful things. You need only look at the many wonderful designs on display at the CSS Zen Garden for evidence of that. Using CSS, a background image can be applied to any element on a page. Furthermore, it can be repeated horizontally, vertically or not at all; it can be positioned within the background area of the image using absolute measurements, or relative to one of the four corners; it can even be made to stay fixed in place when the element's content scrolls. Unfortunately, CSS 2 imposes one small but significant limitation: you can only apply a single background image to each element on the page. To properly render rounded corners on a <div> we need to apply four background images, one in each corner.

Fixed Width Boxes

If the width of the box to which we're applying decorative corners is fixed, half of the problem is solved already. If we know that the box will always be 200 pixels wide, instead of creating four background images (one for each corner), we can create two: one for the top of the box and one for the bottom. The challenge is now reduced to applying two background images to our <div>. It's time to take advantage of our markup.

A box with rounded corners wouldn't be much fun if it didn't contain any content. Consider the following:

<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>

Pretty simple, huh? The title of the box lives in an <h3> (I'm assuming <h1> and <h2> have already been used further up the page's hierarchy) and the content that follows is a paragraph and an unordered list. The key to solving our two background problem lies in the <h3>, which comes right at the top of the box. All we have to do is to apply a background image to the top of the <h3>, and another to the bottom of the containing <div>, and the effect is complete:

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;
}

Click here to see the results.

Well-structured documents are usually full of hooks like this that can be carefully exploited to apply multiple backgrounds and achieve specific visual effects. Learning to identify them is an important part of working with CSS.

Nested Elements

Applying four backgrounds to a single div is still out of our reach. But what if we nested four divs, one for each background? Doing so solves our problem, but comes at the expense of additional markup with no structural value:

<div class="rounded"><div><div><div>
Content goes here
</div></div></div></div>

And, in the 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;
}

The code displays as shown here.

It should be clear what's going on here. Each of the four divs is assigned a rounded corner background image, positioned in the top-right, top-left, bottom-right and bottom-left respectively. While the width of the containing div is set to 200px, it could just as easily be set to something more flexible for use with liquid designs -- the corners would still work, no matter how large or small the containing div was.

We now have a solution to the problem, which uses far less markup than the original tables example. But, it's still not perfect: it uses three extra divs, which add nothing of value to the overall document structure. Can we do any better? It's time to look to JavaScript.

Using the DOM

Using JavaScript and the DOM, it's possible to manipulate the structure of a document after it has been loaded by the browser. Rounded corners are a presentational effect that can be hidden from non-JavaScript user agents without any significant reduction in their overall experience of the site, so there are no ethical problems with using JavaScript for this kind of transformation. Our final solution will require only a single <div> in the source document. We will use JavaScript to dynamically append the three extraneous divs needed for the rounded corner effect.

Here's the markup:

<div class="rounded">
Content goes here.
</div>

I think you'll agree that there's not much we can do to make it simpler than that, except maybe exchange the <div> for a <p> if the content is structurally better defined as a paragraph. Making this switch is left as an exercise for the reader.

Now here's the 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 (//brounded/b/.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;

The script is divided in to two logical sections. The first section iterates over all of the <div> elements in the document, building an array of those that contain 'rounded' in their class attribute (remember, elements can have multiple classes separated by spaces). The second part of the script goes through each of these elements in turn, creating three additional divs and wrapping them around the original. Let's look at the code for that in more detail:

original.className = original.className.replace('rounded', '');

Here we remove the class "rounded" entirely from our original <div>. The reason for this will become clear in the CSS; essentially, we don't want the original styles applied to affect that element any more.

var tr = document.createElement('div');
tr.className = 'rounded2';

We have created out outer-most <div>, which will be used to apply the top-right background image as well as the overall width of the box. Note that we have set the class to 'rounded2'; this will be defined in our CSS, with subtle differences from the 'rounded' class provided to non-JavaScript-enabled clients.

/* Swap out the original (we'll put it back later) */
original.parentNode.replaceChild(tr, original);

The W3C DOM does not provide a direct method to replace a node in a document with another node. Instead, you must use the replaceChild() method of a node to replace one of its children with another node. A useful trick to replace the node you're looking at is to access its own parent using the parentNode property, then use /#c#.replaceChild to swap it for something else. If that doesn't make sense to you, don't worry -- just think of the above line as replacing our original node with the new tr node we have just created.

/* 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);

We've now created three new <div> elements and inserted them in to the document. All that's left is to re-insert our original node, complete with its contents:

br.appendChild(original);

At this point, our actual document tree is almost identical to that in the four nested <div> example above, the only difference being that the outer element has a class of 'rounded2' instead of 'rounded'. Here's the 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;
}

Here's the result.

The first set of rules, for div.rounded, is only used in browsers that do not execute the JavaScript. Note that the width is 170px and the padding 15px, which adds up to a total width of 200px (the width plus the left and right padding). If you need this to work in IE 5/Windows, which interprets padding values differently, you'll need to apply the infamous box model hack. You've already seen the second set of rules in the previous example.

Looking Ahead

The above technique will work in all modern browsers, and all future browsers that support the CSS2 and DOM 2 standards. CSS 3 introduces a number of new ways to achieve this effect, which will render the above techniques obsolete. As well as native rounded corner support (already available in the Mozilla family of browsers) CSS features the powerful ::outside pseudo-element, which allows additional stylable elements to be inserted in a manner similar to the JavaScript example shown in this article. If that's not enough, border images will allow pretty much any border decoration you could care to think of.

Unfortunately, it will be years before CSS 3 support is widely available. Until then, JavaScript is more than capable of taking up some of the slack.

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值