Pure CSS3 animated slide-up caption on hover - html

The background is pretty simple, I wanted to have a small caption slide up from the bottom of an element when the user hovers/taps. See fig 1.
A bit of digging said this couldn't be done using CSS, but I really don't see why. A few hours later, I think I'm very close to solving it, but I can't jump the final hurdle.
My logic was, if your parent element has overflow: hidden, and you absolutely position the caption off the bottom of the parent, you can just animate the position values using the transition attribute so it slides up. Pure CSS baby!
You can't animate height- the text is crushed, the element has to be moved as a block (though not necessarily rendered as display:block).
Here's where I've got to so far https://jsfiddle.net/zufwavpn/. The HTML,
<div class="item-wrapper">
<div class="content">
Hello I am content. All that matters for this method to work is that the item wrapper has a fixed size. In my working project, the width is set to a % value, and the height to rem.
</div>
<div class="popup-title">
<span>A title for my content</span>
</div>
</div>
And the CSS (I've converted to vanilla CSS here),
.item-wrapper{
height:22rem;
position:relative;
overflow:hidden;
color:white;
font-family:sans-serif;
}
.content{
height:100%;
background-color:red;
padding:10px;
}
.popup-title{
position:absolute;
top:100%;
bottom:0%;
width:100%;
transition: bottom 0.5s, top 0.5s;
vertical-align: bottom;
}
.popup-title span{
display:block;
margin:0;
background-color: black;
}
.item-wrapper:hover .popup-title{
bottom:0%;
top:0%;
}
The reason I feel close is that at this stage, the popup basically works, but the content inside it should be aligned to the bottom of the container. Essentially it's the age old trick of set an absolutely positioned element's top and bottom to '0' but used to animate something from below the container.
Why am I animating the top and bottom attributes? If you only work with the 'top' value, you can hide the element by setting top:100%, but you can't animate that so it'll rest on the bottom of the parent. You'd need a specific value for top to be set to (height of parent minus height of content of pop up), and the pop up content / parent could be any size. You could set bottom:-100% - and this actually works, you can animate to bottom:0%, and the pop up with rest at the bottom of the parent. All good and done with no need to set a top value. But, it's unsatisfactory, you're having to place the slider way way below the parent and animate it up, which for various reasons to do with the other animations, produces a badly timed effect.
So, here we have the pop up element positioned at the bottom of the parent, with no height since the top and bottom values coincide, and the content overflowing downwards. Perfect. Then the top value animates up, the pop up element now has top:0; bottom:0, filling the parent, and if only I could get the content to stick to the bottom all would be well.
This last bit isn't usually too difficult. We have vertical-align, and the whole world of flex, but they all seem to produce errors and bugs and lead me down holes. Any ideas anyone? At this point I have to move on and just use javascript, but I feel like it's a problem worth solving in its own right.

.item-wrapper {
height:22rem;
position:relative;
overflow:hidden;
color:white;
font-family:sans-serif;
}
.content {
height:100%;
background-color:red;
padding:10px;
}
.popup-title {
position:absolute;
top:100%;
width:100%;
transition: transform 250ms;
vertical-align: bottom;
}
.popup-title span {
display:block;
margin:0;
background-color: black;
}
.item-wrapper:hover .popup-title {
transform:translateY(-100%);
}
<div class="item-wrapper">
<div class="content">
Hello I am content. All that matters for this method to work is that the item wrapper has a fixed size. In my working project, the width is set to a % value, and the height to rem.
</div>
<div class="popup-title">
<span>A title for my content</span>
</div>
</div>

Adjusted the top: and bottom: properties for the .popup-title, and moved the background color to the div, not it's child span. No need for specific heights here. It should be dynamic.
.item-wrapper{
height:12rem;
position:relative;
overflow:hidden;
color:white;
font-family:sans-serif;
}
.content{
height:100%;
background-color:red;
padding:10px;
}
.popup-title{
position:absolute;
bottom: -101%;
width:100%;
transition: bottom 0.5s, top 0.5s;
vertical-align: bottom;
background-color: black;
}
.popup-title span, .popup-title p{
display:block;
margin:0;
padding: 10px;
}
.item-wrapper:hover .popup-title{
bottom: 0;
}
<div class="item-wrapper">
<div class="content">
Hello I am content. All that matters for this method to work is that the item wrapper has a fixed size. In my working project, the width is set to a % value, and the height to rem.
</div>
<div class="popup-title">
<span>A title for my content. Height of the content here is irrelevant.</span>
</div>
</div>
<br />
<div class="item-wrapper">
<div class="content">
Hello I am content. All that matters for this method to work is that the item wrapper has a fixed size. In my working project, the width is set to a % value, and the height to rem.
</div>
<div class="popup-title">
<p>The popup div should expand as necessary. Even if there are multiple sentences or paragraphs.</p>
<p>Just dont' make it taller than the wrapper div</p>
</div>
</div>

Simply make .popup-title to have negative bottom position (not top value needed at all) and on hover transition it to 0.
.item-wrapper {
height: 22rem;
position: relative;
overflow: hidden;
color: white;
font-family: sans-serif;
}
.content {
height: 100%;
background-color: red;
padding: 10px;
}
.popup-title {
position: absolute;
bottom: -100%;
width: 100%;
transition: bottom 0.5s, top 0.5s;
vertical-align: bottom;
}
.popup-title span {
display: block;
margin: 0;
background-color: black;
}
.item-wrapper:hover .popup-title {
bottom: 0;
}
<div class="item-wrapper">
<div class="content">
Hello I am content. All that matters for this method to work is that the item wrapper has a fixed size. In my working project, the width is set to a % value, and the height to rem.
</div>
<div class="popup-title">
<span>A title for my content</span>
</div>
</div>

Related

container with background image and no content not displaying at all

I have two separate non nested sections with a background image. The one displays the other does not. The one does not display because takes up no space even though a height is specified. When I put content in it, it shows, but only at the height of the content. So the bg image is not the problem. Both have no content except for an absolutely positioned item (which does not count as content to browser). The section that displays is inside a regular div. The section that does not display is inside of a flexbox. Don't know why that would make a difference.
I've seen answers on the web and at stack overflow and they all consist of either changing the path of the background image to the correct one, or giving a height to the element with bg image. I already knew about both of those requirements and I have them in both tags (unless there's a typo). But it works in one, but not the other. Do I have a typo that I can't see from looking at it too much? Driving me nuts over what should be a simple thing. A second pair of eyes would be very helpful
this works:
<section class="headingImg">
<p class="container headerText">
Increase your home's value<br />and enchance your lifestyle
</p>
</section>
Related styles. Container class attribute comes from bootstrap therefore not defined in css
.headerText {
text-shadow: 2px 2px 2px #222;
color:#f4e9da;
font-size:36px;
padding-top:235px;
font-style:italic;
line-height:36px;
}
.headingImg {
background-image:url('images/browndeck.jpg');
background-position: center;
background-repeat:no-repeat;
background-size:cover;
height:350px;
margin-bottom:40px
}
this does not work because section with bgimage has no height even though one is specified
<div class="container">
<section class="flex">
<div class="flexDiv bgColor">
<section id="kitchens" class="imgBoxSize cover relative">
<h2 class="absCenter">Kitchens</h2>
</section>
<p>Enhance the lifestyle of your mice, cock roaches and flies</p>
</div>
</section>
</div>
Related styles
.bgColor{
background-color:white;
}
.flex {
display:flex;
justify-content:space-around;
flex-wrap:wrap;
}
.flexDiv {
background-color:#CCC;
width:30%;
margin:0 auto;
}
#kitchens {
background-image:url("images/kitchen1.jpg");
background-repeat:no-repeat;
}
.imageBoxSize {
height:200px;
width:100%
}
.cover {
background-size:cover;
background-position:center;
}
.relative {
position:relative
}
.absCenter {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin:auto;
}
In the HTML you call class imgBoxSize while in the CSS it is called imageBoxSize. Those darn typo's..

Fixed DIV not covered by following DIV

I have a "fixed" DIV on the very top of my page:
<div id="banner-wrapper">
<div id="banner"></div>
</div>
with the following CSS:
#banner-wrapper {
width:300px;
height:500px;
}
#banner {
width:300px;
height:500px;
position:fixed;
top:0;
left:0;
background:orange;
}
This "fixed" DIV is followed by a "content-wrapper" DIV:
<div id="content-wrapper">
<div id="content-left">
content left
</div>
<div id="content-right">
content right or sidebar
</div>
</div>
with the following CSS:
#content-wrapper {
width:300px;
background:red;
position:absolute;
top:500px;
bottom:0;
}
#content-left {
width:150px;
float:left;
}
#content-right {
width:150px;
float:right;
}
The issue I'm having is that the "content-wrapper" DIV does not fully cover the "fixed" DIV. The top of the "content-wrapper" covers the "fixed" DIV and the bottom of "content-wrapper" becomes transparent, showing the "fixed" DIV beneath.
I was able to solve the problem by giving the "body" a height in CSS. However, I do not want to give the "body" a height as I do not know the true hight of the content and would like it to remain flexible. I've also have tried inserting
<div style="clear:both;"></div>
before the closing tags but it does not force the "content-wrapper" down.
Here is an example of the issue on JSFiddle.
As you can see, the "red" box does not reach the "blue" box even though it is set to absolute, bottom 0. From what I can tell it reaches the bottom if it does not contain any DIVs inside of it. But once I add the "content-x" DIVs, it no longer reaches the bottom of the page.
Thank you for any help.
You could relatively position the element #content-wrapper rather than absolutely positioning it. Then you can omit the top/bottom positioning and it will behave as expected.
The reason it wasn't working in the first place was because you were giving the absolutely positioned element a height of 100%. Therefore it will have the same height is the window, which is not what you wanted.
Updated Example
Change the following:
#content-wrapper {
width: 300px;
height: 100%;
background: red;
position: absolute;
top: 500px;
bottom: 0;
}
to:
#content-wrapper {
width: 300px;
background: red;
position: relative;
}

Getting rid of space under relative div with negative margin-top

I have some kind of animated javascript slider. I wan't some items to stick out a little of the top of my slider but to be hidden when they stick out of the bottom of the wrapper, so i made a div with overflow:hidden; with a little extra space over it. I now need to get rid of that extra-space in the flow.
It wasn't a problem before because i'd just set the div as absolute but now i'm making my layout fluid and i can't have absolute divs because the slider's height is relative to the document's width. Is there any way to get rid of those extra-pixels ? Thanks in advance.
http://jsfiddle.net/ySg6f/
Here's the actual website if it can help : http://pa3com.a3net.fr/
<header>
<div id="slider_wrapper">
<div class="overflow">
<div id="slider">
</div>
</div>
</div>
header
{
padding-top:20px;
background-color:blue;
}
#slider_wrapper
{
position:relative;
background-color:green;
}
.overflow
{
padding-top:12px;
overflow:hidden;
}
#slider
{
height:0;
padding-bottom:25%;
background-color:red;
top:-12px;
position:relative;
}
.overflow {
padding-top: 0;
}
#slider {
top: -12px; /* remove this */
}
Finally solved it by using negative margin and adding 1px padding on the parent.

When using position:absolute, how do I define that I want the bottom edge of one element aligned against the top edge of another?

I have a column of text, with wide margins on either side. Below it, I have a full-width section of data (in tabular format).
I can align these against each other quite readily. My problem is that there is a 'tab' that sits on top of the table section. It's narrow enough that it doesn't interfere with the center column of text, and the layout calls for it to slide up into the white space to the left of the text.
The easy solution would a position:absolute, with top:foopx to slide it up relative to the rest of the div. The only problem is, the tab's height is dynamic. I need to somehow to top:'height'px, but (obviously) CSS doesn't contain anything for dynamic values.
What I need to do is align the bottom edge of the 'tab' against the top edge of the containing div, and I cannot for the life of me figure out any CSS statement that does that. I'd rather avoid a javascript based approach (e. g. at runtime get the height of the tab, then set top equal to that height) because the entire bottom div is refreshed from time to time using an AJAX call, and adjusting the height in that process causes the page to 'jitter' on the update (not sure why it doesn't happen without the height update; the jitter is in a separate section of the code).
Requested code example:
<html>
<head>
<style>
#smallColumn
{
float:left;
width:100px;
height:100px;
background:#000;
margin:5px;
}
#fullColumn
{
float:left;
width:200px;
height:300px;
background:#000;
margin:5px;
}
#bottomDiv
{
position:relative;
}
#tab
{
position:absolute;
top:-40px;
}
</style>
</head>
<body>
<div id="smallColumn">a</div>
<div id="fullColumn">b</div>
<div style="clear:both"></div>
<div id="bottomDiv">
<div id="tab">Tab</div>
<hr />
DATA DATA DATA
</div>
</body>
</html>
Use top margins, the appropriate display properties and vertical-align:bottom. See the code below + comments for an explanation. You have to set a height and negative margin-top value which is larger than the actual height of the tab's content. Otherwise, the content may jump back to the top.
Relevant HTML/CSS:
<div id="cont">
<div id="tab">
<div id="tab-fix">
Tab
</div>
</div>
Rest of content
</div>
#cont {
margin-top: 30px; /*Reserve space*/
height: 100px;
background: lightgreen;
}
#tab {
display: table; /* Necessary for the application */
margin-top: -30px;/* Move tab to the top*/
}
#tab-fix {
height: 30px; /* Expecting the height to not exceed 30px*/
display: table-cell;
vertical-align: bottom; /* Aligns the content at the bottom*/
}
Fiddle: http://jsfiddle.net/stEW3/2/
Update2
So this is a tough problem to solve! The only thing I could think of was to put a wrapper around the tab. That wrapper needs to be relatively positioned and have a height equal to that of the tab. Then you can use absolute and negative top of 100%.
http://jsfiddle.net/mrtsherman/BC8Xr/2/
Update
With posted code I now understand. How about using absolute and specifying a bottom value of 0?
http://jsfiddle.net/mrtsherman/BC8Xr/
<div id="content">
<div id="smallColumn">a</div>
<div id="fullColumn">b</div>
<div style="clear:both"></div>
<div id="bottomDiv">
<div id="tab">Something</div>
<hr />
</div>
</div>
#content { border: 1px solid red; position: relative; }
#bottomDiv
{
position:absolute;
bottom: 0px;
}
#tab
{
/*
position:absolute;
top:-40px;
*/
}
Old
Without html structure and a somewhat vague description this is a bit hard to decipher. But this is what I think you mean:
http://jsfiddle.net/mrtsherman/VM99L/
Basically you want the tab above the tabular data to be drawn up into the div before it. You can use a negative top margin for this. Just set it to the same height as the height of your tab. If you have padding on the div then you will need to compensate for that also.
<div id="tabulardata">
<div id="tab">Tab X</div>
<table>
<tr><td>data</td></tr>
<tr><td>data</td></tr>
<tr><td>data</td></tr>
<tr><td>data</td></tr>
<tr><td>data</td></tr>
</table>
</div>
#tabulardata { margin-top: -50px; }
#tab { height: 50px; width: 80px; background: gray; color: white; }

How to do such layout with html+css?

Boxes are some objects(button, label, textarea). Green's size is dynamic. Especially I have a problem with the blue box stick to bottom.
Place a holder around it and it will take the height from the 'green' one, and give them only absolute and bottom 0, it won't matter what width you give your elements.
Edit: hopefully this works for you, with floating the elements, the green one to the right, and the rest left.
<div id="divHolder">
<label id="red">Label</label>
<button id="blue">Button</button>
<div id="green">
a
</div>
<br class="clearFloat" />
</div>
#divHolder {
width:300px;
position:relative;
}
#green {
height:300px;
background-color: green;
float:right;
}
#red {
background-color:red;
float:left;
position:absolute;
}
#blue {
background-color: blue;
bottom: 0;
position:absolute;
}
.clearFloat {
clear:both;
}
check it out here:
http://jsfiddle.net/YA9yD/32/
Here's my solution →
The main problem here is that the left-hand column doesn't know how tall the right-hand column is.
You can put them in a parent together (which will wrap both columns), but the left-hand column will not know the height of the parent because a child element can only expand to the height of a parent element if the parent element's height is explicitly set.
Also, there are two distinct columns here, so I wanted to try and group them as close to the way they appear as possible. Putting the left column inside the right column (the green box) doesn't accurately represent how this is structured.
HTML:
<div id="container">
<div id="labelDiv">
<label>I'm a label.</label>
<p>Text area, whatevs.</p>
</div>
<button>Hello</button>
<div id="greenBox">
<p>Green box text.</p>
</div>
</div>
CSS:
#container {
width: 610px;
overflow: hidden;
position: relative;
}
#labelDiv {
width: 300px;
float: left;
}
button {
position: absolute;
bottom: 0;
left: 0;
}
#greenBox {
width: 310px;
float: left;
}
So everything on the left (other than the button) is floated left, and the green box is also floated left. Great so far, but the the button needs to know how tall the entire box is so that it can attach itself to the bottom. So, we set overflow to hidden on the outer container so that it wraps around the floated elements, and absolutely positioning the button to the bottom of this aligns it exactly with the bottom of the tallest inner element (the green box).
I'd also recommend setting some margin-bottom on #labelDiv so that it doesn't cover up the button.
See example of the following →
As long as the blue and red widths are specified, you could use relative and absolute position as follows:
<div id="green">
<label id="red">Label</label>
<button id="blue">Button</button>
</div>
#green {
position:relative;
}
#red {
width:100px;
position:absolute; left:-110px; top:0px;
}
#blue {
width:100px;
position:absolute; left:-110px; bottom:0px;
}