Reputation: 193
I have a page with a label directly above a textbox, and this is all centered vertically within the page. After the input is verified I would like to shrink the elements and slide them to the top of the page, while simultaneously "rotating" them to be next to one another, with the label on the left and the textbox on the right. So essentially I want to go from this in the middle of the screen and large:
Label
Textbox
to this at the top of the screen and back to a regular size:
Label: Textbox
I just can't seem to figure out the best way to handle it.
To be clear here, I'm wanting to animate this. To go from the top example to the bottom of the example in fluid motion.
Here is a fiddle of what I'm beginning with: http://jsfiddle.net/xpvt214o/280404/
Here is a fiddle of what I'm wanting to end with: http://jsfiddle.net/xpvt214o/280396/
The motion to get from fiddle 1 to fiddle 2 needs to be animated. That's what I'm struggling with.
Upvotes: 1
Views: 708
Reputation: 40708
Note: I have seen the result you wanted to achieve: smoothly translate the two elements from inline
to inline-block
. I've found a way to do this. As it is a completely different approach from my initial solution, I have decided to post another answer.
You can achieve the desired result with plain CSS but there are a couple of things to take care of.
we will position the main container .parent
with absolute
.parent {
position: absolute;
/* dimensions */
width: 35%
height: 20%;
/* centered horizontally */
margin: 0 auto;
left: 0;
right: 0;
/* centered vertically */
bottom: 0;
top: 45%;
}
to change the layout .parent
will get the class .parentMod
which will overwrite some of .parent
's initial properties:
.parentMod {
top: 10px;
height: 12%;
}
both sub elements are too positioned with absolute
their vertical position inside .parent
have to be set (with percentages to ensure the layout is responsive):
.parent > div:nth-child(1) {
left: calc(50% - 125px);
}
.parent > div:nth-child(2) {
left: calc(50% - 10px);
}
then we can set their position when the layout has changed:
both sub elements will have the same vertical position:
.parentMod > div:nth-child(1),
.parentMod > div:nth-child(2) {
top: 0px;
left: 0px;
right: 0px;
width: 100%;
}
the second sub element will have a vertical offset (it will be positioned below the first sub element):
.parentMod > div:nth-child(2) {
top: 35px;
}
Overall the result will look like:
const changeLayout = () => {
document.querySelector('.parent').classList.toggle('parentMod');
};
.parent {
position: absolute;
margin: 0 auto;
bottom: 0;
right: 0;
top: 45%;
left: 0;
width: 35%;
height: 20%;
font-size: 40px;
transition: all 2s ease;
}
.parent > div {
text-align: center;
width: 130px;
margin: 0px;
position: absolute;
top: 10px;
transition: all 2s;
}
.parent > div:nth-child(1) {
left: calc(50% - 125px);
}
.parent > div:nth-child(2) {
left: calc(50% - 10px);
}
.parentMod {
top: 10px;
height: 12%;
}
.parentMod > div:nth-child(1),
.parentMod > div:nth-child(2) {
top: 0px;
left: 0px;
right: 0px;
width: 100%;
}
.parentMod > div:nth-child(2) {
top: 35px;
}
<div class="parent">
<div>Label</div>
<div>Textbox</div>
</div>
<button onclick="changeLayout()">Switch Layout</button>
Upvotes: 1
Reputation: 21
You can try positioning them absolutely and using flex-box on the parent to center-align them.
It's not a very flexible solution, but it gets the job done!
HTML
<div class="container">
<span id="one">Label</span>
<span id="two">Textbox</span>
</div>
CSS
.container {
position: relative;
width: 200px;
height:200px;
display: flex;
flex-flow: column;
align-items: center;
}
#one, #two {
font-size: 1em;
display: block;
height:1em;
text-align: center;
margin: 0;
transition: all 500ms ease;
}
#one {
position: absolute;
}
#two {
position:absolute;
margin-top:1em;
}
.container:hover #one,
.container:hover #two {
font-size: .75em
}
.container:hover #one{
margin-left: -10px;
}
.container:hover #two{
margin-top: 0;
margin-left:30px
}
Upvotes: 0
Reputation: 40708
You can use vertical-align: middle
and text-align: center
to vertically and horizontally center your content. In the example: .parent1
To have both div
next to each other on the same horizontal level use display: inline-block
. In the example: .parent2
.parent1, .parent2 {
vertical-align: middle;
text-align: center;
}
.parent1 {
font-size: 30px;
}
.parent2 {
font-size: 20px;
}
.parent2 > div {
display: inline-block;
}
.parent2 > div:nth-child(2):before {
content: ': ';
}
<div class="parent1">
<div>Label</div>
<div>Textbox</div>
</div>
<br /><hr />
<div class="parent2">
<div>Label</div>
<div>Textbox</div>
</div>
Bonus if you wish to animate it:
You will need transition
to set the animation type and duration. Then prepare two CSS classes:
a default one called .parent
positionning the item in the center of the screen
.parent {
position: absolute;
left: 25%;
top: calc(50% - 47px);
width: 50%;
vertical-align: middle;
text-align: center;
font-size: 40px;
transition: all 0.5s ease;
}
another one that will be toggled and which overwriting the position of the element to the top of the screen.
.parentMod {
top: 0px;
}
I have added an event listener attached to the button so you can see the animation by toggling the state with a mouse click:
const changeLayout = () => {
document.querySelector('.parent').classList.toggle('parentMod');
};
.container {
height: 200px;
}
.parent {
position: absolute;
left: 25%;
top: calc(50% - 47px);
width: 50%;
vertical-align: middle;
text-align: center;
font-size: 40px;
transition: all 0.5s ease;
}
.parentMod>div {
font-size: 20px;
display: inline-block;
}
.parentMod {
top: 0px;
}
.parentMod>div:nth-child(2):before {
content: ': ';
}
<div class="parent">
<div>Label</div>
<div>Textbox</div>
</div>
<button onclick="changeLayout()">Switch Layout</button>
Upvotes: 2