Creating a transparent inner notch?

2020-02-14 06:31发布

问题:

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:

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.

回答1:

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.

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

}


回答2:

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>


回答3:

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



回答4:

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:


jsFiddle



标签: html css svg