I need to scale the middle div using transform scale(1.3). It works of course but the problem is that after scaling it overlaps neighbor divs. Is it possible to get rid of overlap using just CSS?
This is how it is now looks like:
But I want it this way
.main {
width: 100%;
height: 500px;
background-color: gray;
padding: 100px;
}
.box {
width: 100px;
height: 100px;
background-color: red;
margin: 2px;
display: inline-block;
border: 2px;
border-style: solid;
border-color: black;
}
.scaled-box {
width: 100px;
height: 100px;
-webkit-transform: scale(1.3);
-moz-transform: scale(1.3);
transform: scale(1.3);
display: inline-block;
background-color: green;
opacity: 0.7;
}
<div class="main">
<div class="box"></div>
<div class="scaled-box"></div>
<div class="box"></div>
</div>
.main {
width: 100%;
height: 500px;
background-color: gray;
padding: 100px;
--scale-rate:1.5; /* You can change scale from this line */
}
.box {
width: 100px;
height: 100px;
background-color: red;
display: inline-block;
border: 2px;
border-style: solid;
border-color: black;
}
.box:first-child{
margin-right: calc(((100px * var(--scale-rate)) - 100px) / 2); /* 100px is scaled-box width*/
}
.box:last-child{
margin-left: calc(((100px * var(--scale-rate)) - 100px) / 2); /* 100px is scaled-box width*/
}
.scaled-box {
width: 100px;
height: 100px;
-webkit-transform: scale(var(--scale-rate));
-moz-transform: scale(var(--scale-rate));
transform: scale(var(--scale-rate));
display: inline-block;
background-color: green;
opacity: 0.7;
}
<div class="main">
<div class="box"></div>
<div class="scaled-box"></div>
<div class="box"></div>
</div>
Edited:
margin-rate fixed
transform property does not reflects to the element width or height. Maybe you can use zoom instead. The downside is that Firefox does not support it: https://caniuse.com/?search=zoom
You can add a margin to the scaled box to prevent the overlap.
.scaled-box {
margin: 20px;
width: 100px;
height: 100px;
-webkit-transform: scale(1.3);
-moz-transform: scale(1.3);
transform: scale(1.3);
display: inline-block;
background-color: green;
opacity: 0.7;
}
In your preview, the divs are also aligned vertically which can't happen with a simple margin since they're inline. Use a flex in the main container to align them vertically.
.main {
display: flex;
align-items: center;
width: 100%;
height: 500px;
background-color: gray;
padding: 100px;
}
Related
I am learning React JS and also brushing up on some CSS styling. I have a small app that is basically a drum machine that I wanted to style to look as a launchpad using 3D transformations and CSS. The algorithm itself works, so I made the body of the launchpad, but I also wanted to make 3D buttons for it which would visually sink in when interacted with (either on click or key down). But I can't figure out how to make the buttons into cuboids that go on top of the main cuboid (the drumpad). They just remain flat in the top plane of the launchpad cuboid.
Codesandbox
Relevant JSX code:
The launchpad itself:
return (
<div className="drum-container">
<div className="drum-body">
<div id="drum-machine" className="side top">
<div className="drum-header">
<span>Beat Pro X</span>
<span>{clipName}</span>
</div>
<div id="display">
{keys.map((element, index) => {
return (
<Drumpad
key={element}
clip={clips[index]}
pressKey={element}
onClick={handleDrumpadClick}
onKeyDown={handleDrumpadClick}
/>
);
})}
</div>
</div>
<div className="side bottom"></div>
<div className="side left"></div>
<div className="side right"></div>
<div className="side front"></div>
<div className="side back"></div>
</div>
</div>
);
The Drumpad element:
return (
<div className="drumpad-button">
<div
ref={drumpadRef}
id={props.clip.name}
className="dpad-side dpad-top"
onClick={playAudio}
>
<span className="drum-pad-key">{props.pressKey}</span>
<audio ref={audioRef} className="clip" src={props.clip.source} />
</div>
<div className="dpad-side dpad-bottom"></div>
<div className="dpad-side dpad-left"></div>
<div className="dpad-side dpad-right"></div>
<div className="dpad-side dpad-front"></div>
<div className="dpad-side dpad-back"></div>
</div>
);
CSS:
* {
box-sizing: border-box;
}
body,
html {
margin: 0;
padding: 0;
background-color: darkgrey;
}
#root {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100vh;
}
.drum-container {
display: flex;
justify-content: center;
align-items: center;
border: 2px solid white;
border-radius: 4px;
height: 100%;
width: 100%;
perspective: 1500px;
perspective-origin: center;
}
.drum-body {
padding: 0;
margin: 0;
position: relative;
height: 700px;
width: 700px;
transform-style: preserve-3d;
transform: rotateX(-50deg);
}
.side {
border-radius: 15px;
position: absolute;
opacity: 0.9;
border: 2px solid white;
}
.front {
left: 100px;
top: 300px;
height: 100px;
width: 500px;
background-color: #d50000;
transform: translateZ(350px);
}
.back {
left: 100px;
top: 300px;
height: 100px;
width: 500px;
background-color: #aa00ff;
transform: translateZ(-350px);
}
.left {
top: 300px;
height: 100px;
width: 700px;
background-color: #304ffe;
transform: rotateY(90deg) translateZ(250px);
}
.right {
top: 300px;
height: 100px;
width: 700px;
background-color: #0091ea;
transform: rotateY(-90deg) translateZ(250px);
}
.top {
left: 100px;
height: 700px;
width: 500px;
background-color: #00bfa5;
transform: rotateX(90deg) translateZ(50px);
}
.bottom {
left: 100px;
height: 700px;
width: 500px;
background-color: #64dd17;
transform: rotateX(-90deg) translateZ(50px);
}
#display {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
row-gap: 20px;
column-gap: 20px;
padding: 0;
border: 0;
width: 80%;
margin: 200px auto 100px auto;
}
.drumpad-button {
border: 2px solid black;
position: relative;
padding: 0;
height: 120px;
width: 120px;
transform-style: preserve-3d;
transform: rotateX(30deg);
}
.dpad-side {
border-radius: 2px;
position: relative;
opacity: 0.9;
border: 2px solid white;
}
.dpad-front {
height: 20px;
width: 120px;
background-color: #d50000;
transform: translateZ(60px);
}
.dpad-back {
height: 20px;
width: 120px;
background-color: #aa00ff;
transform: translateZ(-60px);
}
.dpad-left {
height: 20px;
width: 120px;
background-color: #304ffe;
transform: rotateY(90deg) translateZ(60px);
}
.dpad-right {
height: 20px;
width: 120px;
background-color: #0091ea;
transform: rotateY(-90deg) translateZ(60px);
}
.dpad-top {
height: 120px;
width: 120px;
background-color: darkgreen;
transform: rotateX(90deg) translateZ(10px);
}
.dpad-bottom {
height: 120px;
width: 120px;
background-color: #64dd17;
transform: rotateX(-90deg) translateZ(10px);
}
Drumpads are in a grid, so I've tried setting the grid as the basis for the transform-style: preserve-3d, thinking that the grid elements as its children would then treat the top face of the launchpad as the base plane, but maybe there's something else I am doing wrong?
But from my understanding preserve-3d should be set on the element containing the elements that make up the figure in 3D space. When I change translateZ values I can see different planes popping up, but for some reason preserve-3d is ignored. Is it because of the grid? Or maybe specifics of the JSX nesting of imported components?
Im having a problem with a :before element (a left pointing triangle) getting a small line through the middle of it when I transform: scale on :hover I'm not sure what is causing this.. I have seen the same effect on other websites and it doesn't happen.
Any help would be appreciated
.container{
display: flex;
height: 45vw;
width: 100%;
background: black;
}
.image{
background: blue;
width: 50%;
height: 100%
}
.text{
background: yellow;
width: 50%;
height: 100%
}
.text:before{
content: '';
position: relative;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
top: 50%;
left: -17px;
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-right: 20px solid yellow;
}
.text:hover{
transform: scale(1.1);
transition: 0.4s;
}
<div class="container">
<div class="image">
</div>
<div class="text">
</div>
</div>
view on jsFiddle: https://jsfiddle.net/wap184pe/1/
This workaround essentially makes a triangle twice the size of the triangle you have and hides half of it, so the thin border is not visible. Check out this related issue with rendering triangles as borders in Firefox.
.container{
display: flex;
height: 45vw;
width: 100%;
background: black;
}
.image{
background: blue;
width: 50%;
height: 100%
}
.text{
background: yellow;
width: 50%;
height: 100%
}
.text:before{
content: '';
position: relative;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
top: 35%;
height: 0;
width: 0;
border: 36px solid transparent;
border-right: 0;
border-top-color: yellow;
transform: rotate(225deg);
}
.text:hover{
transform: scale(1.1);
transition: 0.4s;
}
<div class="container">
<div class="image">
</div>
<div class="text">
</div>
</div>
If you use the arrow at generator at http://www.cssarrowplease.com, you can save yourself the trouble
I'm having some CSS issues I hope someone here can help with. I basically am trying to set a group of inline divs that slide out to the right, expanding to the width of the parent div containing them. As you can see from the jsfiddle I have (https://jsfiddle.net/0o9bw101/), the divs expand to the width of the parent div, instead of expanding only to the rightmost border of the parent div. If anyone can help I'd be quite thankful. Thank you in advance!
Here is the CSS I'm using in case you want to see it here:
.container {
width: 70%;
height: 100px;
background-color: black;
}
.greyDiv {
height: 60px;
width: 60px;
background-color: white;
border-radius: 5px;
color: white;
display: inline-block;
margin: 20px;
vertical-align: top;
color: black;
}
.greyDiv:hover {
transition: 2s;
width: 70%;
position: absolute
}
Try this
.container {
width: 70%;
height: 100px;
background-color: black;
position:relative;
overflow:hidden;
}
.greyDiv {
height: 60px;
width: 60px;
background-color: white;
border-radius: 5px;
color: white;
display: inline-block;
margin: 20px;
vertical-align: top;
}
.greyDiv:hover {
transition: 2s;
width: 100%;
position: absolute;
}
<div class='container'>
<div class='greyDiv'></div>
<div class='greyDiv'></div>
<div class='greyDiv'></div>
<div class='greyDiv'></div>
</div>
EDIT:
The trick is to add another box inside main container.
DEMO: https://jsfiddle.net/0o9bw101/3/
<div class='container'>
<div class='invisible_container'>
<div class='greyDiv'></div>
<div class='greyDiv'></div>
<div class='greyDiv'></div>
<div class='greyDiv'></div>
</div>
</div>
previous answer:
It's hard to do when you mix parent's with in % with children margins in px.
Also having parent's position set to something other than default helps a bit.
Here is working example for you:
.container {
width: 70%;
height: 100px;
background-color: black;
position: absolute;
}
.greyDiv {
height: 60px;
width: 60px;
background-color: white;
border-radius: 5px;
color: white;
display: inline-block;
margin: 20px;
margin-left: 2%;
vertical-align: top;
}
.greyDiv:hover {
transition: 2s;
width: 96%;
position: absolute
}
DEMO: https://jsfiddle.net/0o9bw101/2/
This might not be quite what you were going for, but here elements will grow to the full width of the container (left to right) regardless of it's starting position using 2 extra elements per object.
The .inner is used to grow the background to the full width
The .placeholder is used to keep the other elements from collapsing left
#keyframes grow {
from {width: 0%;}
to {width: 92%;}
}
.container {
width: 70%;
height: 100px;
position: relative;
background-color: black;
}
.greyDiv {
height: 60px;
width: 60px;
background-color: white;
border-radius: 5px;
color: black;
display: inline-block;
margin: 20px 4%;
vertical-align: top;
position: relative;
z-index: 2;
}
.inner {
width: 0%;
height: 100%;
display: none;
background-color: transparent;
position: absolute;
left: 0;
top: 0;
z-index: 1;
}
.placeholder {
display: none;
background-color: transparent;
height: 60px;
width: 60px;
margin: 20px 4%;
}
.greyDiv:hover {
width: 100%;
position: absolute;
left: 0;
margin: 20px 0;
background-color: transparent;
z-index: 4;
}
.greyDiv:hover + .placeholder {
display: inline-block;
}
.greyDiv:hover .inner {
display: inline-block;
left: 4%;
width: 100%;
background-color: white;
animation-name: grow;
animation-duration: 2s;
animation-fill-mode: forwards;
z-index: 5;
}
<div class='container'>
<div class='greyDiv'>1a<div class="inner">1x</div></div><div class="placeholder"></div>
<div class='greyDiv'>2a<div class="inner">2x</div></div><div class="placeholder"></div>
<div class='greyDiv'>3a<div class="inner">3x</div></div><div class="placeholder"></div>
<div class='greyDiv'>4a<div class="inner">4x</div></div><div class="placeholder"></div>
</div>
Alright so I was attemping to make these 4 divs inside a div be centered on the screen (both horizonally and vertically) but they are stuck to the upper edge of the <div>. Their position is not going down or anything, they are constantly on top.
/* Footer */
#footer {
width: 100%;
height: 400px;
background-color: red;
opacity: 0.5;
text-align: center;
font-size: 20px;
letter-spacing: 35px;
white-space: nowrap;
line-height: 12px;
overflow: hidden;
}
.arrange {
width: 20%;
height: 80%;
border: solid 1px black;
display: inline-block;
vertical-align: middle;
background-color: white;
}
<div id="footer">
<div class="arrange"> </div>
<div class="arrange"> </div>
<div class="arrange"> </div>
<div class="arrange"> </div>
</div>
you can try this. add this to your code.
display:flex;
justify-content:space-around;
align-items:center;
if you want your boxes to be side by side, change space-around with center.
vertical-align: middle doesn't work for your case, use instead these 3 lines of css for .arrange
position: relative;
top: 50%;
transform: translateY(-50%);
So your final css will be:
#footer {
width: 100%;
height: 400px;
background-color: red;
opacity: 0.5;
text-align: center;
font-size: 20px;
letter-spacing: 35px;
white-space: nowrap;
line-height: 12px;
overflow: hidden;
}
.arrange {
width: 20%;
height: 80%;
border: solid 1px black;
display: inline-block;
position: relative;
top: 50%;
-webkit-transform: rotate(7deg); /* Chrome, Safari, Opera */
-ms-transform: rotate(7deg); /* IE 9 */
transform: translateY(-50%);
background-color: white;
}
just add 'padding top' to #footer and 'vertical-align' is no longer needed
<div id="footer">
<div class="arrange"></div>
<div class="arrange"></div>
<div class="arrange"></div>
<div class="arrange"></div>
</div>
<style>
#footer {
padding-top: 90px;
width: 100%;
height: 400px;
background-color: red;
opacity: 0.5;
text-align: center;
font-size: 20px;
letter-spacing: 35px;
white-space: nowrap;
line-height: 12px;
overflow: hidden;
}
.arrange {
width: 20%;
height: 80%;
border: solid 1px black;
display: inline-block;
background-color: white;
}
</style>
I did up a fiddle with some annotations to show you one method of doing what I think you're wanting to do.
* {
box-sizing: border-box; /* percentage calculations wont include border width and padding, but margin still messes with it, see calc below */
}
body {
width: 100vw;
}
#footer {
width: 100%;
height: 400px;
padding: 40px 5px; /* i added this top padding based on your wanting children to be 80% of parents height. 40 top, 40 bottom */
background-color: red;
opacity: 0.5;
text-align: center;
line-height: 12px;
overflow: hidden;
font-size: 0; /* eliminate ghost spaceing after inline blocks */
}
.arrange {
display: inline-block;
width: calc(25% - 10px); /* width% - margin */
height: 100%; /* 100% of parent minus padding of parent */
margin: 0px 5px; /* spacing, margin accounted for in calc of width, 5left + 5right = 10 */
font-size: 20px; /* reset font size */
border: solid 1px black;
background-color: white;
vertical-align: top;
}
<div id="footer">
<div class="arrange"></div>
<div class="arrange"></div>
<div class="arrange"></div>
<div class="arrange"></div>
</div>
fiddle
https://jsfiddle.net/Hastig/ypfcb2nb/1/
Below is the snippet:
.out {
margin: 100px auto;
width: 50%;
height: 100px;
background-color: green;
}
.in {
width: 50%;
height: 50px;
background-color: red;
transform: translate3d(-20%, -40%, 0px) scale(0.7);
position: absolute;
}
<div class="out">
<div class="in">
</div>
</div>
As can be seen, the inner element (red square) goes out of the border/bound of the outer element (green square).
Does anyone have ideas about how to clip the part of inner element which goes out of the border of the outer element?
--
I find overflow: hidden doesn't work well because of the position: absolute property in the inner element..
Add overflow:hidden on the outer element:
.out {
overflow:hidden;
margin: 100px auto;
width: 50%;
height: 100px;
background-color: green;
}
.in {
width: 50%;
height: 50px;
background-color: red;
transform: translate3d(-20%, -40%, 0px) scale(0.7);
}
<div class="out">
<div class="in">
</div>
</div>
you can try this one:
.out {
margin: 100px auto;
width: 50%;
height: 100px;
background-color: green;
overflow:hidden;
}
.in {
width: 50%;
height: 50px;
background-color: red;
transform: translate3d(-20%, -40%, 0px) scale(0.7);
}
DEMO