`
wzg489326
  • 浏览: 47020 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

The Positive Side of Negative Margins(翻译未完成)

阅读更多
在写页面时遇到,margin为负的情况。ie6下不显示。在网上搜到这样一篇详解margin为负的各种情况。解决了问题。
http://www.search-this.com/2007/08/01/the-positive-side-of-negative-margins/
第一次翻译,水平不足。见笑了。
I've been thinking negatively once again and instead of keeping my thoughts to myself I thought I'd share them with you. In this article we look at how negative margins work and how to apply them in everyday usage.

   我费尽心思的分析负margin,在这里分享给大家而不是自己独享。在这篇文章中大家会认识到 负margin 的原理,以及在平时中如何运用。

A number of people suffer under the misconception that negative margins are in some way a hack; they are not. In fact negative margins are valid CSS and extremely useful in certain situations. They only become a hack if you are using them to fix an error that you have made elsewhere. In normal usage negative margins work quite well and are supported across modern browsers. However, there are issues if you use negative margins on the opposite side of a float (e.g. floating left and then using a negative margin on the right) although most modern browsers now behave the same way when this happens. In some of the examples below you will see what I mean. Let's dive in!

     一部分人错误的认为 负margin 是hack的一种,其实不是。在一些情况下 负margin 是一个css特定有效的用法。如果你处理由于自己造成的一些错误时用到了 负margin 那么它就成了hack了。负margin在正常的运用中能够起到很好的效果并且现在流行的浏览器都能够支持。但是当你在一个浮动元素相反的方向 负margin时 尽管现在大部分浏览器都用相同解释在这种情况下 但是仍然会  出现问题(例如:向左浮动margin-right为负的)。通告下面的一些例子你就会明白。我们深入看一下!

Negative Margins on Static Elements

在静态元素上的负margin。

First we'll look at how non-positioned (static) elements behave when negative margins are used. In order to do this we need a point of reference so we can see the effect. Therefore we will construct a number of paragraphs that all have a 20px top and bottom margin. You may recall from my collapsing margin article that adjacent margins of static elements will collapse into one margin. So each paragraph will be 20px apart. 

首先 我们看一下在静态元素上负margin是怎么表现的。为了更好的能看出效果我们需要a point of reference{这个不知怎么翻译。}.因此我们要对比一组 margin-top,margin-bottom都是20px的P。你可能会想起我的 my collapsing margin文章 两个相邻静态元素的margin将会重合。因此每一段将有20px的间距。
例如:
CSS:
      p{
         margin:20px 0;
         height:40px;
         background:#ffffcc;
         border:1px solid #000;
      }
HTML:

      <p>This is the paragraph 1</p>
      <p>This is the paragraph 2</p>
      <p>This is the paragraph 3</p>
      <p>This is the paragraph 4</p>
      <p>This is the paragraph 5</p>



If you run the above code you will see a display like Figure 1.
Figure 1:


Now let's suppose you wanted the second paragraph to be only 5px away from the one above it, how would you achieve this? First you would need to add a class to the first and second paragraphs. Secondly, you give paragraph 1 a 5px bottom margin and paragraph 2 a 5px top margin (look for the margins to collapse into one).

  现在我们想第二个段落与它上面的只是间隔5px,你怎么实现?首先你要分别给这两个P添加一个 class名。然后设置第一个p margin-bottom:5px和第二个P margin-top:5px;
{两个间距重合一起了。}
CSS:
      p.top{margin:20px 0 5px 0}
      p.bottom {margin:5px 0 20px 0:}

HTML:

      <p class="top">This is the paragraph 1</p>
      <p class="bottom">This is the paragraph 2</p>
      <p>This is the paragraph 3</p>
      <p>This is the paragraph 4</p>
      <p>This is the paragraph 5</p>

As expected this produces exactly what we want in Figure 2.
Figure 2:


The gap is now 5px between paragraphs 1 and 2 and the rest have the original 20px margins.

  现在在paragraphs 1 和paragraphs2 的间距是5px;其他的还是20px;

Could we have done this with less code?

As a matter of fact we can reduce the code considerably if we use a negative margin on the second paragraph. By applying a negative margin of -15px on the second paragraph we get exactly the same effect.

  事实上如果我们在第二段上用负margin可以大大减少代码量。通过在第二段上用-15的margin我们可以实现相同的效果。

 css:
      p.bottom {margin:-15px 0 20px 0;
HTML:

      <p>This is the paragraph 1</p>
      <p class="bottom">This is the paragraph 2</p>
      <p>This is the paragraph 4</p>
      <p>This is the paragraph 5</p>

The negative 15px margin pulls the second paragraph upwards by 15px without moving paragraph 1 and leaves us with a 5px gap exactly as shown in figure 2 above. This saves us 1 line of CSS and also saves us from adding a class to both the first and second paragraphs. Therefore, for cleaner code the negative margin approach wins hands down!

margin-top:-15px;把第二段向上提了15px,而没有改动第一段从而实现了图2的效果。这样节省了一行css还不用在两段上都添加calss名。因此为了代码更简洁,负margin更可取。

It should be noted that if you wanted to pull the paragraph up further so that it overlapped the one above then you would need to add position:relative to the mix so that you can control the stacking context with z-indexes. Although by default the bottom paragraph will usually overlap the top but this is not always the case and it is left up to the User Agent to decide where nothing has been set explicitly. (It should also be noted that IE will usually prefer position relative to be added if you pull an element out of its parent container when using negative margins, otherwise on occasions it hides the part that is sticking out.)

   如果你还想把段落提的更高,显而易见它将会和上面的段落重叠,现在你需要在重叠的段落上添加postion:relative通过z-indexes来控制这两个段落。在没有特殊设置的情况下通常margin-top 为负的段落会覆盖 他上面得,但并不是总是这样。这取决于 。。。。(
如果你通过负margin 使得元素超出父容器在ie下通常情况下需要加position relative ,否则超出的部分将不会显示。


So we have established that on static elements positive margins collapse to the greater margin set but when a negative margin is thrown into the mix then the negative margin is subtracted from the positive margin to reveal the final margin. (e.g. In the example above 20-15 = 5). Therefore it's easy to deduce that if the negative margin is greater than the positive margin then some sort of overlap will take place. This is worth a quick example -- using the code above but amended as follows.

CSS:
      p.bottom {margin:-35px 0 20px 0;}


Our calculations will say that -35px - 20px = -15px, which should give us a 15px overlap with the lower paragraph over the top.

As you can see from figure 3 that is exactly what happens.
Figure 3:

(I shifted the second paragraph a little to the right so you could see that is does overlap the one below.)

The above example shows that negative margins will cause static elements to overlap, unlike positive margins which push static elements away. So using negative margins in the above manner is in fact very safe and shouldn't cause any problems at all for the modern browsers.

Next let's look at another useful method -- how to make the box on the inside wider than its parent.

The space on the inside is bigger than the space on the outside.

This has nothing to do with the space time continuum and is simply a matter of applying negative margins to both sides of a container. We will construct a fixed width container and then drag the inner container outside of the parent using negative margins to pull both left and right sides outside of the parent. Here is the code to do this:

CSS:
      .outer{
      margin:50px;
      padding:20px 0;
      width:200px;
      background:#ffffcc;
      border:1px solid #000;
      }
      .outer p {
      margin:0 -20px;
      background:red;
      color:yellow;
      border:1px solid #000;
      padding:5px;
      }
HTML:

      <div class="outer">
      <p>This is the paragraph that we want to stretch outside the parent for a neat effect</p>
      </div>



If you run this code in Firefox 2.0 you will get the desired result as shown in figure 4.
Figure 4:

However, if we look at IE6 and IE7 we get rather different results as shown in figure 5.

Figure 5:


Hmmm... that looks strange - what happened here?

In IE6 the negative margins are completely missing and in IE7 the right negative margin portion is missing.

IE7 is quite easy to fix -- we just need to ensure that "haslayout" is true for the inner element. This can easily be done by applying min-height:0 which is one of the properties that will cause "haslayout" to be true in IE7. The min-height:0 is 100% safe and doesn't need to be hidden from any browsers at all. As can be seen in figure 6 this completely rectifies the issue with IE7.

Figure 6:


Since IE6 doesn't understand min-height it won't cause "haslayout" to be true and therefore nothing changes; both sides of the inner box are still missing. The usual fix to apply layout to IE6 is to use the height:1% hack and if we try that we get the result as shown in figure 7.

CSS:
      * html .outer p{height:1%;}


Figure 7:


As you can see, this doesn't work very well; we get the rather strange effect seen above. If you remember earlier I mentioned that position:relative should be used to rectify stacking problems. So let's see what happens if we add position:relative.

CSS:
      * html .outer p{height:1%;position:relative}


Figure 8:


That's a little better but the element is just shifted to the left and does not overhang the right side as it should. You might start thinking that it can't be made to work in IE6, but the solution is very close. If instead of using the height:1% hack we use the height:1px hack suddenly everything falls into place exactly as we want! This also fixes the layout for IE5, 5.5 and 6!

CSS:
* html .outer p{height:1px;position:relative}

Figure 9:


Why height:1px works in this case and height:1% doesn't work is a bit of a mystery as they both cause "haslayout" to be in place. It was thought that perhaps the 1% height defaulted to height:auto because the parent has no height. However, this doesn't seem to be the answer because the effect is the same even if you give the parent a specific height so that the percentage height can work correctly as it has something to base its height on. It would be nice to know exactly why there is a difference here but for the time being we'll just have to be happy to know that height:1px works for us.

Here is the full code to satisfy IE5 - 7:
      .outer{
      margin:50px;
      padding:20px 0;
      width:200px;
      background:#ffffcc;
      border:1px solid #000;
      }
      .outer p {
      margin:0 -20px;
      background:red;
      color:yellow;
      border:1px solid #000;
      padding:5px;
      min-height:0;
      }
      /* mac hide \*/
      * html .outer p{height:1px;position:relative;}
      /* end hide */


Note that the star selector hack is used here to supply the hack to only IE versions 6 and under so that other browsers do not see the height; otherwise they will limit the element to 1px height. The hack should also be hidden from IE5 Mac as it treats height correctly; so it doesn't need the hack anyway. The strange comments are the Mac hiding hack and filter out IE5 mac from reading the styles between the comments.

In the next section we will look at how using negative margins on floats display different characteristics from those shown above.

Negative Margins and Floats

In the previous section we saw that adding negative margins to a static container pulls the container in the direction specified (e.g. margin-top:-15px pulls the container 15px towards the top). We also learned that adding negative margins to opposing sides of the element pulls the element in both those directions thus increasing the width of the element.

Now we'll look at Floats, which as we'll see are a different beast altogether. Floats posses some behaviors to watch out for and some to utilize.

If you float an element left you will find that adding a left negative margin will pull the element in that direction much the same as explained already for static containers. However, if you try to use a negative margin on the right side of a left floated element (or vice versa for a right floated element with a left negative margin) you will find that things aren't all that they seem.

Using the code below we apply a negative right margin to a left floated element.

CSS:
      .float{
      float:left;
      padding:10px;
      width:100px;
      background:#ffffcc;
      border:1px solid #000;
      height:100px;
      margin-left:20px;
      }
      .one {margin-right:-50px ;}
      .two{
      background:red;
      color:yellow;
      height:90px;
      }

HTML:

      <div class="float one">
      <p>Float 1</p>
      </div>
      <div class="float two">
      <p>Float 2</p>
      </div>


This does not move the float towards the right as happens with static containers, but instead does almost the opposite -- the right margin of the float appears to be moved 50px inside itself!

If you look at figure 10 below you can see how the second floated element is assuming that the first float's margin is 50px away from where it was originally and the second float overlaps the first.

Figure 10:

Looking at the image above you can see that float1 doesn't seem to have changed in any way -- it's in the same position with the same width. The only implication of the negative margin is that other elements now treat float1 as though it was 50px smaller in width than it actually is. What's interesting is that as far as any content inside float1 is concerned nothing has changed and the content will still use the full width available in float1. This will of course result in content being hidden if other elements overlap!

Yes - but what use is this?

So we have established that the right negative margin allows elements to approach from that side, but is that any real use to us?

As it happens, it can be used to solve a common problem where it is required for 2 floats to be side-by-side and to stretch to 100% width but where one float has a fixed pixel width. In this scenario you can easily set one float to 200px width but you can't set the other float to 100% - 200px width. Usually this is resolved by floating the 200px width element and then using a static container with a margin big enough to avoid the float. This method works ok but it suffers badly from the three pixel jog and associated bugs in IE6 and under. It also suffers from the fact that the floated element must be first in the source order in order to work.

By using our knowledge of the negative margin behavior we can use this to our advantage to enable 2 floats to stretch to 100% width exactly. We do this by first setting one float to 100% width and give it a 200px negative right margin. We then simply float our second element with a 200px width.

CSS:
      .float{
      float:left;
      background:#ffffcc;
      height:100px;
      margin-right:-200px
      }
      .one {width:100%}
      .two{
      background:red;
      color:yellow;
      width:200px;
      height:90px;
      margin:0;
      }
HTML:

      <div class="float one">
      <p>Float 1</p>
      </div>
      <div class="float two">
      <p>Float 2</p>
      </div>


This gives the result as seen in Figure11.

Figure 11:

The drawback here is that any content in float one will be hidden underneath float2 as shown in figure 12.

Figure 12:


The solution to this is pretty simple -- we just need to ensure that any content we place in float one has a margin-right that will keep it clear of the right float. This can be done by either nesting a div inside and applying a margin to the div so that all content in the div is kept clear or by applying a margin to all the individual elements inside.
e.g.
CSS:
      .one p{margin-right:210px}


Figure 13:


This results in 2 floated columns that stretch to 100% width, without suffering from the three pixel jog, and are not source order dependent.

It does look a little messy -- if we want to tidy it up we can remove the colours from the parent floats which were just for demonstration purposes and apply some styling to an inner container instead.
CSS:
      .float{
      float:left;
      margin-right:-200px
      }
      .one {width:100%}
      .two{
      width:200px;
      height:90px;
      margin:0;
      }
      .one p{margin-right:210px}
      p{
      background:red;
      color:yellow;
      border:1px solid #000;
      }



(The HTML is exactly as already shown above.)

And here is the result as shown in figure 14.

Figure 14:

We now have our 2 columns working quite nicely!

When 100% - 100% = 0

I should point out that if you make the right negative margin equal to the elements total width then effectively the element becomes 0px wide. This is because margins, padding, borders, and width add up to the total width and therefore if the negative margin is equal to the rest of the dimensions then the elements width effectively becomes 0px. This doesn't really affect anything in modern browsers as they will still work as per the examples above. However, in browsers previous to Mozilla 1.6 and equivalent they will almost treat the element as though it were not there much in the same way that an absolute element behaves. This makes it impossible to clear the float and it will always overlap content underneath. This does not happen in IE and Firefox 2.0. If you make sure that your negative margin is smaller than the total width of the element concerned then this problem is avoided (or if you don't care about older browsers then don't worry).

In this article we have covered the different ways that negative margins can be used and how the behavior differs between floated and static elements. We have also observed and squashed some bugs in IE and in the final example demonstrated how to effect 2 floated columns that stretch 100% wide where one column is a fixed width.

The examples above will work on most modern browsers, but have been specifically optimized for IE5 - 7 and Firefox 2.0 only and you should therefore check in the browsers you want to support when using these advanced methods.



    
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics