Chrome / Firefox inconsistent when parent is positioned with absolute - css

I have a map with rounded icons on it.
I'm using empty canvas elements to preserve 1:1 aspect ratio on rounded containers
When viewing in Chrome 67 everything is fine, but with Firefox 60 it does not work, aspect ratio is not preserved and icons have a content width of zero (only their padding make them visible)
It happens if parent (.zone) has position:absolute, however it work when .zone has position:relative.
I really need position:absolute, does somebody know why firefox does not expand width of .item to adjust to the canvas element ?
* {
margin: 0;
box-sizing: 0;
}
.zone {
position: absolute;
left: 5%;
right: 5%;
top: 5%;
bottom: 5%;
background: grey;
}
.item {
position: absolute;
transform: translate(-50%, -50%);
height: calc(100% / 11);
border-radius: 50%;
z-index: 3;
overflow: hidden;
cursor: help;
border: 1.5px solid #0acaff;
color: #0acaff;
}
.item canvas {
height: 100%;
}
.square_content {
background: red;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
align-items: center;
padding: 5px;
}
<div class="zone">
<!-- inline style is computed -->
<div class="item" style="left: 22.727%;top: 77.273%;">
<canvas width="1" height="1"></canvas>
<div class="square_content">
</div>
</div>
</div>
Note: on the snippet you should see mostly a gray zone with a perfectly rounded icon (blue border and red background)

The issue is with height: calc(100% / 11); it's value is not picking up in Firefox, if you change the % to vw your code will work fine.
A sample code for you:
* {
margin: 0;
box-sizing: 0;
}
.zone {
position: absolute;
left: 5%;
right: 5%;
top: 5%;
bottom: 5%;
background: grey;
}
.item {
position: absolute;
transform: translate(-50%, -50%);
height: 4vw;
/* or height: calc(40vw/11); */
border-radius: 50%;
z-index: 3;
overflow: hidden;
cursor: help;
border: 1.5px solid #0acaff;
color: #0acaff;
}
.item canvas {
height: 100%;
}
.square_content {
background: red;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
align-items: center;
padding: 5px;
}
<div class="zone">
<!-- inline style is computed -->
<div class="item" style="left: 22.727%;top: 77.273%;">
<canvas width="1" height="1"></canvas>
<div class="square_content">
</div>
</div>
</div>
The above sample work will all browsers, Hope this was helpful for you.

Related

CSS preserve ratio of circle on top of image

I have an image and i want to put 2 circles on top of it, instead of the eyes.
body {
background-color: lightgrey;
color: #fff;
padding: 0;
margin: 0;
}
main {
display: grid;
place-items: center;
position: relative;
}
#container {
min-height: 100vw;
min-width: 100vw;
background: none;
aspect-ratio: 1 / 1;
}
.eye-container {
position: relative;
border-radius: 50%;
background-color: red;
width: 12vw;
height: 12vw;
}
.eye-container.left {
top: -84%;
left: 36%;
}
.eye-container.right {
top: -96%;
left: 51%;
}
.eye {
position: absolute;
bottom: 3px;
right: 2px;
display: block;
width: 3vw;
height: 3vw;
border-radius: 50%;
background-color: #000;
}
img {
max-width: 100%;
min-width: 100%;
}
<main>
<div id="container">
<img id="sponge" src="https://upload.wikimedia.org/wikipedia/en/thumb/3/3b/SpongeBob_SquarePants_character.svg/220px-SpongeBob_SquarePants_character.svg.png">
<div class="eye-container left">
<div class="eye"></div>
</div>
<div class="eye-container right">
<div class="eye"></div>
</div>
</div>
</main>
The current issue is the image is too big, it is stretched.
The initial problem was that the layout was not responsive on mobile, and i've did some changes and now the image is this big.
I've used aspect-ratio: 1 / 1; because top was not working with negative percentage, and with pixels the eyes location is changing if is shrink the window.
Do you have another suggestion, maybe a simplified code will be better.
Thank you.
I'm a noob developer and I felt like, this was a tiny engineering job "LOL" but I did it for you.
So the most important point in this is to keep the image and the eyes in the same position. and to do that, you should position them in a parent container for image and eyes considering four important factors:
1- Parent position: relative; All children position: absolute;
2- All children's width: %; so it can stay in the same spot in its parent whatever the width of the parent is.
3- Eyes and eyeballs positioning top, left, right must be % too for the same purpose.
4- To change the image size, use the parent width. do not change the image size.
If you follow these steps, you can position any element with any image or other element.
* {
border: 1px solid blue;
margin: 0;
padding: 0;
}
.container {
width: 200px; /* use this to change the picture size. do not change it somewhere else */
position: relative;
}
.image {
width: 100%;
}
.eye-container{
position: absolute;
border-radius: 50%;
background-color: red;
width: 12%;
height: 12%;
}
.left-eye {
top: 17%;
left: 36%;
}
.right-eye {
top: 17%;
left: 51%;
}
.eyeball {
position: absolute;
bottom: 3px;
right: 2px;
display: block;
width: 30%;
height: 30%;
border-radius: 50%;
background-color: #000;
}
<div class="container">
<img class="image" src="https://upload.wikimedia.org/wikipedia/en/thumb/3/3b/SpongeBob_SquarePants_character.svg/220px-SpongeBob_SquarePants_character.svg.png">
<div class="left-eye eye-container">
<div class="eyeball"></div>
</div>
<div class="right-eye eye-container">
<div class="eyeball"></div>
</div>
</div>

For a picture preview I need to put 2 div elements vertically in front of a picture

For a picture preview I want to put 2 invisble divs (red/blue in the picture) in front of a picture for next/previous image functionality.
I would like to have the div ("pictureContainer"/ green bordered zone) to automatically take over the dimension of the containing picture but I can't find a PURE CSS solution without setting the width and the height manually.
.container {
position: fixed;
width: 100%;
height: 100%;
border: 3px solid black;
}
.pictureContainer {
/* I don't want to set width and hight manuyally.
The container should have the size if the contained image. */
height: 50%;
width:300px;
position: relative;
margin: auto;
border: 3px solid green;
}
.leftSide {
background-color: blue;
float: left;
height: 100%;
width: 50%;
opacity: 80%;
}
.rightSide {
background-color: red;
float: right;
height: 100%;
width: 50%;
opacity: 80%;
}
.picture {
position: absolute;
top: 0;
left: 0;
margin: auto;
z-index: -1;
}
<div class="container">
<div class="pictureContainer">
<div class="leftSide"></div>
<img class="picture" src="https://www.9skips.com/wp-content/uploads/2018/01/anger-300x300.jpg">
<div class="rightSide"></div>
</div>
</div>
Also the container should be horizontally aligned.
Note: The full screen white div with the black border is used to close the picture preview.
You should change so the divs have absolut: position, let the image have it's natural size, container should be display: inline-block;
.container {
display: flex;
align-items: center;
justify-content: center;
position: fixed;
width: 100%;
height: 100%;
border: 3px solid black;
}
.pictureContainer {
position: relative;
display: inline-block;
margin: 0 auto;
border: 3px solid green;
}
.picture {
display: block;
}
.leftSide {
position: absolute;
top: 0;
bottom: 0;
left: 0;
background-color: blue;
width: 50%;
opacity: 80%;
z-index: 1;
}
.rightSide {
position: absolute;
top: 0;
bottom: 0;
right: 0;
background-color: red;
height: 100%;
width: 50%;
opacity: 80%;
z-index: 1;
}
<div class="container">
<div class="pictureContainer">
<div class="leftSide"></div>
<img class="picture" src="https://www.9skips.com/wp-content/uploads/2018/01/anger-300x300.jpg">
<div class="rightSide"></div>
</div>
</div>

Mix-blend-mode working when applied to one element but not another

I am using mix-blend-mode on css-generated content to create a multiplied background effect.
When I apply this generated element to an outer wrapper it has the intended effect:
.standard-cover {
background: blue;
color: #fff;
position: absolute;
top: 0;
left: 0;
width: 100%;
min-height: 100%;
display: flex;
}
.standard-cover:after {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 20;
content: "";
background: blue;
mix-blend-mode: multiply;
}
.image-wrap {
line-height: 0;
}
img {
object-fit: cover;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 10;
}
.content-wrap {
position: relative;
text-align:center;
z-index: 30;
min-height: 1em;
margin: auto;
padding: 3.33%;
}
<div class="standard-cover">
<div class="image-wrap">
<img src="http://placeimg.com/480/480/nature" alt="Nature">
</div>
<div class="content-wrap">
<div class="content">
<h2>A title</h2>
<p>A pagragraph</p>
</div>
</div>
</div>
When I apply it to an inner wrapper it does not:
.standard-cover {
position: absolute;
background: blue;
color: #fff;
top: 0;
left: 0;
width: 100%;
min-height: 100%;
display: flex;
}
.image-wrap {
line-height: 0;
}
img {
object-fit: cover;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 10;
}
.content-wrap {
position: relative;
text-align:center;
z-index: 30;
min-height: 1em;
margin: auto;
padding: 3.33%;
}
.content-wrap:after {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 20;
content: "";
background: blue;
mix-blend-mode: multiply;
}
.content {
position: relative;
z-index: 30;
}
<div class="standard-cover">
<div class="image-wrap">
<img src="http://placeimg.com/480/480/nature" alt="Nature">
</div>
<div class="content-wrap">
<div class="content">
<h2>A title</h2>
<p>A pagragraph</p>
</div>
</div>
</div>
In both cases the actual css that applies the faux background color is identical:
.class:after {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 20;
content: "";
background: blue;
mix-blend-mode: multiply;
}
But in the first example it in fact applies the mix-blend-mode effect properly. In the second example it does not (despite inspectors confirming that the mix-blend-mode attribute is present and set to multiply).
Is there some nuance to the mix-blend-mode spec that I'm not understanding? Or am I missing some crucial something in my code?
It's all about stacking context. In the first case, the pseudo element is applied to .standard-cover where there is the background so its a child element of it and mix-blend-mode will work correctly because both belong to the same stacking context. In the second case, you moved the pseudo element to .content-wrap and there is a z-index specified so now it belong to another stacking context and mix-blend-mode will no more have effect outside.
An easy solution is to remove the z-index from .content-wrap to avoid creating a stacking context and mix-blend-mode will work like intended:
.standard-cover {
position: absolute;
background: blue;
color: #fff;
top: 0;
left: 0;
width: 100%;
min-height: 100%;
display: flex;
}
.image-wrap {
line-height: 0;
}
img {
object-fit: cover;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 10;
}
.content-wrap {
position: relative;
text-align:center;
min-height: 1em;
margin: auto;
padding: 3.33%;
}
.content-wrap:after {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 20;
content: "";
background: blue;
mix-blend-mode: multiply;
}
.content {
position: relative;
z-index: 30;
}
<div class="standard-cover">
<div class="image-wrap">
<img src="http://placeimg.com/480/480/nature" alt="Nature">
</div>
<div class="content-wrap">
<div class="content">
<h2>A title</h2>
<p>A pagragraph</p>
</div>
</div>
</div>
Note: Applying a blendmode other than normal to the element must establish a new stacking context [CSS21]. This group must then be blended and composited with the stacking context that contains the element. ref
I achieved the same effect by applying the mix-blend-mode: difference !important; and filter: invert(1) !important; styles to the header element of my nav-bar, the nav-bar itself has a transparent background so it only finds of the difference of the child elements against the background.

How to manage content dimension?

I need to create a circle with an image inside, so far I almost achieved this but I want set the content dimension too, this is my code:
.circle {
position: absolute;
z-index: 10;
top: -25%;
left: 50%;
border: 5px solid #a7151f;
margin: 0;
padding: 0;
height: 100%;
line-height: 0;
text-align: center;
text-transform: uppercase;
transform: translateX(-50%);
background-color: #a7151f;
width: 500px;
height: 400px;
border-radius: 50%;
content: url("logo");
}
<img class="img-responsive center-block circle">
this is a fiddle.
As you can see I have to display only half of the circle, but the problem is that the logo is not entire visible. How can I manage this?
To fix this you needed to give the img a z-index greater than the circles and then center it ontop of the circle.
Here's the code:
.circle{
background-color: red;
position: absolute;
top: -250px;
left: 50%;
border: 5px solid #a7151f;
margin: 0;
padding: 0;
height: 100%;
line-height: 0;
text-align:center;
text-transform: uppercase;
transform: translateX(-50%);
background-color: #a7151f;
width: 500px;
height: 400px;
border-radius: 50%;
}
.img {
content: url("https://www.google.it/logos/doodles/2019/rugby-world-cup-2019-opening-day-6753651837108235-l.png");
z-index: 10;
position: absolute;
left: 50%;
transform : translateX(-50%);
}
<div class="circle">
</div>
<div class="img">
</div>
here is the jsfiddle fix: http://jsfiddle.net/t5L49f7g/
Hope this helps!

How to center a absolute div inside a fixed div

I have set up a modal for phots, so when i click on a small photo i get a larger photo up in a modal, the modal has position: fixed; and the modal-content has position: absolute; i can center it with margin: auto; left: 0; right: 0;but then the width goes all the way to the right and left, i want the modal content width to be the same as the photo inside it or the content of the modal-content
my code:
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding: 30px;
left: 0;
top: 0;
right: 0;
bottom: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
.modal-content {
background-color: #fefefe;
position: absolute;
top: 50px;
margin-bottom: 30px;
margin: auto;
border: 1px solid #888;
}
.modalimg {
position: relative;
text-align: center;
}
.modalimg img{
max-width: 100%;
max-height: 400px;
margin: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
position: relative;
box-shadow: 0 0 20px rgba(0,0,0,0.4);
}
its maybe a bit messy now but i have tried alot of different things with no luck..
This is what I use when I center an absolute-positioned element, this works for me all the time:
.absolute-center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
here you are please
.element {
position: absolute;
top: 15px;
z-index: 2;
width: 40%;
max-width: 960px;
min-width: 600px;
height: 60px;
overflow: hidden;
background: #fff;
margin: 0 auto;
left: 0;
right: 0;
background: red;
color: #fff;
text-align: center;
}
<div class="element">
text..
</div>
.modal-content {
background-color: #fefefe;
position: absolute;
top: 50px;
left: 50px;
right: 50px;
bottom: 50px;
border: 1px solid #888;
}
to align absolute div to center
left: 0;
right: 0
text-align: center
this will align the div in center.
Here's a possible solution that uses:
absolute positioning on the content container (.modal-content)
doesn't use absolute|fixed on the actual content
The content container (.modal-content) will grow along with its content. Finally, it's moved back to the middle using transform: translate(-50%, -50%);:
.modal {
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.4);
}
.modal-content {
border: 1px solid red;
position: absolute;
top: 50%;
left: 50%;
border: 2px solid red;
transform: translate(-50%, -50%);
}
<div class="modal">
<div class="modal-content">
<img src="//placehold.it/200x200" alt="">
</div>
</div>
Demo
Try before buy

Resources