How about using a circle inset clip path technique?

Can a unique inset circle clip path be created to cut a hole through the center of a div instead of just showing the center?

The entire div should be visible except for a hole cut out in the center to achieve a design similar to this:

https://i.sstatic.net/6FOaY.png

I am interested in using clip path or a similar technique to showcase images and content behind the div, where the clip path will reveal what is hidden. Essentially, the blue div in my jsfiddle example will gradually disappear from the center to show the content behind it through a transition effect.

div {
  background: blue;
  width: 200px;
  height: 200px;
  -webkit-clip-path: circle(50px at center);
}
<div></div>

https://jsfiddle.net/pm4yvbxn/

Answer №1

It may not be possible to achieve this effect using clip-path, but you can create a hole in a div by utilizing a radial-gradient background. This method has better browser support compared to clip-path.

Keep in mind: This technique (along with box-shadow) will only be effective if the overlaying element has a solid color fill. If you want to use a different image instead of a solid color like sandybrown, these methods will not provide the desired effect as they do not actually "cut a hole," but rather simulate the effect.

.div-with-hole {
  height: 100vh;
  background: radial-gradient(circle at center, transparent 25%, sandybrown 25.5%);
  background-size: 100% 100%;
  background-position: 50% 50%;
  transition: all 2s ease;
}
.div-with-hole:hover {
  background-size: 400% 400%;
}
body {
  background: url(http://lorempixel.com/800/800/nature/1);
  min-height: 100vh;
  margin: 0;
  padding: 0;
}
<div class='div-with-hole'></div>

Answer №2

To make a hole using the clip-path property, you can follow this method:

let precision = 64;
let radius = 25;
let c = [...Array(precision)].map((_, i) => {
  let a = -i/(precision-1)*Math.PI*2;
  let x = Math.cos(a)*radius + 50;
  let y = Math.sin(a)*radius + 50;
  return `${x}% ${y}%`
})

document.querySelector('div').style.clipPath = 
 `polygon(100% 50%, 100% 100%, 0 100%, 0 0, 100% 0, 100% 50%, ${c.join(',')})`;
div {
  background: blue;
  width: 200px;
  height: 200px;
}
<div></div>

Alternatively, you can directly use the resulting clip-path string:

div {
      background: blue;
      width: 200px;
      height: 200px;
    }
<div style="clip-path: polygon(100% 50%, 100% 100%, 0px 100%, 0px 0px, 100% 0px, 100% 50%, 75% 50%, 74.8758% 47.5108%, 74.5043% 45.0463%, 73.8893% 42.6311%, 73.0369% 40.2891%, 71.9555% 38.0437%, 70.656% 35.917%, 69.1511% 33.9303%, 67.4559% 32.1033%, 65.5872% 30.4542%, 63.5637% 28.9994%, 61.4053% 27.7532%, 59.1335% 26.7282%, 56.771% 25.9344%, 54.3412% 25.3798%, 51.8683% 25.0699%, 49.3767% 25.0078%, 46.8914% 25.194%, 44.437% 25.6268%, 42.0378% 26.3018%, 39.7178% 27.2124%, 37.5% 28.3494%, 35.4064% 29.7015%, 33.4579% 31.2555%, 31.6737% 32.9957%, 30.0717% 34.9049%, 28.6677% 36.9641%, 27.4758% 39.1529%, 26.5077% 41.4495%, 25.7731% 43.8311%, 25.2792% 46.2739%, 25.0311% 48.7539%, 25.0311% 51.2461%, 25.2792% 53.7261%, 25.7731% 56.1689%, 26.5077% 58.5505%, 27.4758% 60.8471%, 28.6677% 63.0359%, 30.0717% 65.0951%, 31.6737% 67.0043%, 33.4579% 68.7445%, 35.4064% 70.2985%, 37.5% 71.6506%, 39.7178% 72.7876%, 42.0378% 73.6982%, 44.437% 74.3732%, 46.8914% 74.806%, 49.3767% 74.9922%, 51.8683% 74.9301%, 54.3412% 74.6202%, 56.771% 74.0656%, 59.1335% 73.2718%, 61.4053% 72.2468%, 63.5637% 71.0006%, 65.5872% 69.5458%, 67.4559% 67.8967%, 69.1511% 66.0697%, 70.656% 64.083%, 71.9555% 61.9563%, 73.0369% 59.7109%, 73.8893% 57.3689%, 74.5043% 54.9537%, 74.8758% 52.4892%, 75% 50%);"></div>

Answer №3

Using the mask property allows for versatile background options:

div {
  background: linear-gradient(blue, red);
  width: 200px;
  height: 200px;
  -webkit-mask: radial-gradient(50px, #0000 98%, #000);
          mask: radial-gradient(50px, #0000 98%, #000);
}
<div></div>

This technique can also be implemented with animations:

div {
  background: linear-gradient(blue,red);
  width: 200px;
  height: 200px;
  -webkit-mask:
    radial-gradient(farthest-side,#000 98%,#0000) center/50px 50px no-repeat,
    linear-gradient(#000 0 0);
  -webkit-mask-composite:destination-out;
   
  mask:
    radial-gradient(farthest-side,#000 98%,#0000) center/50px 50px no-repeat,
    linear-gradient(#000 0 0);
  mask-composite:exclude;
  transition:0.5s;
}
div:hover {
  -webkit-mask-size:290px 290px,auto;
          mask-size:290px 290px,auto;
}
<div></div>

Answer №4

Another option is using the box-shadow property on the :after pseudo-element

div {
  position: relative;
  width: 300px;
  height: 200px;
  overflow: hidden;
  background: url('http://planetcompas.com/live/wp-content/uploads/2013/04/2015-01-Beautiful-Planet-And-Space-4-Cool-Wallpapers-HD.jpg');
  background-size: cover;
  background-position: center;
}
div:after {
  width: 50px;
  height: 50px;
  content: '';
  border-radius: 50%;
  background: transparent;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0px 0px 0px 300px lightblue;
  transition: all 0.3s linear;
}
div:hover:after {
  opacity: 0;
}
<div></div>

Answer №5

Using an SVG mask for a creative effect

Employing a circle as a mask with an animated radius

Click on the image to initiate the animation

<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"  width="300" height="300" viewBox="0 0 600 600" >  
     <defs>
         <!-- Multicolor radial gradient -->
     <radialGradient id="grad" x1="0" y1="0" x2="100%" y2="0">

        <stop offset="10%" stop-color="#48afc1" />
        <stop offset="10%" stop-color="#b4c63b" />
       <stop offset="20%" stop-color="#ef5b2b" />
       <stop offset="20%" stop-color="#503969" />
        <stop offset="30%" stop-color="#ab6294" />
        <stop offset="30%" stop-color="#1cb98f" />
        <stop offset="40%" stop-color="#48afc1" />
        <stop offset="40%" stop-color="#b4c63b" />
        <stop offset="50%" stop-color="#ef5b2b" />
        <stop offset="50%" stop-color="#503969" />  
        <stop offset="60%" stop-color="#ab6294" />
        <stop offset="60%" stop-color="#1cb98f" />
       <stop offset="70%" stop-color="#48afc1" />
        <stop offset="70%" stop-color="#b4c63b" />
        <stop offset="80%" stop-color="#ef5b2b" />
        <stop offset="80%" stop-color="#503969" />
        <stop offset="90%" stop-color="#ab6294" />
        <stop offset="90%" stop-color="#1cb98f" />
        <stop offset="100%" stop-color="#48afc1" />
     </radialGradient>
         <!-- Mask -->
     <mask id="msk1" > 
            <rect  width="100%" height="100%"  fill="black" /> 
             
       <circle cx="300" cy="300"  r="0" fill="white" >
            <!-- Animation of a mask cutting through the image of a dragon and showing a radial gradient  -->
         <animate attributeName="r" begin="svg1.click" dur="8s" values="0;300;300;0;0" fill="freeze" repeatCount="3" />
        </circle>
     </mask>
     </defs> 
               <!-- Radial gradient background image  -->
      <circle  cx="300" cy="300"  r="300"  fill="url(#grad)"  />  
                 
          <image xlink:href="https://i.sstatic.net/6kywq.png" x="-140" y="-60" mask="url(#msk1)" width="800" height="780" />  

</svg>

Answer №6

After reading through Stranger in the Q's response, I devised a dynamic solution to tackle this issue.

The approach I came up with accommodates rem, em, px, and percent units, while also leveraging attributes on the element.

function parseUnitsToPercent(str, divider){
  var match = str.match(/^calc\((.+)\);?$/);
  if(match){
    var val = [...match[1].matchAll(/((?:\d(?:\.\d)?)+(?:px|rem|em|%)?)(?:\s([\+|\-|\*|\/])\s)?/g)].map(e=>e.slice(1)).flat().filter(e=>!!e);
    val = val.map(e=>{
      if(['+','-','*','/'].includes(e)){
        return e;
      }
      return convertUnitsToPercent(e, divider);
    });
    try {
      str = eval(val.join(' '));
    } catch(e){
      str = 0;
    }
  }
  return convertUnitsToPercent(str, divider); 
}
function convertUnitsToPercent(str, divider){
  if(str.toString().endsWith('rem')) {
    str = parseFloat(str) * parseFloat(getComputedStyle(document.documentElement).fontSize) + 'px';
  }
  if(str.toString().endsWith('em')) {
    str = parseFloat(str) * parseFloat(getComputedStyle(elem).fontSize) + 'px';
  }
  if(str.toString().endsWith('px')) {
    str = parseFloat(str)/divider*100;
  }
  if(str.toString().endsWith('%')) {
    str = parseFloat(str);
  }
  return str;
}
document.querySelectorAll('[clip-x][clip-y][clip-size]').forEach(elem=>{
  if(elem.getAttribute('width')) elem.style.width = elem.getAttribute('width') + 'px';
  if(elem.getAttribute('height')) elem.style.height = elem.getAttribute('height') + 'px';
  var x = elem.getAttribute('clip-x');
  var y = elem.getAttribute('clip-y');
  var size = elem.getAttribute('clip-size');
  var elem_size = elem.getBoundingClientRect();
  x = parseUnitsToPercent(x, elem_size.width);
  y = parseUnitsToPercent(y, elem_size.height);
  var radius_x = parseUnitsToPercent(size, elem_size.width);
  var radius_y = parseUnitsToPercent(size, elem_size.height);
  var precision = parseFloat(elem.getAttribute('clip-precision') || 64);
  var c = [...Array(precision)].map((_, i) => {
    var a = -i/(precision-1)*Math.PI*2;
    var _x = Math.cos(a)*radius_x + x;
    var _y = Math.sin(a)*radius_y + y;
    return `${_x}% ${_y}%`
  });
  elem.style.clipPath = `polygon(100% 50%, 100% 100%, 0 100%, 0 0, 100% 0, 100% 50%, ${c.join(',')})`;
});
div {
  background: blue;
}
<div clip-x="50%" clip-y="calc(50% + 20px)" clip-size="50px" clip-precision="64" width="400" height="200"></div>

Although this query dates back quite a bit, I discovered it to be extremely helpful, so I customized it to suit my needs. I've decided to share my version with you.

My code also accommodates calc() (Please keep in mind: It utilizes eval(), making it vulnerable to potential security issues with user-input codes!)

Answer №7

To achieve this, simply insert elements within a <div> tag.

In this example, I utilized a <span> element. Here is the code

HTML

<div>
  <span></span>
</div>

CSS

div{
  background: blue;
  width: 200px;
  height: 200px;
  -webkit-clip-path: circle(50px at center);
  position:relative;
}
div span{
  position:absolute;
  display:block;
  width:30px;
  height:30px;
  border-radius:100%;
  background:#fff;
  top:50%;
  left:50%;
  transform:translate(-50%,-50%)
}

See example here: https://jsfiddle.net/pm4yvbxn/2/

Another option is to utilize border-radius in the div element for rounded borders.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What steps should be taken to correct the misalignment of the closing x symbol in the alert box?

After making adjustments to the line height, the closing x mark on the right now aligns closer to the bottom of the alert message box. I am currently utilizing Bootstrap version 5.0.1. Is there a way for me to vertically center the x mark? Thank you. CSS: ...

What is the best way to use HTML and CSS to center images and headings on a webpage?

This task is really testing my patience... I'm attempting to create a layout that resembles the following: Logo img|h1|img The horizontal lines flanking the subtitle serve as a visual guide, like this --- Subtitle --- Below is the snippet of H ...

How can I show hidden column names in the Sencha Touch 2 date picker component with CSS?

I am currently utilizing a date and time picker that has the ability to display ['month', 'day', 'year','hour','minute','ampm']. You can find the source code here. Although everything is function ...

The functionality of a Cordova application using Framework 7 CSS can vary across different Android devices

A link is shared for reference showcasing how the progress bar appears on Samsung j2 and other Android devices. Here is the link: [https://i.sstatic.net/C9OpS.jpg](https://i.sstatic.net/C9OpS.jpg) On my personal device, the progress bar is displayed at th ...

When setting the margin to auto, it perfectly centers elements on servers and IE, but on Chrome off the server, it appears to be aligned to the

There seems to be an issue with the display of my page in Chrome - it starts at the middle and ends on the right side. However, when I view it on my server or try it on Internet Explorer 11, it appears centered. Why is that? This problem only arose after ...

The line directly following the first line within the <li> element is located in the same position

I need help with customizing the bullet background-image for an <li> element. I want the text in the bullet to be displayed outside the marker using the CSS property list-item-position: outside. However, my current implementation doesn't seem to ...

Is there a way to adjust the label elevation for a Material UI TextField component?

I am trying to enhance the appearance of a textfield label, but I am facing some challenges with my code. textStyle: { backgroundColor: '#1c1a1a', border: 0, borderRadius: 0, width: 400, height: 66, display: 'flex&a ...

Tips on eliminating borders in react-table components

Within my React.js component, I have implemented a table using react-table along with some material-ui components displayed alongside the table: import React from 'react' import { useTable, useGlobalFilter, usePagination } from 'react-table& ...

Ideal C++ tool for displaying a non-changing HTML page

I am looking to develop a simple cross-platform C++ project for displaying HTML pages, like an application that showcases help materials. These pages may contain images and styles (CSS embedded in HTML). I am researching the best way to incorporate the fol ...

Struggling to implement a vertical scroll bar in HTML code?

<body ng-app="myApp" ng-controller="myCtrl"> <div ng-show = "dataFromRest" ng-repeat = "x in dataFromRest.posts" > <div class="tittle" style="width: 25%;"> <a href="" ng-click="showDi ...

How can we align divs in the center horizontally inside a parent div?

This question has been asked many times, but I can't seem to figure it out in my situation as I am new to HTML. I have three divs (boxes: QM, Audit, PM) and I want to center them within a parent div called Services. In the photo provided, you can see ...

Adjusting the size of icons to fit within a container

I need a div that can display up to 7 icons, depending on certain selections. These icons are from ionicons library. Here is the current code snippet: <div class="item item-text-wrap" style="text-align:center;"> <button class="button" style=" ...

break-word property not functioning correctly within pre tag

Each row in my dataTable triggers a modal to appear: <div id="verifyModal" class="modal"> <div class="modal-content"> <h2>Verify # <span id="verify-modal-id"></span></h2> <pre><code class="" id="verif ...

Tips for activating a dropdown in Bootstrap 4

I am currently working on a dropdown menu where I want to set an active state upon a click. The active class is added successfully when a link is clicked, but the issue arises when trying to remove the active class when another link is clicked. I only want ...

Reorganize div elements responsively using Bootstrap 5.0

Struggling with web design using HTML, CSS, and Bootstrap v5.0, I am facing an issue. I have three divs A, B, and C that I want to reorder responsively as shown in the image below. A consists of a h2 and p tag, B includes two buttons, and C displays an ima ...

Populating container with video element

I have divided my page into 4 quadrants using viewheight and percentage widths, which has been successful. Now, I want to insert a video in each div that can responsively fill its parent div. When I assign width: 100% to the video, it causes some alignmen ...

Enhancing Tabulator tooltips with custom CSS styles

Is there a way to style the tooltips that appear when hovering over cells in my Tabulator table? When I set tooltips:true, Tabulator adds a title tag, but applying CSS inline has been tricky. So far, I have tried: div[title]:hover:after { content:attr( ...

Unable to adjust the padding of the material UI Select component

I'm having trouble adjusting the padding of the Select component in order to align it with the size of my other text fields. Despite knowing that I need to make changes to nested components, I have yet to discover a viable solution. <div className ...

Is a CSS-only autoexpanding label possible within a list?

I am interested in having all the labels automatically expand to the size of the widest one. Below is the HTML structure: <div class="body"> <ul class="list"> <li> <span> <label>condition</label> ...

Tips for adjusting the placeholder color in Material UI using React JS

Is there a way to customize the background color and flashing color of the Skeleton component in Material UI? I would like to implement custom styling for it, similar to what is shown below: <Skeleton variant="circle" classes={{root:'pla ...