Positioning SVGs within a parent container while maintaining responsiveness

How can I anchor an SVG overlay with a circle in the bottom right corner while expanding the rest of the SVG to fill the remaining area of the container without distorting the circle?

I've been able to position the SVG in the bottom right corner, but I'm struggling to make it fill the rest of the container. Any suggestions on how to achieve this without affecting the circle shape would be appreciated.

View codepen example: https://codepen.io/emilychews/pen/KQmZEd

body {
  width: 100%; 
  height: 100vh;
  padding: 0; margin: 0;
  display: flex;}

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: url(https://lorempixel.com/400/400/) center/cover;
  overflow: hidden;
}

#overlay {
position: absolute;
bottom: 0; 
right: 0;
}
<div id="box">
    <svg id="overlay" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 232.71 170.5"><g id="Layer_2" data-name="Layer 2"><g id="Layer_2-2" data-name="Layer 2-2"><path d="M0,0V170.5H232.71V0ZM187.37,148.19a23,23,0,1,1,23-23h0A23,23,0,0,1,187.37,148.19Z" transform="translate(0 0)" fill="#015668"/></g></g></svg>
</div>

Answer №1

I have come up with an alternative solution for creating a hole using a mask in which you can easily manipulate the position and size of the circle. The key is to ensure that the entire SVG overflows with a large width/height to always cover the div while maintaining the size of the circle:

body {
  width: 100%;
  height: 100vh;
  padding: 0;
  margin: 0;
  display: flex;
}

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: url(https://lorempixel.com/400/400/) center/cover;
  overflow: hidden;
}

#overlay {
  position: absolute;
  bottom: 0;
  right: 0;
  width:1000px;
  height:1000px;
}
<div id="box">
  <svg  id="overlay" viewbox="0 0 400 400" >
  <defs>
    <mask id="hole">
      <rect width="100%" height="100%" fill="white"/>
      <!-- This circle represents the hole -->
      <circle r="20" cx="370" cy="370" fill="black"/>
    </mask>
  </defs>

  <rect x=0 y=0 width=400 height=400 mask="url(#hole)" fill="green" />
    
</svg>
</div>

If you want the circle to adjust its size when the width changes, you can explore this approach:

body {
  width: 100%;
  height: 100vh;
  padding: 0;
  margin: 0;
  display: flex;
}

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: url(https://lorempixel.com/400/400/) center/cover;
  overflow: hidden;
}

#overlay {
  position: absolute;
  bottom: 0;
  right: 0;
  width:100%;
}
<div id="box">
  <svg  id="overlay" viewbox="0 0 400 10000" >
  <defs>
    <mask id="hole">
      <rect width="100%" height="100%" fill="white"/>
      <!-- This circle represents the hole -->
      <circle r="80" cx="300" cy="9900" fill="black"/>
    </mask>
  </defs>

  <rect x=0 y=0 width=400 height=10000 mask="url(#hole)" fill="green" />
    
</svg>
</div>


You can achieve the desired opacity as requested in the previous question with ease:

body {
  width: 100%;
  height: 100vh;
  padding: 0;
  margin: 0;
  display: flex;
}

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: url(https://lorempixel.com/400/400/) center/cover;
  overflow: hidden;
}

#overlay {
  position: absolute;
  bottom: 0;
  right: 0;
  width:100%;
}
<div id="box">
  <svg  id="overlay" viewbox="0 0 400 10000" >
  <defs>
    <mask id="hole">
      <rect width="100%" height="100%" fill="white"/>
      <!-- This circle represents the hole -->
      <circle r="80" cx="300" cy="9900" fill="black"/>
    </mask>
  </defs>

  <rect x=0 y=0 width=400 height=10000 mask="url(#hole)" fill="rgba(0,0,255,0.5)" />
    
</svg>
</div>

Answer №2

Let me guide you through the process step by step to create this effect easily and efficiently.

To begin, we will use a basic square SVG with a viewBox set at 100x100. We can then position the circle that will act as our future hole in the bottom right corner of the viewBox.

body {
  width: 100%;
  height: 100vh;
  padding: 0; margin: 0;
  display: flex;}

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: url(https://lorempixel.com/400/400/) center/cover;
  overflow: hidden;
}
<div id="box">
  <svg width="100%" height="100%" viewBox="0 0 100 100">
    <rect x="0" y="0" width="100" height="100" fill="#015668"/>
    <circle cx="70" cy="70" r="20" fill="black"/><!-- the hole -->
  </svg>
</div>

We will utilize

preserveAspectRatio="xMaxYMax meet"
to specify that the SVG contents should be placed in the bottom right corner.

body {
  width: 100%;
  height: 100vh;
  padding: 0; margin: 0;
  display: flex;}

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: url(https://lorempixel.com/400/400/) center/cover;
  overflow: hidden;
}
<div id="box">
  <svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMaxYMax meet">
    <rect x="0" y="0" width="100" height="100" fill="#015668"/>
    <circle cx="70" cy="70" r="20" fill="black"/><!-- the hole -->
  </svg>
</div>

Next, extend the rectangle to the left of the viewBox by setting x="-900" and width="1000". This ensures coverage for various monitor sizes.

A similar adjustment is made vertically to account for potential changes in viewport size.

body {
  width: 100%;
  height: 100vh;
  padding: 0; margin: 0;
  display: flex;}

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: url(https://lorempixel.com/400/400/) center/cover;
  overflow: hidden;
}
<div id="box">
  <svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMaxYMax meet">
    <rect x="-900" y="-900" width="1000" height="1000" fill="#015668"/>
    <circle cx="70" cy="70" r="20" fill="black"/><!-- the hole -->
  </svg>
</div>

Finally, convert this setup into a mask and apply it to a rectangle covering the viewport.

body {
  width: 100%;
  height: 100vh;
  padding: 0; margin: 0;
  display: flex;}

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 200px;
  background: url(https://lorempixel.com/400/400/) center/cover;
  overflow: hidden;
}
<div id="box">
  <svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMaxYMax meet">
    <defs>
      <mask id="mymask">
        <rect x="-900" y="-900" width="1000" height="1000" fill="white" fill-opacity="0.9"/>
        <circle cx="70" cy="70" r="20" fill="black"/><!-- the hole -->
      </mask>
    </defs>
    <rect x="-900" y="-900" width="1000" height="1000" fill="#015668" mask="url(#mymask)"/>
  </svg>
</div>

To test responsiveness, increase the "box" height to 400px and observe its behavior when resizing the browser window.

body {
  width: 100%;
  height: 100vh;
  padding: 0; margin: 0;
  display: flex;}

#box {
  margin: auto;
  position: relative;
  width: 33%;
  height: 400px;
  background: url(https://lorempixel.com/400/400/) center/cover;
  overflow: hidden;
}
<div id="box">
  <svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMaxYMax meet">
    <defs>
      <mask id="mymask">
        <rect x="-900" y="-900" width="1000" height="1000" fill="white" fill-opacity="0.9"/>
        <circle cx="70" cy="70" r="20" fill="black"/><!-- the hole -->
      </mask>
    </defs>
    <rect x="-900" y="-900" width="1000" height="1000" fill="#015668" mask="url(#mymask)"/>
  </svg>
</div>

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

Expand or collapse Angular Material Accordion depending on selected Radio button choice

Is it possible to use a mat-accordion with radio buttons where each panel expands only when its corresponding radio button is selected? I have the radio buttons functioning correctly, but the panels are expanding and collapsing with every click rather than ...

Link to toggle a CSS spoiler button

Currently, I have Ajax set up to replace the main div with a link. In addition, there's a spoiler-type navigation that allows you to hide or show the menu. I have my links inserted in this structure and am trying to figure out how to make it so that c ...

Submitting a form with multiple actions using Ajax

Is it possible to submit data from multiple forms on the same page to different API tables using AJAX for each form? I have one form that needs to write to one table and another form that needs to write to a different table. How can I achieve this with o ...

HTMLMediaElement does not have the setSinkId method

I am currently in the process of developing a WebRTC application using Angular, with the goal of managing audio output through the setSinkId() method within HTMLMediaElement. However, when attempting to use this method, I am encountering an error message s ...

Darken the backdrop of the bootstrap modal

When the modal is opened, the background turns black instead of having an opacity of 0.5 or something similar. How can I resolve this issue? I am using Bootstrap 3.2. Below is some CSS code snippet: .fade.in { opacity: 1; } .modal-open .modal { overflow ...

Contains a D3 (version 3.4) edge bundle chart along with a convenient update button for loading fresh datasets

I am looking to update my D3 (v3.4) edge bundling chart with a new dataset when a user clicks an 'update' button. Specifically, I want the chart to display data from the data2.json file instead of data1.json. Although I have started creating an u ...

Animating links with multi-line effects on :before.orEnhancing

As per the given query, I have a code snippet Is there any way to apply this effect to multiple lines of text instead of just one line? Currently, the effect only appears on one of two text lines (as shown in the example). :root { --00a3a3: #00a3a3; ...

Executing a function every time a prop is updated within the component

I have a prop named transcript in one of my components. Whenever I speak a voice intent, it gets updated. I want to execute a function every time the transcript changes and pass the transcript as an argument. In this code snippet, I attempted to use an On ...

Tips for adding extra spacing between icon and text field using Vuetify

The code snippet below is used for the username section: <v-text-field prepend-icon="fas fa-user" height="60px" placeholder="Username" outlined ></v-text-field> Is there a way to add space between the user ...

Expanding borders occur when the element is repositioned using the translate property

I am trying to create a vertical line that remains in the center of a div container regardless of the screen size. I want this line to be 1px thick. However, when I use transform: translate(-50%, -50%);, the border seems to become thicker than expected. Be ...

css issue with opacity transition not functioning properly

My website is designed to display images in a table, but some of them are Stock Photos, so I need to indicate the source. I want the source to appear when the user hovers over the picture. For this purpose, I have assigned the source tag to a class (.PicSo ...

Ensure that the div stays anchored to the bottom of the page while maintaining its

Although I know this question has probably been asked and answered before, I couldn't find any useful solutions to my specific problem... I'm attempting to position a chat box div at the bottom of a page without being fixed, while still maintain ...

Creating a navigation bar - using the LI tag with spaces between words causes text to wrap to the next line

Currently, I am in the process of creating a dynamic navigation bar for my website. In order to ensure that the elements within the navigation bar adjust automatically based on content, I have implemented the code below: .mytaboptions { position: rela ...

Is there a method to categorize distinct "continuing" numbered list items in order to show that they are interconnected?

There is HTML code that I am currently dealing with, and it looks like this: <ol> <li>...</li> </ol> ... content <ol start="2"> <li>...</li> </ol> ... more content <ol start="3"> <li&g ...

How can images be resized according to screen resolution without relying on javascript?

Looking to use a large banner image on my website with dimensions of 976X450. How can I make sure that the image stretches to fit higher resolution monitors without using multiple images for different resolutions? ...

The main-panel div's width increase is causing the pages to extend beyond the window's width limit

I recently downloaded a Reactbootstrap theme and managed to integrate it with NextJS successfully. However, I am facing an issue where my <div className="main-panel"> in the Layout.js is extending slightly beyond the window. It seems like t ...

Intrigued by the prospect of making HTML elements vanish or smoothly glide along with the content without obstructing it

I'm a beginner in coding and I want to make my website impressive. Right now, I have an HTML embedded element called "On this Page" that I would like to disappear when the user scrolls down the page. I've managed to position the element on the ...

Achieving priority for style.php over style.css

Having trouble with theme options overriding default CSS settings in style.css. Here's what I have in my header.php: <link rel='stylesheet' type='text/css' media='all' href="<?php bloginfo( 'stylesheet_url&apo ...

Creating interactive tabs within the HTML document with AngularJS

Trying to customize the tab layout on my HTML page and I have a code similar to this: <form name="requestForm"> <div class="form-group col-md-6 md-padding"> <div class="text-primary"> <h3>Create Request</h3> ...

Transitioning from a fixed position to absolute in CSS3

Sticky Logo Element In my project, I implemented a logo element that is positioned absolutely within the document. As the user scrolls, the logo sticks to the top of the window with a fixed position (you can view an example here: https://jsfiddle.net/swzb ...