Creating a transparent inner notch?

2020-02-14 05:57发布

I know how to create a notch on the outside like:

div:after {
    content: '';
    display: block;
    width: 20px;
    height: 20px;
    -webkit-transform: rotate(45deg);
    transform: rotate(45deg);
}

But I can't figure out how to solve this thingy using CSS only:

enter image description here

The notch has to be inside of the container and it has to be transparent. So the above solution or an image won't solve it.

Maybe this can be created using SVG?

Edit

What I tried is this:

body {
    background: #eee;
}

div {
    position: relative;
    height: 100px;
    width: 200px;
    background: #ccc;
}

div:after {
    content: '';
    position: absolute;
    display: block;
    top: 40px;
    right: -10px;
    width: 20px;
    height: 20px;
    -webkit-transform: rotate(45deg);
    transform: rotate(45deg);
    background: #eee;
}

But this is clearly no soultion, because the pseudo element is not tranparent.

标签: html css svg
4条回答
够拽才男人
2楼-- · 2020-02-14 06:34

Try this fiddle out, it should set you on your way for what you're looking for.

#notched {
     width: 0px;
     height: 0px;
     border-right: 60px solid transparent;
     border-top: 60px solid #d35400;
     border-left: 60px solid #d35400;
     border-bottom: 60px solid #d35400;
}

Updated fiddle

查看更多
甜甜的少女心
3楼-- · 2020-02-14 06:37

Here's an example using SVG clipping.

jsFiddle Demo

<div></div>
<svg>
  <defs>
    <clipPath id="clipping">
        <polygon points="
             0 0, 202 0,
             202 36, 185 50, 202 64,
             202 102, 0 102" />
    </clipPath>
  </defs>
</svg>
查看更多
Rolldiameter
4楼-- · 2020-02-14 06:42

You cannot do this with pure CSS as clipping is not fully supported yet in all browsers (if cross-compatibility is important).

You would need to combine SVG clipping paths with CSS clipping and would end up with a not so elegant solution.

What you can do however is to create a background image using canvas. Canvas is supported in all the major HTML5 capable browsers. The backdraw with canvas is that you need to do a little more coding to create the shape. Optional an image could have been used instead but using canvas allow you to keep everything sharp (and not blurry as with an image when it is stretched).

The following solution will produce this result (I added red border to show the transparent region). You can tweak the parameters to get it look exactly as you need it to look and extend it with arguments to define size of the notch, width of transparent area etc. The code automatically adopts to the size of the element given as argument.

demo preview

To add a notch simply call:

addNotch(element);

ONLINE DEMO HERE

The code is straight-forward and performs fast:

function addNotch(element) {

    /// some setup
    var canvas = document.createElement('canvas'),
        ctx = canvas.getContext('2d'),

        /// get size of element in pixels
        cs = window.getComputedStyle(element),
        w = parseInt(cs.getPropertyValue('width') || '0', 10),
        h = parseInt(cs.getPropertyValue('height') || '0', 10),

        /// pre-calculate some values
        hh = h * 0.5,
        nw = 20,  /// notch size
        nh = nw * 0.5;

    canvas.width = w;
    canvas.height = h;

    /// draw the main shape        
    ctx.moveTo(0, 0);
    ctx.lineTo(w - nw, 0);
    ctx.lineTo(w - nw, hh - nh);
    ctx.lineTo(w - nw - nh, hh);
    ctx.lineTo(w - nw, hh + nh);
    ctx.lineTo(w - nw, h);
    ctx.lineTo(0, h);
    ctx.closePath();

    ctx.fillStyle = '#7c7058';
    ctx.fill();

    /// draw the white arrow
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = '#eee';
    ctx.moveTo(w - nw - nw * 0.33, hh - nw * 0.75);
    ctx.lineTo(w - nw - nw * 1.1, hh);
    ctx.lineTo(w - nw - nw * 0.33, hh + nw * 0.75);
    ctx.stroke();

    /// convert canvas to image and set background of element
    /// with this image    
    element.style.background = 'url(' + canvas.toDataURL() +
                               ') no-repeat left top';

}
查看更多
一纸荒年 Trace。
5楼-- · 2020-02-14 06:50

You can use the :before for mask and after selector for the border, just set border-lef and border-bottom property.

div:before {
    content: '';
    position: absolute;
    display: block;
    top: 40px;
    right: -10px;
    width: 20px;
    height: 20px;
    -webkit-transform: rotate(45deg);
    transform: rotate(45deg);
    background: #eee;
}
div:after {
    content: '';
    position: absolute;
    display: block;
    top: 38px;
    right: -5px;
    width: 20px;
    height: 21px;
    -webkit-transform: rotate(45deg);
    transform: rotate(45deg);
    background: transparent;
    border-left: 2px solid #eee;
    border-bottom: 2px solid #eee;
}



the result:

enter image description here
jsFiddle

查看更多
登录 后发表回答