Multiline container unfolding animation - html

How should CSS multiline container (e.g. content block or alert) unfolding animation should be managed?
http://plnkr.co/edit/Qq5fzeb3GBengviVNimC?p=preview
.alert {
background: turquoise;
color: white;
padding: 10px;
overflow: hidden;
opacity: 0;
max-height: 0;
}
body:hover .alert {
display: block !important;
opacity: 1;
-webkit-transition: 2s;
-moz-transition: 2s;
-ms-transition: 2s;
transition: 2s;
max-height: 100px;
}
The problem here is 'multiline', as you can see, the block height isn't a fixed value.
<div class="alert">Alert!<br>Alert!<br>Alert!</div>
While max-height: 100px is near real block height, it works fine. If max-height is smaller, the animation would be jaggy in the end, and max-height: 9999px will make the transition too fast.
Can this be done without calculating the exact height in JS?

Calculating the height can be done in jQuery indeed, I did the following to solve your problem:
$("#out").html("Block height: " + $("#alert").height());
//solely for demonstration, you can delete this line
$("#alert").css('height','0px');
$('#alert').mouseover( function(){
$("#alert").css('height', '58px');
});
$('#alert').mouseout( function(){
$("#alert").css('height', '0px');
});
#alert {
background: turquoise;
color: white;
padding: 10px;
overflow: hidden;
opacity: 0;
//max-height: 0; this causes .height() to always display '0' so delete this here, and set this via jQuery
}
body:hover #alert {
display: block !important;
opacity: 1;
-webkit-transition: 2s;
-moz-transition: 2s;
-ms-transition: 2s;
transition: 2s;
// max-height: 100px !important; set this via jQuery
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>Hello!</p>
<div id="alert">Alert!<br>Alert!<br>Alert!</div>
<p>Hello again!</p>
<span id="out"></span>

Related

Transition accordion: roll down works, but not roll back up

I am trying to make the accordion roll down, when selected, and roll back up when closed. It rolls down, but when closed it just closes without transition.
I tried adding max-height to the elements, and then using transition: max-height 1s ease-in/ease-out, but it doesn't work for rolling back up :(
I guess I am doing something wrong, but I am still new at web-development, so it's a bit hard to see my own mistakes :P
$('.topic-container').on('click', function() {
if ($(this).hasClass('active')) {
$(this).removeClass('active')
$(this).addClass('closed')
} else {
$(this).addClass('active')
$(this).removeClass('closed')
.siblings()
.removeClass('active')
.addClass('closed')
}
});
.accordion .content {
position: relative;
height: 0;
font-size: 20px;
text-align: justify;
width: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
max-height: 0;
transition: max-height 1s ease;
}
.accordion .topic-container.active .content {
height: 100%;
max-height: 1000px;
transition: max-height 1s ease-in;
}
.accordion .topic-container.closed .content {
height: 0;
max-height: 0;
transition: max-height 1s ease-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="accordion-body">
<div class="accordion">
<div class="topic-container closed">
<div class="label">
Header
</div>
<div class="content">
Inside the accordion tab
</div>
</div>
</div>
</div>
Instead of using max-height 1s ease-out you have to use max-height 1s, height 1s ease-out for transition property
.accordion .topic-container.active .content {
height: 100%;
max-height: 1000px;
transition: max-height 1s, height 1s ease-in;
}
.accordion .topic-container.closed .content {
height: 0;
max-height: 0;
transition: max-height 1s, height 1s ease-out;
}

weird color stain from css

I've coded it in css where if you hover over a div it expands and show more details about the div, the issue is that whenever I remove the mouse some of the color is still left as lines, I'll attach a picture.
This is the css code where movie card is the details and movie is the div to hover on
.movie-card{
transition: 500ms ease-in-out;
background-color: #a851ff;
opacity: 0;
visibility: hidden;
border: 1px solid #a851ff;
}
.movie-box-content:hover .movie-card{
transition-delay: 250ms;
transition-duration: 500ms;
visibility: visible;
opacity: 1;
}
This is the result of hovering over:
And this is after removing the mouse over it:
its worth noting that after I scroll once, all the lines get removed.
Removing the transition: 500ms ease-in-out; from the movie-card class gets rid of the spurious 'shadows'.
.movie-box {
position: relative;
display: block;
width: 300px;
height: 168.75px;
}
.movie-box-content {
transform: scale(1);
transition: 500ms ease-in-out;
background-image: url('https://wallpaperaccess.com/full/1508305.jpg');
background-repeat: no-repeat;
background-size: 300px 168.75px;
width: 100%;
height: 100%;
rborder-radius: 2%;
}
.movie-box-content:hover {
transition-delay: 250ms;
transition-duration: 500ms;
transform: scale(1.3);
border: 1px solid #a851ff;
box-shadow: #a851ff;
}
.movie-card {
/* transition: 500ms ease-in-out;*/
background-color: #a851ff;
opacity: 0;
visibility: hidden;
}
.movie-box-content:hover .movie-card {
transition-delay: 250ms;
transition-duration: 500ms;
visibility: visible;
opacity: 1;
}
<div class="movie-box">
<div class="movie-box-content">
<div style="width: 100%; height: 100%;"></div>
<div class="movie-card hidden">
<div class="text-center">
<strong>Drama, psycho, crime</strong>
</div>
</div>
</div>
</div>
There is the question of whether this alters anything else visually.
Incidentally, changing scale(1.2) to scale(i) where i is an integer also seemed to remove the problem which perhaps indicates difficulty with mapping CSS pixels (which can take up several display pixels each) so that as the div scales down it 'leaves behind' parts of the CSS pixel. It would be good if someone could explain this phenomenon.
I don't think it's necessary to have both visibility and opacity change as they essentially achieve the same thing. As you have a general transition set on the class, perhaps the two are interfering with each other.

Move div according to other div's height

I have two divs and I want to move both of them at the same time: one to left and other to up.
I did that using the transfom CSS property and I set the translateX and translateY in pixels.
How can I do the same effect when I don't know the height of first div? It's addaptive according to its content.
My real project uses Angular and I want to avoid using pure JQuery (a pure CSS solution will be great!).
EDIT:
I use the class above to animate my second div:
.to-up {
transition-delay: .2s;
transform: translateY(-127px);
}
I came to that value of 127px through this calculation:
div1 height + div1 margin-bottom + div1 borders.
In my real case, the div1 height is addaptive to its content so I don't know how to animate div2 to the top of its parent. How can I do that?
Here's my HTML:
<div class="container">
<div id="item1" class="item">Test1</div>
<div id="item2" class="item">Test2</div>
</div>
My CSS:
.container {
width: 100%;
}
#item1 {
height: 120px;
}
#item2 {
height: 80px;
}
.item {
width: 100px;
border: 1px solid black;
margin: 5px;
transition: all .3s ease-in-out;
-webkit-transition: all .3s ease-in-out;
-moz-transition: all .3s ease-in-out;
-ms-transition: all .3s ease-in-out;
-o-transition: all .3s ease-in-out;
}
.to-right {
transform: translateX(-107%);
}
.to-up {
transition-delay: .2s;
transform: translateY(-127px);
}
And JQuery:
$('.item').on('click', function() {
$('#item1').toggleClass('to-right');
$('#item2').toggleClass('to-up');
});
Finally there's the code working with pixels on Jsfiddle.
Thanks a lot!
This is the better solution that you can do, with Angular in template (don't forget the "goOn" variable initialization in the component):
<div class="container">
<div id="item1" class="item" [class.to-right]="goOn" (click)="goOn = !goOn">Test1</div>
<div id="item2" class="item" [class.to-up]="goOn" (click)="goOn = !goOn">Test2</div>
</div>
Here a working example: https://stackblitz.com/edit/angular-animation-on-click?file=src/app/app.component.html
I think you can't do it without angular (or js) because we're talking about "click" event.
I'm not understanding about what do you want to do without knowing the box heights. Where do you want to move them? I think that without knowing its solution you can't do it.
Problem fixed.
Instead using translateY property to move the second div I used animation with animation-timing-function as linear and animation-fill-mode as forwards.
What did I changed?
Container element now has relative position.
An animation called top was created (set top to 0 on 100%).
The class .move-up changes element position to absolute and call the top animation.
I set .move-up class to the second div on click.
Here's a working poc on Jsfiddle.
HTML:
<div class="container">
<div id="item1" class="item">Test1</div>
<div id="item2" class="item">Test2</div>
</div>
JQuery:
$('.item').on('click', function() {
$('#item1').toggleClass('to-right');
$('#item2').toggleClass('to-top');
});
CSS:
.container {
width: 100%;
position: relative;
}
#item1 {
height: 120px;
}
#item2 {
height: 80px;
margin-top: 0px;
}
.item {
width: 100px;
border: 1px solid black;
margin: 5px;
transition: all .3s ease-in-out;
-webkit-transition: all .3s ease-in-out;
-moz-transition: all .3s ease-in-out;
-ms-transition: all .3s ease-in-out;
-o-transition: all .3s ease-in-out;
}
.to-right {
transform: translateX(-107%);
}
.to-top {
position: absolute;
animation-name: top;
animation-duration: .3s;
animation-delay: .2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
}
#keyframes top {
0% {
top: 100%;
}
100% {
top: 0;
}
}

CSS min-height not resizing based on content

I am currently trying to make content appear when a label is selected. The issue which I am having is that the content which will appear will vary in size based on the data which is being pulled in so I cannot set a specific height which will work in all cases. I thought the best way to work around this was to use min-height but the height doesn't seem to be betting itself based on the length of the size of the content. How can I fix this o that the size will be based on how much content there is.
#block {
background: yellow;
height: 0;
overflow: hidden;
-webkit-transition: height 300ms linear;
-moz-transition: height 300ms linear;
-o-transition: height 300ms linear;
transition: height 300ms linear;
}
label {
cursor: pointer;
}
#showContent {
display: none;
}
#showContent:checked+#block {
min-height: 5px;
}
#showContent:not(:checked) {
height: 0px;
}
<label for="showContent">Show content</label>
<input type="checkbox" id="showContent" />
<div id="block">
Show content ..... Bla bla bla
</div>
jsfiddle
https://jsfiddle.net/sacora9/81m14v1s/14/
Just set the height to auto. Otherwise, you set min-height:5px, but the height is still set to 0, so the calculated height will be 5px. So the solution is to release the height and make it free :
#block {
background: yellow;
height: 0;
overflow: hidden;
-webkit-transition: height 300ms linear;
-moz-transition: height 300ms linear;
-o-transition: height 300ms linear;
transition: height 300ms linear;
}
label {
cursor: pointer;
}
#showContent {
display: none;
}
#showContent:checked+#block {
height : auto; /* <----- Here, instead of min-height: 5px */
}
#showContent:not(:checked) {
height: 0px;
}
<label for="showContent">Show content</label>
<input type="checkbox" id="showContent" />
<div id="block">
Show content ..... Bla bla bla
</div>
EDIT
I've just noticed the animation part. Transition from 0 to auto is tricky, but here's the trick :
#block {
background: yellow;
overflow: hidden;
max-height: 0;
transition: max-height 0.3s cubic-bezier(0,1,0,1);
}
label {
cursor: pointer;
}
#showContent {
display: none;
}
#showContent:checked+#block {
max-height: 1000px;
transition: max-height 0.3s cubic-bezier(1,0,1,0);
}
#showContent:not(:checked) {
height: 0px;
}
<label for="showContent">Show content</label>
<input type="checkbox" id="showContent" />
<div id="block">
Show content ..... Bla bla bla
</div>
On your example, block still has height: 0; applied to it even when showContent is checked. Instead, set the height to auto.
One way to do this while maintaining the animation would be to use max-height instead:
#block {
background: yellow;
max-height: 0px;
overflow: hidden;
-webkit-transition: max-height 300ms linear;
-moz-transition: max-height 300ms linear;
-o-transition: max-height 300ms linear;
transition: max-height 300ms linear;
}
label {
cursor: pointer;
}
#showContent {
display: none;
}
#showContent:checked + #block {
max-height: 100px; /*any value larger than the content */
}
#showContent:not(:checked){
height:0px;
}

Split content of a div into 2 divisions

I was trying to implement splitting of entire content to create a slideshow. Something similar to this.
http://tympanus.net/Tutorials/FullscreenSlitSlider/
The problem is splitting of divisions equally. I just don't want them to appear to be split but actually split with the first div containing all content but only top 50% height of actual content, and second div containing all content but having only bottom 50% height of original div.
Here's what I have so far.
.container {
position: absolute;
width: 100%;
height: 20%;
}
.slide1, .slide2 {
width: 100px;
height: 50%;
/*height: 100%;*/
overflow: hidden;
position: absolute;
color: #AAA;
}
.slide1 {
background: #F00;
}
.slide2 {
top: 50%;
background: #0F0;
}
Here's a fiddle link.
UPDATE: This is what I want the end result to look like. This is just a quick hack that appears as though second div is split.
If you just viewed source in the demo site you supplied, you might have seen this bit of code:
<script type="text/javascript" src="js/jquery.slitslider.js"></script>
And if you googled jquery slitslider, the first link you get is FULLSCREEN SLIT SLIDER WITH JQUERY AND CSS3
Do you looking for this..
.container {
position: absolute;
width: 100%;
height: 100%;
}
.slide1, .slide2 {
width: 100px;
height: 100px;
overflow: hidden;
color: #AAA;
}
.slide1 {
background: #F00;
}
.slide2 {
top: 50%;
background: #0F0;
}
Fiddle: http://jsfiddle.net/6Kz7c/3/
EDIT:
Fiddle: http://jsfiddle.net/6Kz7c/5/
This uses a jquery plugin call FULLSCREEN SLIT SLIDER
So You no need to implement it from the sketch.
Here you can find a tutorial how to use that and download the library.
http://tympanus.net/codrops/2012/06/05/fullscreen-slit-slider-with-jquery-and-css3/
Edit:
css
* {
margin: 0;
padding: 0;
}
body {
background: #222;
}
.reveal {
width: 300px;
height: 300px;
margin: 50px;
float: left;
}
.curve {
background: url(http://designshack.net/tutorialexamples/splitreveal/300.jpg) 0px 150px, url(http://designshack.net/tutorialexamples/splitreveal/300.jpg) 0px -225px, #f6d9ad;
background-repeat: no-repeat;
-webkit-transition: background-position 0.3s ease;
-moz-transition: background-position 0.3s ease;
-o-transition: background-position 0.3s ease;
-ms-transition: background-position 0.3s ease;
transition: background-position 0.3s ease;
}
.curve:hover {
background: url(http://designshack.net/tutorialexamples/splitreveal/300.jpg) 0px 210px, url(http://designshack.net/tutorialexamples/splitreveal/300.jpg) 0px -285px, #f6d9ad;
background-repeat: no-repeat;
}
.reveal p {
font: 45px/300px Helvetica, Arial, sans-serif;
text-align: center;
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
opacity: 0;
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
-ms-transition: all 0.3s ease;
transition: all 0.3s ease;
}
.reveal:hover p {
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
filter: alpha(opacity=100);
opacity: 1;
cursor: pointer;
}
html
<div class="reveal curve">
<p>lorem</p>
</div>
Fiddle is here
The same principle as that of vertical splitting can be used for horizontal as well. The HTML layout had to be modified a bit to get it working.
HTML
<div class="container">
<div class="slide-wrapper">
<div class="slide1">
<div class="slide-content">Some content that has fixed width and positioned absolutely.</div>
</div>
<div class="slide2">
<div class="slide-content">Some content that has fixed width and positioned absolutely.</div>
</div>
</div>
</div>
Here's a working fiddle.
http://jsfiddle.net/6Kz7c/8/