3

There's lots of techniques that cover the simplicity of the question, here are my requirements:

  1. I'd like an <hr /> element to be visible, with a portion of it cut out (e.g.; fully transparent)
  2. The width of the <hr /> is unknown
  3. The cutout region has fixed dimensions and must be centered on top of the <hr />
  4. Use 1x <hr /> element
  5. Supported in IE11 and Safari 11, as well as modern browsers

Due to the browser support, I think I am left with using clipPath within an SVG and setting that as the clipping region via CSS on the <hr /> element.

The following demo is not tested in IE/Safari yet and it highlights my attempts to firstly draw an SVG shape with a portion cut out. That part is nearly fine apart from my requirements #2 and #3 because I don't yet have a fluid filling path with a fixed and centred second path inside it.

Requirement #1 currently fails completely, when I convert the path inside the SVG into a clipPath and then assign that to the hr /> element.

Codepen demo: https://codepen.io/davewallace/pen/WNNRMoR

Markup:

<p>1. Aspect ratio in action, box is correctly centered, but I need the black region to stretch all the way to the far left and right edges, leaving the inner cut-out box in the middle.</p>
<div>
    <hr />
    <svg xmlns="http://wwww3org/2000/svg" height="32" width="100%" viewBox="0,0,10,10">
        <path d="M 0,0 h 10 v 10 h -10 z
                         M 2,2 v  6 h  6 v  -6 z" /> 
    </svg>
</div>

<p>2. So I tried removing the aspect ratio. That sort of helped, but I need the inner cut-out box to be a fixed width and centered.</p>
<div>
    <hr />
    <svg xmlns="http://wwww3org/2000/svg" height="32" width="100%" viewBox="0,0,10,10" preserveAspectRatio="none">
        <path d="M 0,0 h 10 v 10 h -10 z
                         M 2,2 v  6 h  6 v  -6 z" /> 
    </svg>
</div>

<p>3. Regardless of the stretching accuracy of the two techniques above, I expected the supplied paths, converted into a clipPath, to hide the centre part of the HR element, leaving only its left/right sides visible.</p>
<div>
    <hr class="clipped" />
    <svg xmlns="http://wwww3org/2000/svg" height="32" width="100%" viewBox="0,0,10,10">
        <defs>
            <clipPath id="square">
                <path d="M 0,0 h 10 v 10 h -10 z
                                 M 2,2 v  6 h  6 v  -6 z" /> 
            </clipPath>
        </defs>
    </svg>
</div>

CSS (mostly to illustrate):

div {
    position: relative;
    border: 1px solid red;
    margin: 50px;
    padding: 20px;
    background: #999;
}
hr {
    height: 5px;
    background: lime;

    &.clipped {
        clip-path: url(#square);        
    }
}
svg {
    position: absolute;
    left: 0;
    top: 20%;
    border: 1px dotted red;
}

Research so far:

Alternative approaches so far:

  • Use flexbox and have 1 <hr />, a gap, and then another element like a <div /> finishing off the second half of the effect. So it's not 'cutting a hole' in the <hr /> but stopping and starting it visually. This approach, in my context, would need some magic numbers and isn't so clean. Pretty sure it's still accessible in that I am still using 1x <hr /> element mostly as it is intended to be used.
  • Nothing else so far, but this is to achieve a "fancy horizontal rule" effect, where someone can drop their image/SVG asset into the middle of the horizontal rule without worrying about the horizontal line going under the asset. I also don't know what the page background colour is, no assumptions can be made about that.

Thank you!

danjah
  • 2,939
  • 2
  • 30
  • 47
  • you will always hide a square part from your element? – Temani Afif Oct 22 '19 at 10:02
  • Well, ideally I'd like to be able to supply custom width/ height values to the inner box, so that a different image/SVG could be used in the centre of the
    . I'd settle for 'always square' in the middle part for now though :)
    – danjah Oct 22 '19 at 21:03
  • then in this case make your element having only border and control their width. You will have your square at the center easily – Temani Afif Oct 22 '19 at 21:06

2 Answers2

0

I suppose your hr element will have a solid coloration as background. Considering this you can play with background to coloration to color only the needed part keeping the middle on transparent.

I will rely on calc() that should work on IE11 but I cannot test it.

hr {
  height:10px;
  margin:10px 0;
  border:none;
  background:
    linear-gradient(blue,blue) left,
    linear-gradient(blue,blue) right;
  background-size:calc(50% - 10px) 100%; /* Cut 20px from the middle */
  background-repeat:no-repeat;
}

body {
  background:pink;
}
<hr>

You can also add some border if you want to have a hole in your element:

hr {
  height:20px;
  margin:10px 0;
  border-top:10px solid blue;
  border-bottom:10px solid blue;
  background:
    linear-gradient(blue,blue) left,
    linear-gradient(blue,blue) right;
  background-size:calc(50% - 10px) 100%; /* Cut 20px from the middle */
  background-repeat:no-repeat;
}

body {
  background:pink;
}
<hr>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Yes, solid background colour is assumed. Your solution works and is simple, I neglected tweaking background directly to do this, thank you for your answer! – danjah Dec 04 '19 at 02:28
0

Just use clip-path and calc().

I used this tool to make a relative path, and then I added manually the calc(). https://bennettfeely.com/clippy/

hr {
  clip-path: polygon(0% 0%, 0% 100%, calc(50% - 10px) 100%, calc(50% - 10px) calc(50% - 10px), calc(50% + 10px) calc(50% - 10px), calc(50% + 10px) calc(50% + 10px), calc(50% - 10px) calc(50% + 10px), calc(50% - 10px) 100%, 100% 100%, 100% 0%);
  height:40px;
  background: black;
}

body {
  background: url(http://placekitten.com/200/300);
  margin: 10px;
}
<hr>
Maurici Abad
  • 1,012
  • 9
  • 20
  • Nice succinct attempt, doesn't work in IE11 though sadly, I think that fall down because of `polygon()`, not 100% sure but either way I just tested it and it's only the black bar, unlike in Chrome that correctly has the transparent cutout. Thank you for your answer though. – danjah Dec 04 '19 at 02:23