Transparent arrow/triangle indented over an image

后端 未结 4 489
伪装坚强ぢ
伪装坚强ぢ 2020-11-22 02:06

I would like to make a transparent arrow over an image. This triangle should be indented in a semi transparent block and show the background image.

相关标签:
4条回答
  • 2020-11-22 02:37

    Simple Approach

    • Use pseudo element with box-shadow and transform: rotate();

    • Add overflow: hidden; to main div.

    Snippet :

    body {
      margin: 0;
      padding: 0;
      background: url(http://i.imgur.com/EinPKO3.jpg);
      background-size: cover;
    }
    div {
      height: 100px;
      width: 100%;
      position: absolute;
      bottom: 0;
      overflow: hidden;
    }
    div:before {
      position: absolute;
      top: -50px;
      left: calc(50% - 35px);
      content: "";
      height: 50px;
      width: 50px;
      background: transparent;
      -webkit-transform-origin: 0% 100%;
      -moz-transform-origin: 0% 100%;
      -ms-transform-origin: 0% 100%;
      transform-origin: 0% 100%;
      -webkit-transform: rotate(45deg);
      -moz-transform: rotate(45deg);
      -ms-transform: rotate(45deg);
      transform: rotate(45deg);
      box-shadow: 0 0 0 5000px rgba(0, 0, 0, 0.6);
    }
    <div></div>

    0 讨论(0)
  • 2020-11-22 02:43

    We can make this with linear-gradients. No pseudo-element. I used some CSS variables to control everything easily. This is more flexible.

    .a {
      /* you can change these variables */
      --arrow-width: 20px;
      --rgba: rgba(0, 0, 0, 0.5);
      --bottom-height: 50px;
      
      width: 100%;
      height: 300px;
      background: linear-gradient(to right, var(--rgba) 0 calc(50% - var(--arrow-width)), transparent calc(50% - var(--arrow-width)) calc(50% + var(--arrow-width)), var(--rgba) 0 calc(50% + var(--arrow-width) * 2)) 0 calc(100% - var(--bottom-height)) / 100% var(--arrow-width), 
                  linear-gradient(to bottom right, transparent 0 50%, var(--rgba) 50.1% 100%) calc(50% + (var(--arrow-width) / 2)) calc(100% - var(--bottom-height)) / var(--arrow-width) var(--arrow-width), 
                  linear-gradient(to bottom left, transparent 0 50%, var(--rgba) 50.1% 100%) calc(50% - (var(--arrow-width) / 2)) calc(100% - var(--bottom-height)) / var(--arrow-width) var(--arrow-width), 
                  linear-gradient(var(--rgba), var(--rgba)) 0 100%/ 100% calc(var(--bottom-height)),
                  url(https://picsum.photos/id/600/360) 50% 50% / cover;
      background-repeat: no-repeat;
    }
    <div class="a"></div>

    By changing the variables:

    .a {
      /* you can change these variables */
      --arrow-width: 50px;
      --rgba: rgba(0, 0, 0, 0.5);
      --bottom-height: 70px;
      
      width: 100%;
      height: 300px;
      background: linear-gradient(to right, var(--rgba) 0 calc(50% - var(--arrow-width)), transparent calc(50% - var(--arrow-width)) calc(50% + var(--arrow-width)), var(--rgba) 0 calc(50% + var(--arrow-width) * 2)) 0 calc(100% - var(--bottom-height)) / 100% var(--arrow-width), 
                  linear-gradient(to bottom right, transparent 0 50%, var(--rgba) 50.1% 100%) calc(50% + (var(--arrow-width) / 2)) calc(100% - var(--bottom-height)) / var(--arrow-width) var(--arrow-width), 
                  linear-gradient(to bottom left, transparent 0 50%, var(--rgba) 50.1% 100%) calc(50% - (var(--arrow-width) / 2)) calc(100% - var(--bottom-height)) / var(--arrow-width) var(--arrow-width), 
                  linear-gradient(var(--rgba), var(--rgba)) 0 100%/ 100% calc(var(--bottom-height)), 
                  url(https://picsum.photos/id/600/360) 50% 50% / cover;
      background-repeat: no-repeat;
    }
    <div class="a"></div>

    To better understand the trick here is the gradients with different colors:

    .a {
      /* you can change these variables */
      --arrow-width: 50px;
      --bottom-height: 70px;
      
      width: 100%;
      height: 300px;
      background: linear-gradient(to right, red 0 calc(50% - var(--arrow-width)), transparent calc(50% - var(--arrow-width)) calc(50% + var(--arrow-width)), blue 0 calc(50% + var(--arrow-width) * 2)) 0 calc(100% - var(--bottom-height)) / 100% var(--arrow-width), 
                  linear-gradient(to bottom right, transparent 0 50%, yellow 50.1% 100%) calc(50% + (var(--arrow-width) / 2)) calc(100% - var(--bottom-height)) / var(--arrow-width) var(--arrow-width), 
                  linear-gradient(to bottom left, transparent 0 50%, green 50.1% 100%) calc(50% - (var(--arrow-width) / 2)) calc(100% - var(--bottom-height)) / var(--arrow-width) var(--arrow-width), 
                  linear-gradient(purple, purple) 0 100%/ 100% calc(var(--bottom-height)), 
                  url(https://picsum.photos/id/600/360) 50% 50% / cover;
      background-repeat: no-repeat;
    }
    <div class="a"></div>

    Masking:

    .a {
      /* you can change this variable */
      --arrow-width: 30px;
      
      width: 100%;
      height: 300px;
      --mask: linear-gradient(#000, #000) 0 0/100% calc(100% - var(--arrow-width)) no-repeat, 
              linear-gradient(to top right, transparent 0 50%, #000 50.1% 100%) calc(50% - var(--arrow-width) / 2) 100% / var(--arrow-width) var(--arrow-width) no-repeat, 
              linear-gradient(to top left, transparent 0 50%, #000 50.1% 100%) calc(50% + var(--arrow-width) / 2) 100% / var(--arrow-width) var(--arrow-width) no-repeat;
      -webkit-mask: var(--mask);
      mask: var(--mask);
      background: url(https://picsum.photos/id/600/360) 50% 50% / cover;
    }
    <div class="a"></div>

    0 讨论(0)
  • 2020-11-22 02:47

    Here is a solution using CSS clip-path that doesn't overflow the wrapper.

    .wrap {
      position:relative;
      width:480px;
      height:270px;
      background-image:url(http://placehold.it/480x270);
    }
    
    .wrap:after {
      content:"";
      display:block;
      position:absolute;
      left:0;
      right:0;
      bottom:0;
      height:50px;
      background-color:rgba(0, 0, 0, 0.7);
      -webkit-clip-path:polygon(0 0, calc(50% - 30px) 0, 50% 50%, calc(50% + 30px) 0, 100% 0, 100% 100%, 0 100%);
      -moz-clip-path:polygon(0 0, calc(50% - 30px) 0, 50% 50%, calc(50% + 30px) 0, 100% 0, 100% 100%, 0 100%);
      clip-path:polygon(0 0, calc(50% - 30px) 0, 50% 50%, calc(50% + 30px) 0, 100% 0, 100% 100%, 0 100%);
    }
    <div class="wrap"></div>

    0 讨论(0)
  • 2020-11-22 02:50

    There are several approaches to make a transparent arrow over an image with CSS. The two I will describe involve pseudo elements to minimize markup and have the same output. You can also see an SVG approach at the end of this answer :

    Transparent arrow over an image

    The transparent effect on the black part arround the arrow is made with rgba() colors that allow transparency. But you can use opacity on the pseudo elements if you prefer.


    1. SkewX()

    You can use the CSS3 skewX() property on two pseudo elements to make the transparent arrow. The main asset of this approach is that the transparent arrow can be responsive but it also allows you to put a border on the black shape and around the traingle.

    The responsiveness of the shape is made with the padding-bottom property to maintain it's aspect ratio (this technique is described here).

    DEMO

    .wrap {
      position: relative;
      overflow: hidden;
      width: 70%;
      margin: 0 auto;
    }
    .wrap img {
      width: 100%;
      height: auto;
      display: block;
    }
    .arrow {
      position: absolute;
      bottom: 0;
      width: 100%;
      padding-bottom: 3%;
      background-color: rgba(0, 0, 0, 0.8);
    }
    .arrow:before,
    .arrow:after {
      content: '';
      position: absolute;
      bottom: 100%;
      width: 50%;
      padding-bottom: inherit;
      background-color: inherit;
    }
    .arrow:before {
      right: 50%;
      -ms-transform-origin: 100% 100%;
      -webkit-transform-origin: 100% 100%;
      transform-origin: 100% 100%;
      -ms-transform: skewX(45deg);
      -webkit-transform: skewX(45deg);
      transform: skewX(45deg);
    }
    .arrow:after {
      left: 50%;
      -ms-transform-origin: 0 100%;
      -webkit-transform-origin: 0 100%;
      transform-origin: 0 100%;
      -ms-transform: skewX(-45deg);
      -webkit-transform: skewX(-45deg);
      transform: skewX(-45deg);
    }
    <div class="wrap">
      <img src="https://farm8.staticflickr.com/7187/6895047173_d4b1a0d798.jpg" />
      <div class="arrow"></div>
    </div>

    Browser support for the transform : skew() property is IE9+ (see canIuse).

    2. Border

    The asset of this technique is browser support so if you need IE8 support this one is for you. The drawback is that the shape can't be responsive because border can't use % widths.

    DEMO

    .wrap {
      position: relative;
      overflow: hidden;
      width: 70%;
      margin: 0 auto;
    }
    .wrap img {
      width: 100%;
      height: auto;
      display: block;
    }
    .arrow {
      position: absolute;
      bottom: 0;
      width: 100%;
      height: 20px;
      background-color: rgba(0, 0, 0, 0.8);
    }
    .arrow:before,
    .arrow:after {
      content: '';
      position: absolute;
      bottom: 100%;
      width: 50%;
      box-sizing: border-box;
    }
    .arrow:before {
      right: 50%;
      border-bottom: 20px solid rgba(0, 0, 0, 0.8);
      border-right: 20px solid transparent;
    }
    .arrow:after {
      left: 50%;
      border-bottom: 20px solid rgba(0, 0, 0, 0.8);
      border-left: 20px solid transparent;
    }
    <div class="wrap">
      <img src="https://farm8.staticflickr.com/7187/6895047173_d4b1a0d798.jpg" />
      <div class="arrow"></div>
    </div>


    3. Play with it!

    Example : if you can change the black transparent color to the same as your background color (white here), you can make an transparent triangle/arrow with the same background image as the block :

    transparetn arrow with a see through image

    DEMO

    .wrap {
        position: relative;
        overflow: hidden;
        width: 50%;
        margin: 0 auto;
        background-color:#fff;
    }
    .wrap img {
        width: 100%;
        height: auto;
        display: block;
    }
    .wrap:before, .wrap:after {
        content:'';
        position: absolute;
        bottom: 0;
        width: 50%;
        background-color: inherit;
        padding-bottom:3%;
    }
    .wrap:before {
        right: 50%;
        -ms-transform-origin: 100% 100%;
        -webkit-transform-origin: 100% 100%;
        transform-origin: 100% 100%;
        -ms-transform: skewX(45deg);
        -webkit-transform: skewX(45deg);
        transform: skewX(45deg);
    }
    .wrap:after {
        left: 50%;
        -ms-transform-origin: 0 100%;
        -webkit-transform-origin: 0 100%;
        transform-origin: 0 100%;
        -ms-transform: skewX(-45deg);
        -webkit-transform: skewX(-45deg);
        transform: skewX(-45deg);
    }
    <div class="wrap">
        <img src="https://farm8.staticflickr.com/7187/6895047173_d4b1a0d798.jpg" />
    </div>

    4. Tooltip with a triangle over an image.

    If you need to use this shape over another image, background gradient or whatever non plain color, you will need to use a different approach in order to see the image all around the shape like this:

    tooltip like element with a triangle over an image

    The point is to use the same image twice. Once in the div element and once in the triangle and to postion them exactly at the same place with absolute positioning. The arrow is made with transform:rotate();.

    DEMO

    body{
      padding-top:100px;
      background:url('https://farm8.staticflickr.com/7187/6895047173_d4b1a0d798.jpg')no-repeat center center;
      background-size:cover;
    }
    
    .wrap, .img {
      display:inline-block;
      position:relative;
    }
    .tr{
      position:absolute;
      overflow:hidden;
      top:-25px; left:100px;
      width:50px; height:50px;
      -webkit-transform:rotate(45deg);
      -ms-transform:rotate(45deg);
      transform:rotate(45deg);
    }
    .tr img{
      position:absolute;
      top:-15px; left:-100px;
      -webkit-transform-origin: 125px 40px;
      -ms-transform-origin: 125px 40px;
      transform-origin: 125px 40px;
      -webkit-transform:rotate(-45deg);
      -ms-transform:rotate(-45deg);
      transform:rotate(-45deg);
    }
    .img{
      overflow:hidden;
      width: 600px; height:100px;
    }
    .img img{
      position:absolute;
      top:-40px;
    }
    <div class="wrap">
        <div class="img">
            <img src="https://farm7.staticflickr.com/6092/6227418584_d5883b0948.jpg" alt="" />
        </div>
         <div class="tr">
            <img src="https://farm7.staticflickr.com/6092/6227418584_d5883b0948.jpg" alt="" />
        </div>
    </div>

    DEMO with box shadows.

    5. SVG and cliPath

    DEMO using an svg tag and clipPath.
    This might be a semanticaly better approach if you are making graphics.

    0 讨论(0)
提交回复
热议问题