Using SVG as a flexible background with position: absolute; - html

I'd like to be able to use inline SVGs as background images – without actually using them as CSS background images.
I need the ability to change the fill of the SVG, so with the help of some absolutely positioned elements I thought it would be possible to do it. But I'm not having much luck.
Example HTML:
<div class="block">
<div class="block-bg">
<svg><!-- SVG code --></svg>
</div>
<div class="block-text">
<p>Content</p>
</div>
</div>
In this approach the SVG is placed behind the <div class="block-text"> in an attempt to have it grow/shrink/respond to the content.
My current CSS:
.block {
position: relative;
}
.block-bg {
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: 100%;
height: 100%;
}
.block-text {
position: relative;
z-index: 2;
padding: 10rem;
}
.block-bg svg {
fill: grey;
}
Pretty simple stuff, but SVGs seem to be tricky to get to act right in certain circumstances.
Preserving the aspect ratio isn't needed, so the SVG shape can warp to whatever size the content forces it. I also need the SVG to be responsive – so when the viewport is wider or small the SVG scales accordingly. Is this possible?
Here's a Codepen with some example code: https://codepen.io/abbasarezoo/pen/86f824a2d5a57279c19b33cf14d8904a
Thanks for any help with this.

Your SVG needs to fill out the space it's given with width: 100%; height: 100%;, and if you set the preserveAspectRatio to "none" on your SVG element, you will get the result you're after:
.block {
position: relative;
}
.block-bg {
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: 100%;
height: 100%;
}
.block-text {
position: relative;
z-index: 2;
padding: 10rem;
}
.block-bg svg {
fill: grey;
width: 100%;
height: 100%;
}
<div class="block">
<div class="block-bg">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1760 515" preserveAspectRatio="none"><!-- SVG code --></svg>
</div>
<div class="block-text">
<p>Content</p>
</div>
</div>
With your CodePen SVG data, here's an updated working demo.

Related

Placing many images on top of another image with CSS

Beginner in CSS here.
Basically, what I am trying to do is to place check marks or X-es on top of a country map and I am trying to find the best way to do this.(open to learn JS for this)
So far, I have placed my map in a div and centered it, with HTML code <img src="check mark"> after the map image.
I will do this for every check mark i have to add, but is it there any better solution ?
.container {
margin-left: 10%;
width: 75%;
height: 80%;
display: flex;
justify-content: center;
}
.child {
position: relative;
margin: 0 auto;
}
.check {
position: absolute;
top: 300px;
right: 500px;
}
<div class="container">
<div class="child">
<img src="Map_image.png">
</div>
</div>
This is an example of what i want to achieve:
https://imgur.com/a/mu5WpuN
Short answer is create a wrapper div with position: relative and place the map and the Xes inside it. Then make map fit with the wrapper (i.e. 100% width and height or whatever) then make all Xes position: absolute and position them accordingly using top: left: right: bottom: properties
Here's a working sample. Try to run it.
.wrapper {
position: relative;
width: 100%;
}
img.map {
width: 100%;
}
img.marker {
position: absolute;
width: 20px;
}
.marker.x1 {
top: 20px;
left: 50px;
}
.marker.x2 {
top: 50px;
left: 190px;
}
<div class="wrapper">
<img class="map" src="https://www.onlygfx.com/wp-content/uploads/2015/12/world-map-vector.png" alt="map">
<img class="marker x1" src="https://i.pinimg.com/474x/b1/7e/59/b17e59bc32383f7878c9132081f37c60.jpg" alt="x1">
<img class="marker x2" src="https://i.pinimg.com/474x/b1/7e/59/b17e59bc32383f7878c9132081f37c60.jpg" alt="x1">
</div>

Width percentage value not being applied to element

I am styling an element in HTML using Sass, and when setting the width of an element using percentages, it is not applied.
Could this be due to me setting the parent element's width and height using "content-max"?
Here is a basic version of the code I am using, the idea is for the parent's size to be limited by the image size (which works), and for the text overlay to be half the width and the full height of the container element (hence me using 50 and 100 percent respectively).
<div class="container">
<img src="image.png" alt="A square image">
<div class="text-overlay">
</div>
</div>
The separately complied Sass is as follows:
.container {
display: block;
position: relative;
width: max-content;
height: max-content;
img {
display: block;
position: absolute;
z-index: 0;
}
.text-overlay {
display: flex;
position: absolute;
width: 50%;
height: 100%;
z-index: 1;
}
}
Both HTML and SCSS are written in different files and correctly complied where necesary.
As mentioned in the comments, you can not write Sass directly inside your HTML markup. It has to be compiled first.
In your example you are using nesting, which is not valid CSS3 code, so to fix this behavior you either have to write plain CSS like the snippet below or compile your Sass before you apply it to your HTML.
About your actual question, the positioning you are trying to archieve is working, when you hardcore the width and height to the .container element.
.container {
position: relative;
width: 200px;
height: 200px;
}
.container img {
position: absolute;
z-index: 0;
}
.container .text-overlay {
position: absolute;
z-index: 1;
width: 50%;
height: 100%;
background-color: green;
color: red;
opacity: 50%;
}
<div class="container">
<img src="https://i.picsum.photos/id/793/200/200.jpg?hmac=3DeE830wjdSShKq_h_iFtV_jAxf43FO4xx-sivW0Q_Y">
<div class="text-overlay">
Overlay
</div>
</div>

Stretch background image width but crop height

How do you make a background img that would:
Stretch across the window horizontally
Have a fixed height
Crop height when it's bigger than the content's height (do not shrink)
Currently I have this code that implements #1 and #2 but I can't seem to make it do #3:
<img class="background" src="images/page-background.png"/>
html {
position: relative;
}
.background {
width: 100%;
height: 2800px;
position: absolute;
top: 0;
left: 0;
z-index: -1;
}
I tried moving the img inside a div with overflow: hidden but that didn't work for some reason:
<div class="background-wrap">
<img class="background" src="images/page-background.png"/>
</div>
.background-wrap {
position: absolute;
width: 100%;
height: 1000px;
overflow: hidden;
z-index: -1;
}
How would you do this properly in CSS / HTML (without JavaScript)?
You could use a css background-image on a div like so:
.background-wrap {
background: url(images/page-background.png) no-repeat;
background-size: 100% 500px;
}
The background-size specifying that;
Stretch 100% across the window horizontally, and have a 500px fixed height (change this to auto if you want the image height to scale in proportion to the width).
Sorry guys, it turns out I completely forgot to remove a duplicate background <img> that I left after splitting my HTML in multiple files (actually PHP files but that's irrelevant).
For the sake of future reference, the following worked for me:
<html>
<head>...</head>
<body>
<div class="background-wrap">
<img class="background" src="images/page-background.png"/>
</div>
</body>
</html>
html {
position: relative;
}
.background-wrap {
position: absolute;
width: 100%;
top: 0;
bottom: 0;
overflow: hidden;
z-index: -1;
}
.background {
width: 100%;
height: 2800px;
position: absolute;
top: 0;
left: 0;
z-index: -1;
}

Using CSS "padding-trick" for proportional resizing on Y-axis?

I'm building an web app which has a 100% height/width/fullscreen layout. I am looking for a CSS-trick to proportionally resize an elements dimensions according to its height.
Right now I am looking for an equivalent of what this trick does to the x-axis:
html, body{
height:100%;
margin:0;
}
#view {
min-height: 100%;
position: relative;
width: 100%;
background-color: #333333;
}
#test-hld {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
background-color: tomato;
width: 100%;
height: 75%;
}
.test{
position: relative;
width: 30%;
}
.test:before{
content: "";
display: block;
padding-top: 75%;
}
.content{
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: black;
}
<div id="view">
<div id="test-hld">
<div class="test">
<div class="content"></div>
</div>
</div>
</div>
But changing (for example) .test{height: 80%} and .test:before{padding-left: 75%} makes the browser render no dimensions of the box at all.
My question(s) is
Why is the opposite not working?
Has it something fundamental to do with setting heights of elements with CSS?
Can flex/flexbox solve this?
I know it's possible to fix this with some lines of JS but I just can't believe it's not doable with CSS until someone slaps my face telling me to get real.
First of all, just to know why the padding trick works.
Padding-top and padding-bottom are vertical dimensions that are related to the width (so, an horizontal dimension) of the container.
That allows the ratio of an element to be fixed, and related to the width of the container. But there isn't any horizontal dimension that is related to some vertical of the container, so the equivalent trick over the height is not posible right now.
I have tried to get this same result using another technique, but I have had a very partial success.
My failed attempt is try to use an image to set the ratio
body, html {
height: 99%;
}
.base {
height: 40%;
border: solid 1px green;
display: inline-block;
position: relative;
}
.ratio {
content: url("http://placehold.it/400x200");
opacity: 0.05;
height: 100%;
width: auto;
position: relative;
}
<div class="base">
<img class="ratio" />
</div>
This is working in IE and Chrome, and failing in FF. But just on initial loading.
Changing the browser size won't work until the page is reloaded. I just can't figure out why, or how to solve it

Make Div overlay ENTIRE page (not just viewport)?

So I have a problem that I think is quite common but I have yet to find a good solution for. I want to make an overlay div cover the ENTIRE page... NOT just the viewport. I don't understand why this is so hard to do... I've tried setting body, html heights to 100% etc but that isn't working. Here is what I have so far:
<html>
<head>
<style type="text/css">
.OverLay { position: absolute; z-index: 3; opacity: 0.5; filter: alpha(opacity = 50); top: 0; bottom: 0; left: 0; right: 0; width: 100%; height: 100%; background-color: Black; color: White;}
body { height: 100%; }
html { height: 100%; }
</style>
</head>
<body>
<div style="height: 100%; width: 100%; position: relative;">
<div style="height: 100px; width: 300px; background-color: Red;">
</div>
<div style="height: 230px; width: 9000px; background-color: Green;">
</div>
<div style="height: 900px; width: 200px; background-color: Blue;"></div>
<div class="OverLay">TestTest!</div>
</div>
</body>
</html>
I'd also be open to a solution in JavaScript if one exists, but I'd much rather just be using some simple CSS.
The viewport is all that matters, but you likely want the entire website to stay darkened even while scrolling. For this, you want to use position:fixed instead of position:absolute. Fixed will keep the element static on the screen as you scroll, giving the impression that the entire body is darkened.
Example: http://jsbin.com/okabo3/edit
div.fadeMe {
opacity: 0.5;
background: #000;
width: 100%;
height: 100%;
z-index: 10;
top: 0;
left: 0;
position: fixed;
}
<body>
<div class="fadeMe"></div>
<p>A bunch of content here...</p>
</body>
body:before {
content: " ";
width: 100%;
height: 100%;
position: fixed;
z-index: -1;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.5);
}
First of all, I think you've misunderstood what the viewport is. The viewport is the area a browser uses to render web pages, and you cannot in any way build your web sites to override this area in any way.
Secondly, it seems that the reason that your overlay-div won't cover the entire viewport is because you have to remove all margins on BODY and HTML.
Try adding this at the top of your stylesheet - it resets all margins and paddings on all elements. Makes further development easier:
* { margin: 0; padding: 0; }
Edit:
I just understood your question better. Position: fixed; will probably work out for you, as Jonathan Sampson have written.
I had quite a bit of trouble as I didn't want to FIX the overlay in place as I wanted the info inside the overlay to be scrollable over the text. I used:
<html style="height=100%">
<body style="position:relative">
<div id="my-awesome-overlay"
style="position:absolute;
height:100%;
width:100%;
display: block">
[epic content here]
</div>
</body>
</html>
Of course the div in the middle needs some content and probably a transparent grey background but I'm sure you get the gist!
I looked at Nate Barr's answer above, which you seemed to like. It doesn't seem very different from the simpler
html {background-color: grey}