38

Definition of Hole in a div - An element or a method by which you can show the background, only for a particular area, behind the content of a <div> element.

Brian Webster
  • 30,033
  • 48
  • 152
  • 225
Sussagittikasusa
  • 2,525
  • 9
  • 33
  • 47
  • 1
    you mean creating a mask? best thing would split the div up in portions and make the opacity 0 in the part where you want to unmask – Breezer Dec 03 '10 at 11:07
  • Not like a mask, something like a see through lens. – Sussagittikasusa Dec 03 '10 at 11:09
  • k but my answer stays the same split the div up in portions and make the opacity 0 in the part where you want to lens :P – Breezer Dec 03 '10 at 11:10
  • Its going to be really difficult splitting that div up man, there has to be another way. – Sussagittikasusa Dec 03 '10 at 11:12
  • 4
    Is it an option to create a GIF with a transparent area and use this as background-image of the div(background-color of the div has to be set to transparent)? – Dr.Molle Dec 03 '10 at 11:13
  • Yeah, then after that? How do we make it seethrough in a particular area? – Sussagittikasusa Dec 03 '10 at 11:16
  • nope trust me when i say it's not possible, you have to see a page as layers of boxes where you can do anything to the entire box but nothing with just a portion of it – Breezer Dec 03 '10 at 11:24
  • Hmmmm... maybe the background of this div element can be broken into smaller boxes... and I can achieve what I'm looking for. – Sussagittikasusa Dec 03 '10 at 11:27
  • could you possible show us your page and maybe tell us what you want to be able to see through the lens – Breezer Dec 03 '10 at 11:29
  • regarding to my comment above: the transparent area of the background-image will be the area you can see trough. – Dr.Molle Dec 03 '10 at 12:26

10 Answers10

56

CSS box-shadow is supported in almost all modern browsers, so you can do what you want (I hope, I understood you right) this way:

body {
  margin: 0;
  padding: 0;
}

.hole {
  position: absolute;
  left: 50px;
  top: 50px;
  width: 100px;
  height: 100px;
  box-shadow: 0 0 0 99999px rgba(0, 0, 0, .8);
}
<img src="http://upload.wikimedia.org/wikipedia/commons/5/51/Fox_Head.jpg" alt="" style="width: 100%;">
<div class="hole"></div>

So, the block will be transparent, and all around it will be highlighted with its shadow.

Anurag Srivastava
  • 14,077
  • 4
  • 33
  • 43
equinox
  • 701
  • 5
  • 8
  • 3
    or you can use outline: "outline: 99999px solid rgba(0, 0, 0, .8);" – equinox Oct 27 '14 at 14:53
  • 2
    Best solution so far. – user50992 Dec 04 '14 at 10:44
  • 1
    @equinox outline-width appears to max out at 65534px on Chrome version 40.0, so "outline: 65534px solid rgba(0, 0, 0, .8)" is fine, but higher values of outline-width result in no outline. There's a similar, though higher, limit with FF, too. – Paul Pepper Feb 18 '15 at 22:19
  • Outline seems not to support border-radius, it is block. Beware of using accidentally big blur radius eg. 0rem 0rem 4000rem 4000rem hsla(0, 0%, 0%, 0.6). In Mac Chrome Version 41.0.2272.104 (64-bit) causes significant slowness if background has eg. a table with few tens of cells. Scrolling and responsiveness to mouse is slow. Also it causes random rendering errors. Using blur radius 0 or outline is fast. – Timo Kähkönen Apr 04 '15 at 19:50
  • Making a huge box-shadow spread doesn't work on ios - disappears altogether when it exceeds some limit. equinox's solution: `outline: 9999px solid rgba(0, 0, 0, .8);` works great on ios. Although, as Paul Pepper points out, `99999px` probably exceeds an outline limit... but why would anyone want an outline 100,000px??? – sterfry68 Jul 01 '17 at 17:47
  • On iOS Safari I see an upper limit of `box-shadow` combined with `border-radius: 50%` at `951px`. After that, it just disappears. The `outline` combined with `border-radius` does not work for me on iOS. – jkettmann Jul 08 '18 at 08:01
  • 1
    Instead of setting an impossible high size like 99999px, for my use case, `calc(100vw + 100vh)` worked pretty well (also on iOS). – Jefrey Sobreira Santos Sep 02 '19 at 20:28
35

A new way to solve this, using blend modes, and supporting border-radius, multiple elements... but without support in IE

.back {
 background-color: lightblue;
 width: 400px;
 height: 300px;
 background-image: repeating-linear-gradient(45deg, white 0px,lightblue 40px);
}

.base {
 position: relative;
 left: 10px;
 top: 10px;
 width: 200px;
 height: 200px;
 border: solid 1px black;
 background-color: white;
 mix-blend-mode: hard-light;
}

.hole {
 width: 80px;
 height: 50px;
 margin: 10px;
 border: solid 1px red; 
 border-radius: 10px;
 background-color: gray;
}
<div class="back">
 <div class="base">
  <div class="hole">ONE</div>
  <div class="hole">TWO</div>
 </div>
</div>
vals
  • 61,425
  • 11
  • 89
  • 138
  • This is some great information to know - I had not heard of `mix-blend-mode` beforehand. This should be the accepted answer. – Gershom Maes Oct 07 '15 at 22:56
  • This is awesome, I agree, this is the best answer – whaley Apr 14 '16 at 21:54
  • @vals, Why is this only working with "gray" color for the Hole (any other color will not create a hole)??? – Gil Epshtain Jun 26 '18 at 15:45
  • @GilEpshtain the **hard-light** blend-mode , when the channel intensity is 0.5 (or 128 in rgb scale), will reproduce the color of the background. gray is 0.5 in all chanels, so it reproduces fully the background – vals Jun 26 '18 at 17:18
  • 4
    It should be noted though that this **significantly decreases font quality** on both Firefox and Chrome (at least on Manjaro Linux) and that any color **other than `white`, `black`, `red`, `blue`, `lime`, `cyan`, `magenta` and `yellow`** become (partly) transparent. This affects not only the background color, but also text, borders, etc. – Aloso Aug 09 '18 at 15:36
  • @vals what would be the solution if you wanted the **base** div to be of any other color, for example pink? also the children? – sima ghoreyshi Dec 04 '21 at 06:09
  • @simaghoreyshi You can not choose any color , only colors with RGB values of 0 or 255 are supported (so, red or green is ok, also yellow, but not pink) – vals Dec 04 '21 at 18:47
13

You can construct a set of frame divs in the following format:

alt text

So, one container div, with no/little style applied to it.

Then a set of 4 'border' divs with style applied to them, leavin the central area transparent.

Tom Gullen
  • 61,249
  • 84
  • 283
  • 456
4

Found it!

  1. Parent div with a relative position, a transparent background and hidden overflow.
  2. Child div with absolute position, with colored, super big borders to fill the background of the parent, and a transparent background.

The hole will be composed of a transparent child, with borders so big they fill up the parent's background. The positioning of the child will depend of the size of the borders. Set a background to whatever is behind the parent, and it will show through!

In this example you can see the red through the yellow faux background (which is actually a huge border).

#parent{overflow:hidden; position:relative;}
#child {position:absolute; border:9000px yellow solid; top:0; left:0;}

http://jsfiddle.net/CarambaMoreno/UrbhS/

What do you think?

3

I designed something on code pen that I think you are/were looking for. I was looking for the same... couldn't find anything so this is what I made

Demo

3

You can use a png with alpha channel transparency as the background image of your div.

<div style="background-image:url(pngwithtransparentarea.png);width:100px;height:100px;">
</div>
Bazzz
  • 26,427
  • 12
  • 52
  • 69
2

There's one approach, albeit it can only do mostly rectangular borders, with the following mark-up as a demo:

html:

<div id="wrap">
    <div id="frame">
    </div>
    <img src="http://farm3.static.flickr.com/2232/2299184911_ea1091968b_z.jpg?zz=1" />
</div>

css:

#wrap {
    overflow: hidden;
    position: relative;
}

#frame {
    border: 60px solid #000;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background-color: rgba(255,255,255,0.5);
}

Demo at JS Fiddle.

While there's no way to truly 'cut' a hole in a div, there is the possibility of using -webkit-mask-box-image to apply masks directly to images. Albeit this only works in, so far as I'm aware, Webkit browsers (I know that it's a -webkit vendor-prefixed property, but I don't believe that there's a -moz or -o equivalent, sadly).

Demo using the above, -webkit-mask-box-image property, at JS Fiddle.

David Thomas
  • 249,100
  • 51
  • 377
  • 410
  • Hey David thanks though this is not what i wanted. Suppose your '#wrap', or any outside container had a background color. The code should've been able to penetrate through the image and show the background color of the outside container. – Sussagittikasusa Dec 03 '10 at 11:25
  • @Sussagittikasusa: ah, in which case I may have completely misunderstood your question. – David Thomas Dec 03 '10 at 11:28
1

The larger issue is not actually the background of the element you want to see through (which would just be background-color:transparent) but instead its ancestor element(s). For instance, a div with a background-color: transparent is still going to look as if it has a white background if its containing element has a white background. The best approach then is to define the background colors at lower levels in the page. For instance, if you want to see through div#see-through and it's a child of div#content which is in between div#header and div#footer, you could give #header and #footer background colors but define #content as transparent. Then assign background colors to the individual sibling elements of #see-through. One more thing: it might be helpful to remember when defining the transparent element that even a transparent element can have "colored" borders, meaning that you might be able to reach into in-between spots without adding extra elements.

DavidH
  • 34
  • 1
  • Just asking, is it possible to cut a hole through an element with having the element a background color gradient? – Green Feb 20 '21 at 23:32
0

After really thinking this through best thing i could come up with is if you use an iframe it could be the "lens" that views whatever you desire but ofcourse it wont work like a real lens but close to

Breezer
  • 10,410
  • 6
  • 29
  • 50
0

If it's acceptable to use an SVG element instead of a div, SVG provides a flexible mechanism for cutting holes using the fill-rule="evenodd" attribute. You can create as many transparent regions of any shape as you'd like.

Here's an example that cuts two square holes into a gray square (also available as a JSFiddle):

<img
  src="http://upload.wikimedia.org/wikipedia/commons/5/51/Fox_Head.jpg"
  style="position: absolute; width: 300px;"
>

<svg style="position: absolute; width: 300px; height: 300px;">
<!--
  This `path` element draws 3 squares:
    1. A gray 300x300 square
    2. A transparent 100x100 square
    3. Another transparent 100x100 square
  
  The key mechanism for creating transparent regions in the shape is
  `fill-rule="evenodd"`. This attribute affects pixel colors in the following
  way. Pick a pixel and draw an infinitely long line in any direction:
    - If the line crosses an odd number of lines, the pixel receives the fill
      color. In this fiddle, the infinite line extending from any gray pixel
      crossed an odd number of lines -- for example, just the line that is the
      perimeter of the gray rectangle.
    - If the line crosses an even number of lines, the pixel is transparent.
      In this fiddle, the infinite line extending from any transparent pixel
      crossed an even number of lines -- for example, the perimeters of the
      transparent square and the gray square.
-->
<path
  fill="grey"
  fill-rule="evenodd"
  d="
    M 0 0
    h 300
    v 300
    h -300
    Z
    
    M 25 50
    h 100
    v 100
    h -100
    Z
    
    M 175 50
    h 100
    v 100
    h -100
    Z
  "
/>
</svg>
rigdern
  • 103
  • 4