【问题标题】:How do CSS triangles work?CSS 三角形是如何工作的?
【发布时间】:2011-10-27 18:12:56
【问题描述】:

CSS Tricks - Shapes of CSS 上有很多不同的 CSS 形状,我对三角形特别困惑:

#triangle-up {
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 100px solid red;
}
<div id="triangle-up"></div>

它是如何以及为什么起作用的?

【问题讨论】:

  • 您可以:jsfiddle.net/wbZet
  • 那不存在的广场呢? jsfiddle.net/minitech/sZgaa
  • @mskfisher 你的等边三角形底边的大小不应该是 ceil(sqrt(3) * 60) 吗?再多几个像素!
  • @Niloct:我在整数上快速观察了它。你是对的,更准确的等边测量值将是 (side:58,bottom:100) 或 (side:60,bottom:104)。
  • 这是一个适用于所有方向和尺寸的出色的 CSS 三角形生成器apps.eky.hk/css-triangle-generator

标签: css geometry polygon css-shapes


【解决方案1】:

CSS 三角形:五幕悲剧

作为alex said,等宽的边框以 45 度角相互对接:

当你没有上边框时,它看起来像这样:

然后你给它一个宽度 0...

...高度为 0...

...最后,让两侧边框透明:

这会产生一个三角形。

【讨论】:

  • @Jauzsika,您只需使用:before:after 伪类即可将这些三角形添加到页面中而无需添加其他元素。
  • 用动画行动:jsfiddle.net/pimvdb/mA4Cu/104。仅适用于像我这样需要更多视觉证据的人...
  • 使用不同的left-borderright-border,可以制作非等腰三角形。当许多三角形组合在一起时......jsfiddle.net/zRNgz
  • 在 2018 年,有没有比这个 hack 更好的用 CSS 制作三角形的方法?
  • @Scribblemacher Inline SVG 可以做到。
【解决方案2】:

边框在相交处使用有角度的边缘(45° 角与等宽边框,但更改边框宽度可能会倾斜角度)。

div {
  width: 60px;
  border-width: 30px;
  border-color: red blue green yellow;
  border-style: solid;
}
<div></div>

看看jsFiddle

通过隐藏某些边框,您可以获得三角形效果(如上所示,通过将不同部分设置为不同的颜色)。 transparent 经常被用作边缘颜色来实现三角形的形状。

【讨论】:

    【解决方案3】:

    从基本的正方形和边框开始。每个边框都将被赋予不同的颜色,以便我们将它们区分开:

    .triangle {
        border-color: yellow blue red green;
        border-style: solid;
        border-width: 200px 200px 200px 200px;
        height: 0px;
        width: 0px;
    }
    <div class="triangle"></div>

    给你this:

    但不需要顶部边框,因此将其宽度设置为0px。现在,200px 的边框底部将使我们的三角形高 200 像素。

    .triangle {
        border-color: yellow blue red green;
        border-style: solid;
        border-width: 0px 200px 200px 200px;
        height: 0px;
        width: 0px;
    }
    <div class="triangle"></div>

    我们会得到this:

    然后要隐藏两个边三角形,将边框颜色设置为透明。由于 top-border 已被有效删除,我们也可以将 border-top-color 设置为透明。

    .triangle {
        border-color: transparent transparent red transparent;
        border-style: solid;
        border-width: 0px 200px 200px 200px;
        height: 0px;
        width: 0px;
    }
    <div class="triangle"></div>

    最后我们得到this:

    【讨论】:

    • 很酷,但这不就是一样吗? :-)
    • There's another way to draw ..,结果是一样的 :) 很好的解释
    • -1 用于使用带有大量伪影的 JPEG。但是 +1 创建了一个很好的例子,说明什么时候不使用 JPEG,我将来可以链接到该 JPEG 以进行威慑。 ;)
    • 这里为什么不用gif呢?
    • 对不起@hheimbuerger,我通过修复图像搞砸了你的例子。以后你必须链接到revision 2 of this answer
    【解决方案4】:

    不同的方法: CSS3 三角形 带变换旋转

    使用这种技术很容易制作三角形。对于喜欢看动画解释这种技术如何在这里工作的人来说:

    否则,这里有 4 幕的详细解释(这不是悲剧),如何用一个元素制作等腰直角三角形。

    • 注意 1 :对于非等腰三角形和花哨的东西,你可以看到第 4 步
    • 注意 2:在以下 sn-ps 中,供应商前缀不包括在内。它们包含在codepen demos中。
    • 注意 3:以下解释的 HTML 始终是: <div class="tr"></div>

    第一步:制作一个div

    简单,只需确保width = 1.41 x height。您可以使用任何技术 (see here),包括使用百分比和 padding-bottom 来保持纵横比并制作响应式三角形。在下图中,div 有一个金黄色的边框。

    在该 div 中,插入一个 伪元素,并为其赋予 100% 的父级宽度和高度。下图中伪元素的背景为蓝色。

    此时,我们有了这个CSS

    .tr {
        width: 30%;
        padding-bottom: 21.27%; /* = width / 1.41 */
        position: relative;
    }
    
    .tr: before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: #0079C6;
    }
    

    第 2 步:让我们旋转

    首先,最重要的是:定义变换原点default origin 在伪元素的中心,我们需要它在左下角。通过将此 CSS 添加到伪元素:

    transform-origin:0 100%;transform-origin: left bottom;

    现在我们可以用transform : rotate(45deg);将伪元素顺时针旋转45度

    此时,我们有了这个CSS

    .tr {
        width: 30%;
        padding-bottom: 21.27%; /* = width / 1.41 */
        position: relative;
    }
    
    .tr:before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: #0079C6;
        transform-origin: 0 100%;        
        transform: rotate(45deg);
    }
    

    第 3 步:隐藏它

    要隐藏伪元素的不需要的部分(所有溢出 div 的黄色边框),您只需在容器上设置overflow:hidden;。去掉黄色边框后,你会得到……一个TRIANGLE! :

    DEMO

    CSS:

    .tr {
        width: 30%;
        padding-bottom: 21.27%; /* = width / 1.41 */
        position: relative;
        overflow: hidden;
    }
    
    .tr:before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: #0079C6;
        transform-origin: 0 100%;
        transform: rotate(45deg);
    }
    

    第 4 步:走得更远……

    demo所示,可以自定义三角形:

    1. skewX(),让它们变得更薄或更扁平。
    2. 通过使用变换原点和旋转方向使它们指向左、右或任何其他方向。
    3. 使用 3D 变换属性制作 some reflexion
    4. triangle borders
    5. 放一张图片inside the triangle
    6. 更多...释放CSS3的力量!

    为什么要使用这种技术?

    1. 三角形可以轻松响应。
    2. 您可以创建triangle with border
    3. 您可以保持三角形的边界。这意味着只有当光标在inside the triangle时,才能触发悬停状态或点击事件。这在 this one 等某些情况下会变得非常方便,因为每个三角形都不能覆盖它的邻居,所以每个三角形都有自己的悬停状态。
    4. 你可以做一些fancy effects like reflections
    5. 它将帮助您了解 2d 和 3d 变换属性。

    为什么不使用这种技术?

    1. 主要缺点是浏览器兼容性,IE9+ 支持2d 变换属性,因此如果您打算支持IE8,则不能使用此技术。有关更多信息,请参阅CanIuse。对于一些使用 3d 转换的精美效果,例如 the reflection 浏览器支持 IE10+(请参阅 canIuse 了解更多信息)。
    2. 您不需要任何响应式的东西,一个简单的三角形就可以了,那么您应该使用这里解释的边框技术:更好的浏览器兼容性和更容易理解,这要归功于这里的精彩帖子。

    【讨论】:

    • 值得一提的是,1.41 是 √2 的近似值,也是您创建的三角形斜边的长度,这就是您需要(至少)该宽度的原因。
    • 我想保持答案简单,但你是对的,应该提到@KRyan
    • 实际上,在尝试使用它时,提及skewX 使用的不同宽度是如何派生的会很有用。
    • 当您需要三角形的 1px 实心边框时,此方法效果更好。
    • 这是为三角形创建边框的情况,当我想创建这个注释框AnnotationBox
    【解决方案5】:

    这是我为演示创建的animation in JSFiddle

    另请参阅下面的 sn-p。

    这是一个由截屏视频制作的 GIF 动画

    transforms = [
             {'border-left-width'   :'30', 'margin-left': '70'},
             {'border-bottom-width' :'80'},
             {'border-right-width'  :'30'},
             {'border-top-width'    :'0', 'margin-top': '70'},
             {'width'               :'0'},
             {'height'              :'0', 'margin-top': '120'},
             {'borderLeftColor'     :'transparent'},
             {'borderRightColor'    :'transparent'}
    ];
    
    
    $('#a').click(function() {$('.border').trigger("click");});
    (function($) {
        var duration = 1000
        $('.border').click(function() {
    		  for ( var i=0; i < transforms.length; i++ ) {
            $(this)
             .animate(transforms[i], duration)
    		  }
        }).end()
    }(jQuery))
    .border {
        margin: 20px 50px;
        width: 50px;
        height: 50px;
        border-width: 50px;
        border-style: solid;
        border-top-color: green;
        border-right-color: yellow;
        border-bottom-color: red;
        border-left-color: blue;
        cursor: pointer
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
    Click it!<br>
    <div class="border"></div>

    随机版本

    /**
     * Randomize array element order in-place.
     * Using Durstenfeld shuffle algorithm.
     */
    function shuffleArray(array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    }
    
    transforms = [
             {'border-left-width'   :'30', 'margin-left': '70'},
             {'border-bottom-width' :'80'},
             {'border-right-width'  :'30'},
             {'border-top-width'    :'0', 'margin-top': '70'},
             {'width'               :'0'},
             {'height'              :'0'},
             {'borderLeftColor'     :'transparent'},
             {'borderRightColor'    :'transparent'}
    ];
    transforms = shuffleArray(transforms)
    
    
    
    $('#a').click(function() {$('.border').trigger("click");});
    (function($) {
        var duration = 1000
        $('.border').click(function() {
    		  for ( var i=0; i < transforms.length; i++ ) {
            $(this)
             .animate(transforms[i], duration)
    		  }
        }).end()
    }(jQuery))
    .border {
        margin: 50px;
        width: 50px;
        height: 50px;
        border-width: 50px;
        border-style: solid;
        border-top-color: green;
        border-right-color: yellow;
        border-bottom-color: red;
        border-left-color: blue;
        cursor: pointer
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
    Click it!<br>
    <div class="border"></div>

    一次性版本

    $('#a').click(function() {$('.border').trigger("click");});
    (function($) {
        var duration = 1000
        $('.border').click(function() {
            $(this)
             .animate({'border-top-width': 0            ,
             					 'border-left-width': 30          ,
             					 'border-right-width': 30         ,
             					 'border-bottom-width': 80        ,
             					 'width': 0                       ,
             					 'height': 0                      ,
                       'margin-left': 100,
                       'margin-top': 150,
             					 'borderTopColor': 'transparent',
             					 'borderRightColor': 'transparent',
             					 'borderLeftColor':  'transparent'}, duration)
        }).end()
    }(jQuery))
    .border {
        margin: 50px;
        width: 50px;
        height: 50px;
        border-width: 50px;
        border-style: solid;
        border-top-color: green;
        border-right-color: yellow;
        border-bottom-color: red;
        border-left-color: blue;
        cursor: pointer
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
    Click it!<br>
    <div class="border"></div>

    【讨论】:

      【解决方案6】:

      假设我们有以下 div:

      <div id="triangle" />
      

      现在逐步编辑 CSS,这样您就可以清楚地了解周围发生了什么

      第 1 步: JSfiddle Link:

       #triangle {
              background: purple;
              width :150px;
              height:150PX;
              border-left: 50px solid black ;
              border-right: 50px solid black;
              border-bottom: 50px solid black;
              border-top: 50px solid black;
          }
      

      这是一个简单的 div。用一个非常简单的 CSS。所以外行可以理解。 Div 的尺寸为 150 x 150 像素,边框为 50 像素。附上图片:

      第 2 步: JSfiddle Link:

      #triangle {
          background: purple;
          width :150px;
          height:150PX;
          border-left: 50px solid yellow ;
          border-right: 50px solid green;
          border-bottom: 50px solid red;
          border-top: 50px solid blue;
      }
      

      现在我只是更改了所有 4 个边的边框颜色。图片已附上。

      步骤:3 JSfiddle Link:

      #triangle {
          background: purple;
          width :0;
          height:0;
          border-left: 50px solid yellow ;
          border-right: 50px solid green;
          border-bottom: 50px solid red;
          border-top: 50px solid blue;
      }
      

      现在我只是将 div 的高度和宽度从 150 像素更改为零。图片已附上

      第 4 步: JSfiddle:

      #triangle {
          background: purple;
          width :0px;
          height:0px;
          border-left: 50px solid transparent;
          border-right: 50px solid transparent;
          border-bottom: 50px solid red;
          border-top: 50px solid transparent;
      }
      

      现在我已经使除了底部边框之外的所有边框都是透明的。图片附在下面。

      第 5 步: JSfiddle Link:

      #triangle {
          background: white;
          width :0px;
          height:0px;
          border-left: 50px solid transparent;
          border-right: 50px solid transparent;
          border-bottom: 50px solid red;
          border-top: 50px solid transparent;
      }
      

      现在我只是将背景颜色更改为白色。图片已附上。

      因此我们得到了我们需要的三角形。

      【讨论】:

      • 第一步为什么要使用下界传送门?
      【解决方案7】:

      现在完全不同了……

      除了使用 css 技巧,不要忘记像 html 实体这样简单的解决方案:

      &#9650;
      

      结果:

      见:What are the HTML entities for up and down triangles?

      【讨论】:

      • 我认为“殴打”在这里并不合适。该解决方案依赖于字体度量,因此精确定位相当可疑,更不用说您无法控制形状。
      【解决方案8】:

      考虑下面的三角形

      .triangle {
          border-bottom:15px solid #000;
          border-left:10px solid transparent;
          border-right:10px solid transparent;
          width:0;
          height:0;
      }
      

      这是我们得到的:

      为什么会出现这种形状?下图解释了尺寸,注意底部边框使用了 15px,左右使用了 10px。

      通过删除右边框也很容易制作直角三角形。

      【讨论】:

        【解决方案9】:

        更进一步,在此基础上使用 css 我在后退和下一个按钮上添加了箭头(是的,我知道它不是 100% 跨浏览器,但仍然很流畅)。

        .triangle {
          width: 0;
          height: 0;
          border-left: 50px solid transparent;
          border-right: 50px solid transparent;
          border-bottom: 100px solid red;
          margin:20px auto;
        }
        
        .triangle-down {
          border-bottom:none;
          border-top: 100px solid red;
        }
        
        .triangle-left {
          border-left:none;
          border-right: 100px solid red;
          border-bottom: 50px solid transparent;
          border-top: 50px solid transparent;
        }
        
        .triangle-right {
          border-right:none;
          border-left: 100px solid red;
          border-bottom: 50px solid transparent;
          border-top: 50px solid transparent;
        }
        
        .triangle-after:after {
          width: 0;
          height: 0;
          border-left: 5px solid transparent;
          border-right: 5px solid transparent;
          border-bottom: 5px solid red;
          margin:0 5px;
          content:"";
          display:inline-block;
        }
        
        .triangle-after-right:after {
          border-right:none;
          border-left: 5px solid blue;
          border-bottom: 5px solid transparent;
          border-top: 5px solid transparent;
        
        }
        
        .triangle-before:before {
          width: 0;
          height: 0;
          border-left: 5px solid transparent;
          border-right: 5px solid transparent;
          border-bottom: 5px solid blue;
          margin:0 5px;
          content:"";
          display:inline-block;
        }
        
        .triangle-before-left:before {
          border-left:none;
          border-right: 5px solid blue;
          border-bottom: 5px solid transparent;
          border-top: 5px solid transparent;
        
        }
        <div class="triangle"></div>
        <div class="triangle triangle-down"></div>
        <div class="triangle triangle-left"></div>
        <div class="triangle triangle-right"></div>
        
        <a class="triangle-before triangle-before-left" href="#">Back</a>
        <a class="triangle-after triangle-after-right" href="#">Next</a>

        【讨论】:

        • 这不是跨浏览器吗?三角形应该可以回到 IE6。
        • 不 100% 支持 :before 和 :after 的使用。
        • 不支持伪元素
        【解决方案10】:

        不同的方法。具有线性渐变(对于 IE,仅 IE 10+)。 你可以使用任何角度:

        .triangle {
            margin: 50px auto;
            width: 100px;
            height: 100px;
        /* linear gradient */
            background: -moz-linear-gradient(-45deg,  rgba(255,0,0,0) 0%, rgba(255,0,0,0) 50%, rgba(255,0,0,1) 50%, rgba(255,0,0,1) 100%);
         /* FF3.6+ */
            background: -webkit-gradient(linear, left top, right bottom, color-stop(0%,rgba(255,0,0,0)), color-stop(50%,rgba(255,0,0,0)), color-stop(50%,rgba(255,0,0,1)), color-stop(100%,rgba(255,0,0,1)));
         /* Chrome,Safari4+ */
            background: -webkit-linear-gradient(-45deg,  rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
         /* Chrome10+,Safari5.1+ */
            background: -o-linear-gradient(-45deg,  rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
         /* Opera 11.10+ */
            background: -ms-linear-gradient(-45deg,  rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
         /* IE10+ */
            background: linear-gradient(135deg,  rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
         /* W3C */;
        }
        &lt;div class="triangle"&gt;&lt;/div&gt;

        这里是jsfiddle

        【讨论】:

        • 这是一个漂亮的解决方案,但需要注意的是它仅适用于 IE 10+。
        【解决方案11】:

        CSS clip-path

        这是我觉得这个问题错过了的东西; clip-path

        clip-path 简而言之

        使用clip-path 属性进行剪切类似于从一张矩形纸上剪切一个形状(如圆形或五边形)。该属性属于“CSS Masking Module Level 1”规范。规范指出,“CSS 遮罩提供了两种方法来部分或完全隐藏部分视觉元素:遮罩和剪裁”。


        clip-path 将使用元素本身而不是其边框来切割您在其参数中指定的形状。它使用一个超级简单的基于百分比的坐标系统,这使得编辑变得非常容易,这意味着您可以在几分钟内将其拾取并创建奇怪而美妙的形状。


        三角形形状示例

        div {
          -webkit-clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
          clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
          background: red;
          width: 100px;
          height: 100px;
        }
        &lt;div&gt;&lt;/div&gt;

        缺点

        目前它确实有一个主要缺点,一个是它主要缺乏支持,仅在-webkit- 浏览器中真正被覆盖,并且不支持 IE,并且仅在 FireFox 中非常部分。


        资源

        这里有一些有用的资源和材料,可帮助您更好地理解 clip-path 并开始创建您自己的。

        【讨论】:

        • 现在好像在firefox有更好的支持
        【解决方案12】:

        好的,这个三角形将被创建,因为元素的边框在 HTML 和 CSS 中协同工作的方式......

        由于我们通常使用 1 或 2px 的边框,我们从来没有注意到边框以相同的宽度与彼此形成 45° 角,如果宽度发生变化,角度也会发生变化,运行我在下面创建的 CSS 代码:

        .triangle {
          width: 100px;
          height: 100px;
          border-left: 50px solid black;
          border-right: 50px solid black;
          border-bottom: 100px solid red;
        }
        <div class="triangle">
        </div>

        然后在下一步中,我们没有任何宽度或高度,像这样:

        .triangle {
          width: 0;
          height: 0;
          border-left: 50px solid black;
          border-right: 50px solid black;
          border-bottom: 100px solid red;
        }
        <div class="triangle">
        </div>

        现在我们使左右边界不可见,以使我们想要的三角形如下:

        .triangle {
          width: 0;
          height: 0;
          border-left: 50px solid transparent;
          border-right: 50px solid transparent;
          border-bottom: 100px solid red;
        }
        &lt;div class="triangle"&gt;&lt;/div&gt;

        如果您不愿意运行 sn-p 查看步骤,我创建了一个图像序列来查看一张图像中的所有步骤:

        【讨论】:

          【解决方案13】:

          这是一个老问题,但我认为值得分享如何使用这种三角形技术创建箭头。

          第 1 步:

          让我们创建 2 个三角形,对于第二个,我们将使用 :after 伪类并将其放置在另一个的下方:

          .arrow{
              width: 0;
              height: 0;
              border-radius: 50px;
              display: inline-block;
              position: relative;
          }
          
              .arrow:after{
                  content: "";
                  width: 0;
                  height: 0;
                  position: absolute;
              }
          
          
          .arrow-up{
               border-left: 50px solid transparent;
               border-right: 50px solid transparent;
               border-bottom: 50px solid #333;
          }
              .arrow-up:after{
                   top: 5px;
                   border-left: 50px solid transparent;
                   border-right: 50px solid transparent;
                   border-bottom: 50px solid #ccc;
                   right: -50px;
              }
          &lt;div class="arrow arrow-up"&gt; &lt;/div&gt;

          第二步

          现在我们只需要将第二个三角形的主要边框颜色设置为与背景相同的颜色:

          .arrow{
              width: 0;
              height: 0;
              border-radius: 50px;
              display: inline-block;
              position: relative;
          }
          
              .arrow:after{
                  content: "";
                  width: 0;
                  height: 0;
                  position: absolute;
              }
          
          
          .arrow-up{
               border-left: 50px solid transparent;
               border-right: 50px solid transparent;
               border-bottom: 50px solid #333;
          }
              .arrow-up:after{
                   top: 5px;
                   border-left: 50px solid transparent;
                   border-right: 50px solid transparent;
                   border-bottom: 50px solid #fff;
                   right: -50px;
              }
          &lt;div class="arrow arrow-up"&gt; &lt;/div&gt;

          拨弄所有箭头:
          http://jsfiddle.net/tomsarduy/r0zksgeu/

          【讨论】:

            【解决方案14】:

            如果你想为三角形应用边框,请阅读:Create a triangle with CSS?

            几乎所有的答案都集中在使用边框构建的三角形上,所以我将详细说明linear-gradient 方法(从@lima_fil 的答案开始)。

            使用像45° 这样的度数值将迫使我们遵守height/width 的特定比率以获得我们想要的三角形,这不会响应:

            .tri {
              width:100px;
              height:100px;
              background:linear-gradient(45deg, transparent 49.5%,red 50%);
              
              /*To illustrate*/
              border:1px solid;
            }
            Good one
            <div class="tri"></div>
            bad one
            <div class="tri" style="width:150px"></div>
            bad one
            <div class="tri" style="height:30px"></div>

            我们应该考虑预定义的方向值,例如to bottomto top 等,而不是这样做。在这种情况下,我们可以获得任何类型的三角形,同时保持响应。

            1) 矩形三角形

            要获得这样的三角形,我们需要一个线性梯度和一个对角线方向,例如to bottom rightto top leftto bottom left

            .tri-1,.tri-2 {
              display:inline-block;
              width:100px;
              height:100px;
              background:linear-gradient(to bottom left, transparent 49.5%,red 50%);
              border:1px solid;
              animation:change 2s linear infinite alternate;
            }
            .tri-2 {
              background:linear-gradient(to top right, transparent 49.5%,red 50%);
              border:none;
            }
            
            @keyframes change {
              from {
                width:100px;
                height:100px;
              }
              to {
                height:50px;
                width:180px;
              }
            }
            <div class="tri-1"></div>
            <div class="tri-2"></div>

            2) 等腰三角形

            对于这个,我们需要 2 个像上面一样的线性渐变,每个都需要一半的宽度(或高度)。这就像我们创建了第一个三角形的镜像。

            .tri {
              display:inline-block;
              width:100px;
              height:100px;
              background-image:
              linear-gradient(to bottom right, transparent 49.5%,red 50%),
              linear-gradient(to bottom left,  transparent 49.5%,red 50%);
              background-size:50.3% 100%; /* I use a value slightly bigger than 50% to avoid having a small gap between both gradient*/
              background-position:left,right;
              background-repeat:no-repeat;
              
              animation:change 2s linear infinite alternate;
            }
            
            
            @keyframes change {
              from {
                width:100px;
                height:100px;
              }
              to {
                height:50px;
                width:180px;
              }
            }
            &lt;div class="tri"&gt;&lt;/div&gt;

            3) 等边三角形

            这个处理起来有点棘手,因为我们需要保持渐变的高度和宽度之间的关系。我们将有与上面相同的三角形,但我们将使计算更加复杂,以便将等腰三角形转换为等边三角形。

            为方便起见,我们将考虑 div 的宽度是已知的,并且高度足够大,以便能够在里面绘制我们的三角形 (height &gt;= width)。

            我们有两个渐变g1g2,蓝线是div w 的宽度,每个渐变都有50% (w/2) 和三角形的每一边应该等于w。绿线是两个渐变的高度hg,我们可以很容易地得到下面的公式:

            (w/2)² + hg² = w² ---> hg = (sqrt(3)/2) * w ---> hg = 0.866 * w

            我们可以依靠calc()来进行计算并获得所需的结果:

            .tri {
              --w:100px;
              width:var(--w);
              height:100px;
              display:inline-block;
              background-image:
              linear-gradient(to bottom right, transparent 49.5%,red 50%),
              linear-gradient(to bottom left,  transparent 49.5%,red 50%);
              background-size:calc(var(--w)/2 + 0.5px)  calc(0.866 * var(--w));
              background-position:
                left bottom,right bottom;
              background-repeat:no-repeat;
              
            }
            <div class="tri"></div>
            <div class="tri" style="--w:80px"></div>
            <div class="tri" style="--w:50px"></div>

            另一种方法是控制div的高度,保持渐变的语法简单:

            .tri {
              --w:100px;
              width:var(--w);
              height:calc(0.866 * var(--w));
              display:inline-block;
              background:
               linear-gradient(to bottom right, transparent 49.8%,red 50%) left,
               linear-gradient(to bottom left,  transparent 49.8%,red 50%) right;
              background-size:50.2% 100%;
              background-repeat:no-repeat;
              
            }
            <div class="tri"></div>
            <div class="tri" style="--w:80px"></div>
            <div class="tri" style="--w:50px"></div>

            4) 随机三角形

            要获得一个随机三角形,这很容易,因为我们只需要删除每个三角形的 50% 的条件,但我们应该保留两个条件(两个条件应该具有相同的高度并且两个宽度的总和应该是 100%)。

            .tri-1 {
              width:100px;
              height:100px;
              display:inline-block;
              background-image:
              linear-gradient(to bottom right, transparent 50%,red 0),
              linear-gradient(to bottom left, transparent 50%,red 0);
              background-size:20% 60%,80% 60%;
              background-position:
                left bottom,right bottom;
              background-repeat:no-repeat;
              
             
            }
            &lt;div class="tri-1"&gt;&lt;/div&gt;

            但是如果我们想为每一边定义一个值呢?我们只需要重新计算!

            让我们将hg1hg2 定义为渐变的高度(两者都等于红线),然后将wg1wg2 定义为渐变的宽度(wg1 + wg2 = a)。我不会详细说明计算,但最后我们将有:

            wg2 = (a²+c²-b²)/(2a)
            wg1 = a - wg2
            hg1 = hg2 = sqrt(b² - wg1²) = sqrt(c² - wg2²)
            

            现在我们已经达到了 CSS 的极限,即使使用 calc() 我们也无法实现这一点,所以我们只需要手动收集最终结果并将它们用作固定大小:

            .tri {
              --wg1: 20px; 
              --wg2: 60px;
              --hg:30px; 
              width:calc(var(--wg1) + var(--wg2));
              height:100px;
              display:inline-block;
              background-image:
              linear-gradient(to bottom right, transparent 49.5%,red 50%),
              linear-gradient(to bottom left,  transparent 49.5%,red 50%);
            
              background-size:var(--wg1) var(--hg),var(--wg2) var(--hg);
              background-position:
                left bottom,right bottom;
              background-repeat:no-repeat;
              
            }
            <div class="tri" ></div>
            
            <div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;" ></div>

            奖金

            我们不应该忘记我们也可以应用旋转和/或倾斜,我们有更多的选择来获得更多的三角形:

            .tri {
              --wg1: 20px; 
              --wg2: 60px;
              --hg:30px; 
              width:calc(var(--wg1) + var(--wg2) - 0.5px);
              height:100px;
              display:inline-block;
              background-image:
              linear-gradient(to bottom right, transparent 49%,red 50%),
              linear-gradient(to bottom left,  transparent 49%,red 50%);
            
              background-size:var(--wg1) var(--hg),var(--wg2) var(--hg);
              background-position:
                left bottom,right bottom;
              background-repeat:no-repeat;
              
            }
            <div class="tri" ></div>
            
            <div class="tri" style="transform:skewY(25deg)"></div>
            
            <div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;" ></div>
            
            
            <div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;transform:rotate(20deg)" ></div>

            当然我们应该记住SVG solution,它在某些情况下可能更合适:

            svg {
             width:100px;
             height:100px;
            }
            
            polygon {
              fill:red;
            }
            <svg viewBox="0 0 100 100"><polygon points="0,100 0,0 100,100" /></svg>
            <svg viewBox="0 0 100 100"><polygon points="0,100 50,0 100,100" /></svg>
            <svg viewBox="0 0 100 100"><polygon points="0,100 50,23 100,100" /></svg>
            <svg viewBox="0 0 100 100"><polygon points="20,60 50,43 80,100" /></svg>

            【讨论】:

              【解决方案15】:

              SASS (SCSS) triangle mixin

              我写这个是为了让自动生成一个 CSS 三角形变得更容易(并且 DRY):

              // Triangle helper mixin (by Yair Even-Or)
              // @param {Direction} $direction - either `top`, `right`, `bottom` or `left`
              // @param {Color} $color [currentcolor] - Triangle color
              // @param {Length} $size [1em] - Triangle size
              @mixin triangle($direction, $color: currentcolor, $size: 1em) {
                $size: $size/2;
                $transparent: rgba($color, 0);
                $opposite: (top:bottom, right:left, left:right, bottom:top);
              
                content: '';
                display: inline-block;
                width: 0;
                height: 0;
                border: $size solid $transparent;
                border-#{map-get($opposite, $direction)}-color: $color;
                margin-#{$direction}: -$size;
              }
              

              用例示例:

              span {
                @include triangle(bottom, red, 10px);
              }
              

              Playground page


              重要提示:
              如果三角形在某些浏览器中看起来像素化,请尝试here 中描述的方法之一。

              【讨论】:

                【解决方案16】:

                如果你想玩 border-sizewidthheight 并看看它们如何创建不同的形状,试试这个:

                const sizes = [32, 32, 32, 32];
                const triangle = document.getElementById('triangle');
                
                function update({ target }) {
                  let index = null;
                  
                  if (target) {
                    index = parseInt(target.id);
                
                    if (!isNaN(index)) {
                      sizes[index] = target.value;
                    }
                  }
                  
                  window.requestAnimationFrame(() => {
                    triangle.style.borderWidth = sizes.map(size => `${ size }px`).join(' ');
                    
                    if (isNaN(index)) {
                      triangle.style[target.id] = `${ target.value }px`;
                    }
                  });
                }
                
                document.querySelectorAll('input').forEach(input => {
                  input.oninput = update;
                });
                
                update({});
                body {
                  margin: 0;
                  min-height: 100vh;
                  display: flex;
                  justify-content: center;
                  align-items: center;
                  overflow: hidden;
                }
                
                #triangle {
                    border-style: solid;
                    border-color: yellow magenta blue black;
                    background: cyan;
                    height: 0px;
                    width: 0px;
                }
                
                #controls {
                  position: fixed;
                  bottom: 0;
                  left: 0;
                  right: 0;
                  background: white;
                  display: flex;
                  box-shadow: 0 0 32px rgba(0, 0, 0, .125);
                }
                
                #controls > div {
                  position: relative;
                  width: 25%;
                  padding: 8px;
                  box-sizing: border-box;
                  display: flex;
                }
                
                input {
                  margin: 0;
                  width: 100%;
                  position: relative;
                }
                <div id="triangle" style="border-width: 32px 32px 32px 32px;"></div>
                
                <div id="controls">
                  <div><input type="range" min="0" max="128" value="32" id="0" /></div>
                  <div><input type="range" min="0" max="128" value="32" id="1" /></div>
                  <div><input type="range" min="0" max="128" value="32" id="2" /></div>
                  <div><input type="range" min="0" max="128" value="32" id="3" /></div>
                  <div><input type="range" min="0" max="128" value="0" id="width" /></div>
                  <div><input type="range" min="0" max="128" value="0" id="height" /></div>
                </div>

                【讨论】:

                  【解决方案17】:

                  这是另一个小提琴:

                  .container:after {
                      position: absolute;
                      right: 0;
                      content: "";
                      margin-right:-50px;
                      margin-bottom: -8px;
                      border-width: 25px;
                      border-style: solid;
                      border-color: transparent transparent transparent #000;
                      width: 0;
                      height: 0;
                      z-index: 10;
                      -webkit-transition: visibility 50ms ease-in-out,opacity 50ms ease-in-out;
                      transition: visibility 50ms ease-in-out,opacity 50ms ease-in-out;
                      bottom: 21px;
                  }
                  .container {
                      float: left;
                      margin-top: 100px;
                      position: relative;
                      width: 150px;
                      height: 80px;
                      background-color: #000;
                  }
                  
                  .containerRed {
                      float: left;
                      margin-top: 100px;
                      position: relative;
                      width: 100px;
                      height: 80px;
                      background-color: red;
                  }
                  

                  https://jsfiddle.net/qdhvdb17/

                  【讨论】:

                    【解决方案18】:

                    其他人已经很好地解释了这一点。让我给你一个动画,它会快速解释这一点:http://codepen.io/chriscoyier/pen/lotjh

                    这里有一些代码供您使用和学习这些概念。

                    HTML:

                    <html>
                      <body>
                        <div id="border-demo">
                        </div>
                      </body>
                    </html>
                    

                    CSS:

                    /*border-width is border thickness*/
                    #border-demo {
                        background: gray;
                        border-color: yellow blue red green;/*top right bottom left*/
                        border-style: solid;
                        border-width: 25px 25px 25px 25px;/*top right bottom left*/
                        height: 50px;
                        width: 50px;
                    }
                    

                    玩这个,看看会发生什么。将高度和宽度设置为零。然后去掉上边框,让左右透明,或者直接看下面的代码做一个css三角形:

                    #border-demo {
                        border-left: 50px solid transparent;
                        border-right: 50px solid transparent;
                        border-bottom: 100px solid blue;
                    }
                    

                    【讨论】:

                      【解决方案19】:

                      我知道这是一个旧的方法,但我想在这个讨论中补充一点,creating a triangle 至少有 5 种不同的方法可以单独使用 HTML 和 CSS。

                      1. 使用borders
                      2. 使用linear-gradient
                      3. 使用conic-gradient
                      4. 使用 transformoverflow
                      5. 使用clip-path

                      我认为除了方法3,使用conic-gradient,这里都已经介绍过了,所以在这里分享一下:

                      .triangle{
                              width: 40px;
                              height: 40px;
                              background: conic-gradient(at 50% 50%,transparent 135deg,green 0,green 225deg, transparent 0);
                          }
                      &lt;div class="triangle"&gt;&lt;/div&gt;

                      【讨论】:

                        【解决方案20】:

                        使用clip-path: polygon(50% 0%, 100% 100%, 0% 100%); 轻松创建三角形

                        <div class="triangle"></div>
                        
                        .triangle{width:200px; height:200px;background:#000;clip-path: polygon(50% 0%, 100% 100%, 0% 100%);}
                        

                        【讨论】:

                          【解决方案21】:

                          试试这个:-

                          .triangle {
                              border-color: transparent transparent red transparent;
                              border-style: solid;
                              border-width: 0px 200px 200px 200px;
                              height: 0px;
                              width: 0px;
                          }
                          &lt;div class="triangle"&gt;&lt;/div&gt;

                          【讨论】:

                            【解决方案22】:

                            clip-path 对我来说效果最好 - 适用于有和没有固定尺寸的 div/容器:

                            .triangleContainer{
                                position: relative;
                                width: 500px;
                                height: 500px;
                            }
                            
                            .triangleContainer::before{
                                content: "";        
                                position: absolute;
                                background:blue;
                                top: 0;
                                left: 0;
                                width: 100%;
                                height: 100%;
                                clip-path: polygon(50% 0, 0 100%, 100% 100%);
                            }
                            

                            【讨论】:

                            • 不确定我的建议有什么问题。我刚刚在另一个项目中使用了它,并且很享受 - 很高兴根据要求制作一个三角形,并为任何感兴趣的人提供这种技术的变体!
                            • 问题是 OP 想知道它是如何工作的,这样做或导致三角形的原因是什么?不是怎么做。
                            猜你喜欢
                            • 2013-01-04
                            • 1970-01-01
                            • 1970-01-01
                            • 2012-10-01
                            • 1970-01-01
                            • 2011-11-15
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多