I am trying to produce this effect with CSS. I have tried creating a box with a triangle and then using negative margin to overlap it onto the circle, but cannot get it right.
Many thanks for any help.
fiddle
https://jsfiddle.net/Hastig/n3w0tztv/
Getting the circle to stay vertically centered and have the text container min-height the height of circle is tricky and is not worked out in this example. A cheap fix is adding align-items: center to .container at a breakpoint with #media.
body {
display: flex;
justify-content: center;
align-items: center;
margin: 0;
background-color: white;
height: 100vh;
}
.container {
display: flex;
width: 100%;
padding: 10px;
overflow: hidden;
}
.left {
position: relative;
display: flex;
width: 150px;
height: 150px;
margin-top: -4px;
margin-bottom: -4px;
margin-right: -17px;
background-color: #ec847c;;
border-style: solid;
border-color: white;
border-width: 4px;
border-radius: 100%;
z-index: 10;
}
.right {
position: relative;
display: flex;
flex: 2;
font-size: 20px;
color: white;
background-color: #4ca132;
}
.square {
position: absolute;
left: 0;
width: 50px;
height: 50px;
background-color: white;
overflow: hidden;
}
.square-top { top: 0; }
.square-btm { bottom: 0; }
.square::before {
content: "";
position: absolute;
display: flex;
width: 100%;
height: 100%;
transform: rotate(45deg) scale(2);
background-color: #4ca132;
z-index: 1;
}
.square-top::before { top: 50%; left: 50%; }
.square-btm::before { bottom: 50%; left: 50%; }
.text {
position: relative;
z-index: 2;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
padding: 20px 20px 20px 40px;
}
<div class="container">
<div class="left">
</div>
<div class="right">
<div class="square square-top"></div>
<div class="square square-btm"></div>
<div class="text">
Roles play an extremely important part in family funtion.
</div>
</div>
</div>
Related
I'm looking for an alternative to this css code, which is working as expected on chrome, but not on firefox.
The pins are not keeping their position when the viewport size is different. You can resize (height and width) the viewport on jsfiddle on chrome to see what I expect and on firefox to see what I don't.
I guess there is something between margin: auto and object-fit: contain which is not calculated the same way...
Chrome margin from devtools
Firefox margin from devtools
I know that I can do it in javascript but i'd like to know if it's possible with css !
<div class="site">
<div class="wrapper">
<div class="title">TITLE</div>
<div class="subtitle">Subtitle</div>
<div class="container">
<div class="img-wrapper">
<img src="./img.jpg" alt="">
</div>
<div class="pin-container">
<div class="pin pin1">?</div>
<div class="pin pin2">?</div>
<div class="pin pin3">?</div>
<div class="pin pin4">?</div>
</div>
</div>
</div>
</div>
.site{
position: relative;
width: 100%;
height: 80vh;
display: flex;
flex-direction: column;
margin: 0 auto;
max-width: 960px;
border: 1px solid blue;
}
.wrapper{
display: flex;
flex-direction: column;
}
.container{
position: relative;
border-radius: 6px;
margin: auto;
}
.img-wrapper{
height: 100%;
}
.img-wrapper img{
width: 100%;
height: 100%;
object-fit: contain;
}
.pin-container{
position: absolute;
color: red;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.pin{
position: absolute;
background-color: white;
width: 20px;
height: 20px;
border-radius: 50%;
text-align: center;
transform: translate(-50%, -50%);
}
.pin1 {
top: 50%;
left: 24%;
}
.pin2 {
top: 30%;
left: 52%;
}
.pin3 {
top: 87%;
left: 79%;
}
.pin4 {
top: 100%;
left: 100%;
}
https://jsfiddle.net/MathieuSP/8u3gLz4q/
Thank you ! :)
I think it's because of display: flex in the .wrapper.
The flex-box itself will always keep the content to fit inside so it will shrink your image down or scale it up.
You can use flex: 1 to keep the image from being change (you can read more about it here) and set the aspect-ratio to keep width and height of the image consistent. Just set it in the .container
.container {
position: relative;
border-radius: 6px;
margin: auto;
flex: 1;
aspect-ratio: 1.5;
}
Here is the snippet, hope this can help you
* {
margin: 0;
overflow: hidden;
box-sizing: border-box;
}
body{
height: 100vh;
width: 100vw;
color: white;
background-color: black;
}
.title{
text-align: center;
padding: 2rem 0;
font-size: 2rem;
}
.subtitle{
text-align: center;
padding: 1rem 0;
font-size: 1rem;
}
.site{
position: relative;
width: 100%;
height: 80vh;
display: flex;
flex-direction: column;
margin: 0 auto;
max-width: 960px;
border: 1px solid blue;
}
.wrapper{
display: flex;
flex-direction: column;
}
.container{
position: relative;
border-radius: 6px;
margin: auto;
flex: 1;
aspect-ratio: 1.5;
}
.img-wrapper{
height: 100%;
}
.img-wrapper img{
width: 100%;
height: 100%;
object-fit: contain;
}
.pin-container{
position: absolute;
color: red;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.pin{
position: absolute;
background-color: white;
width: 20px;
height: 20px;
border-radius: 50%;
text-align: center;
transform: translate(-50%, -50%);
}
.pin1 {
top: 50%;
left: 24%;
}
.pin2 {
top: 30%;
left: 52%;
}
.pin3 {
top: 87%;
left: 79%;
}
.pin4 {
top: 100%;
left: 100%;
}
<div class="site">
<div class="wrapper">
<div class="title">TITLE</div>
<div class="subtitle">Subtitle</div>
<div class="container">
<div class="img-wrapper">
<img src="https://images.pexels.com/photos/1534057/pexels-photo-1534057.jpeg" alt="">
<div class="pin-container">
<div class="pin pin1">?</div>
<div class="pin pin2">?</div>
<div class="pin pin3">?</div>
<div class="pin pin4">?</div>
</div>
</div>
</div>
</div>
</div>
They are moving because their container size changes bigger than the picture. For such positioning, always put the image and absolute elements in one container with fit-content width and height. and of course relative position If you do so, they will stay in the same spot.
* {
margin: 0;
overflow: hidden;
box-sizing: border-box;
}
body{
height: 100vh;
width: 100vw;
color: white;
background-color: black;
}
.title{
text-align: center;
padding: 2rem 0;
font-size: 2rem;
}
.subtitle{
text-align: center;
padding: 1rem 0;
font-size: 1rem;
}
.site{
position: relative;
width: 100%;
height: 80vh;
display: flex;
flex-direction: column;
margin: 0 auto;
max-width: 960px;
border: 1px solid blue;
}
.wrapper{
display: flex;
flex-direction: column;
}
.container{
position: relative;
border-radius: 6px;
margin: auto;
}
.img-wrapper{
height: 100%;
}
.img-wrapper img{
width: 100%;
height: 100%;
object-fit: contain;
}
.pin-container{
position: absolute;
color: red;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 1px solid red;
}
.pos-container {
border: 3px solid orange;
position: relative;
width: fit-content;
height: fit-content;
}
.pin{
position: absolute;
background-color: white;
color: red;
width: 20px;
height: 20px;
border-radius: 50%;
text-align: center;
transform: translate(-50%, -50%);
}
.pin1 {
top: 50%;
left: 24%;
}
.pin2 {
top: 30%;
left: 52%;
}
.pin3 {
top: 87%;
left: 79%;
}
.pin4 {
top: 100%;
left: 100%;
}
<body>
<div class="site">
<div class="wrapper">
<div class="title">TITLE</div>
<div class="subtitle">Subtitle</div>
<div class="container">
<div class="img-wrapper">
<div class="pos-container">
<img src="https://images.pexels.com/photos/1534057/pexels-photo-1534057.jpeg" alt="">
<div class="pin pin1">?</div>
<div class="pin pin2">?</div>
<div class="pin pin3">?</div>
<div class="pin pin4">?</div>
</div>
</div>
</div>
</div>
</div>
</body>
i have two divs, i want to put the child on top of the parent top, i was trying but the child div got stuck outside, what is the wrong?
.content {
align-items: center;
border-radius: 4px;
display: flex;
flex-direction: column;
height: 200px;
min-height: 140px;
min-width: 140px;
border: 1px solid;
}
.topcorner {
width: 42px;
height: 42px;
background: red;
position: absolute;
top: 0;
right: 0;
z-index: 1;
}
<div class="content">
<div class="topcorner">top</div>
</div>
Parent element needs to have position: relative.
Add position: relative to the parent class .content to make the child div inside the parent div.
.content {
align-items: center;
border-radius: 4px;
display: flex;
flex-direction: column;
height: 200px;
min-height: 140px;
min-width: 140px;
border: 1px solid;
position: relative; //Add this line
}
.topcorner {
width: 42px;
height: 42px;
background: red;
position: absolute;
top: 0;
right: 0;
z-index: 1;
}
<div class="content">
<div class="topcorner">top</div>
</div>
I want to make this layout with CSS:
The <video> (its aspect ratio and size may change) should be centered vertically and horizontally in the container with the black background (the size of the container may also change). The <button> should be centered in the remaining space on the right side of the <video>. If there is no space left for the button, it should overlay the <video>.
What I currently have is this:
div {
background-color: black;
position: relative;
resize: both;
overflow: hidden;
}
video {
display: block;
max-width: 100%;
max-height: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
video:focus {
outline: none;
}
button {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 16px;
width: 50px;
height: 50px;
border-radius: 50%;
background-color: red;
border: 5px solid white;
}
<div style="height: 200px; width: 700px;">
<video src="https://static.videezy.com/system/protected/files/000/019/696/pointing_blue.mp4" autoplay muted loop></video>
<button></button>
</div>
but I don't know how to center the button
Keywords:
Add elements (.button-spacer) on both sides of the video to claim the width needed for a button.
Center and space everything evenly using flex layout.
Use absolute positioning on the button to keep it on-screen even if there isn't enough room next to the video.
.player {
display: flex;
flex-flow: row nowrap;
justify-content: space-evenly;
background-color: black;
resize: both;
overflow: hidden;
}
video {
display: block;
max-width: 100%;
max-height: 100%;
align-self: center;
}
video:focus {
outline: none;
}
.button-spacer {
flex: 1 1 auto;
max-width: 50px;
position: relative;
display: flex;
align-items: center;
background: maroon;
}
button {
position: absolute;
right: 0;
width: 50px;
height: 50px;
background-color: red;
border-radius: 50%;
border: 5px solid white;
cursor: pointer;
}
<div class="player" style="height: 120px; width: 400px;">
<div class="button-spacer"></div>
<video src="https://static.videezy.com/system/protected/files/000/019/696/pointing_blue.mp4" autoplay muted loop></video>
<div class="button-spacer">
<button></button>
</div>
</div>
Flex (again) and a pseudo can help you without position :
div {
background-color: black;
position: relative;
resize: both;
overflow: hidden;
display: flex;
align-items: center;
justify-content: space-evenly;
}
video {
display: block;
max-width: 100%;
max-height: 100%;
margin: 0 -50px;
}
video:focus {
outline: none;
}
div:before {
content: '';
width: 50px;
margin: -100px;
}
button {
box-sizing: border-box;
width: 50px;
height: 50px;
border-radius: 50%;
background-color: red;
border: 5px solid white;
margin: -100px;
}
<div style="height: 200px; width: 700px;">
<video src="https://static.videezy.com/system/protected/files/000/019/696/pointing_blue.mp4" autoplay muted loop></video>
<button></button>
</div>
You can fix the problem by editing it from right: 16px; to right: 9%; in the button{} line 4.
I hope it fixes your problem
<style>
div {
background-color: black;
position: relative;
resize: both;
overflow: hidden;
}
video {
display: block;
max-width: 100%;
max-height: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
video:focus {
outline: none;
}
button {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 50%;
width: 50px;
height: 50px;
border-radius: 50%;
background-color: red;
border: 5px solid white;
}
</style>
<div style="height: 200px; width: 700px;">
<video src="https://static.videezy.com/system/protected/files/000/019/696/pointing_blue.mp4" autoplay muted loop></video>
<button></button>
</div>
I'm trying to implement a zoom in/out functionality, just like you would have on a document editor like google docs or any word processor application. The problem I'm having is that I cannot keep the "document" centered and also be able to scroll all of its parts into view. Here is a small demonstration of the problem: https://codepen.io/liviu_vasut/pen/dyGbwwO
document.getElementById('objectToScale').style.transform = "scale(3)";
.container {
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
width: 300px;
height: 200px;
border: 1px solid #000000;
left: 0px;
top: 0px;
margin: 10px;
overflow: auto;
}
.object {
position: relative;
width: 120px;
height: 120px;
display: inline-block;
background-color: grey;
border-radius: 25px;
padding: 5px;
transform-origin: center;
transform: scale(1);
}
<div class="container">
<div id="objectToScale" class="object">x</div>
</div>
Thanks for your time.
You scale only some inner element inside the whole box, but expect see the whole box scaled. if you want to scale the white padding and all the inner content to stay visible (and be able to scroll to) you should add some wrapper inside with width: 100% and height: 100%, and scale it, so the whole content become scaled.
Also, as #HaoWu mentioned, you should set the transform-origin to 0 0.
The final product should look somewhat like this:
var scaled = false;
function toggleScale() {
var objects = document.getElementsByClassName('wrapper');
for (var i = 0; i < objects.length; i++) {
objects[i].style.transform = scaled ? 'scale(1)' : 'scale(3)';
}
scaled = !scaled;
}
.container {
width: 300px;
height: 200px;
border: 1px solid #000000;
left: 0px;
top: 0px;
margin: 10px;
overflow: auto;
}
.wrapper {
width: 100%;
height: 100%;
display: flex;
box-sizing: border-box;
align-items: center;
justify-content: center;
padding: 5px;
transform-origin: 0 0;
}
.object {
position: relative;
width: 120px;
height: 120px;
display: inline-block;
background-color: grey;
border-radius: 25px;
padding: 5px;
transform-origin: center;
transform: scale(1);
}
<input type="button" onclick="toggleScale()" value="Toggle Scale" />
<div class="container">
<div class="wrapper">
<div id="objectToScale" class="object">x</div>
</div>
</div>
Actually, use the transform-origin: 0 0; and manually set the scrollbar to the center:
var scaled = false;
function toggleScale() {
[...document.getElementsByClassName('object')].forEach(e => {
e.classList.toggle('scaled');
e.parentElement.scrollTop = (e.parentElement.scrollHeight - e.parentElement.clientHeight) / 2;
e.parentElement.scrollLeft = (e.parentElement.scrollWidth - e.parentElement.clientWidth) / 2;
});
}
* {
box-sizing: border-box;
}
.container {
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
width: 300px;
height: 200px;
border: 1px solid #000000;
left: 0px;
top: 0px;
margin: 10px;
overflow: auto;
}
.object {
position: relative;
width: 120px;
height: 120px;
display: inline-block;
background-color: grey;
border-radius: 25px;
padding: 5px;
transform-origin: 0 0;
}
.scaled {
transform: scale(3);
}
<input type="button" onClick="toggleScale()" value="Toggle Scale" />
<div class="container">
<div class="object">cannot see the entire object when scaled</div>
</div>
Safari has full support for FlexBox according to caniuse.
I am simply trying to stack some differently sized div's on top of each other using flexbox. I am genuinely curious as to why this works in Chrome/Firefox but not in Safari:
<div class="container">
<div class="inner-one"></div>
<div class="inner-two"></div>
</div>
.container {
width: 15rem;
height: 15rem;
border-radius: 50%;
background-color: blue;
display: flex;
align-items: center;
justify-content: center;
}
.container div {
position: absolute;
}
.inner-one {
width: 13rem;
height: 13rem;
border-radius: 50%;
background-color: green;
}
.inner-two {
width: 11rem;
height: 11rem;
border-radius: 50%;
background-color: purple;
}
See JSFiddle here: https://jsfiddle.net/19n95exf/3/
Because position: absolute; break display: flex, use transform: translate instead
.container {
position: relative;
width: 15rem;
height: 15rem;
border-radius: 50%;
background-color: blue;
}
.container div {
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
.inner-one {
width: 13rem;
height: 13rem;
background-color: green;
}
.inner-two {
width: 11rem;
height: 11rem;
background-color: purple;
}
<div class="container">
<div class="inner-one"></div>
<div class="inner-two"></div>
</div>
Or give the inner elements a left/top value
.container {
width: 15rem;
height: 15rem;
border-radius: 50%;
background-color: blue;
display: flex;
align-items: center;
justify-content: center;
}
.container div {
border-radius: 50%;
position: absolute;
}
.inner-one {
left: 1.5rem;
top: 1.5rem;
width: 13rem;
height: 13rem;
background-color: green;
}
.inner-two {
left: 2.5rem;
top: 2.5rem;
width: 11rem;
height: 11rem;
background-color: purple;
}
<div class="container">
<div class="inner-one"></div>
<div class="inner-two"></div>
</div>