CSS "table-cell" styled element: Maximum height (and overflow: hidden) - css

I have a display: table-cell div inside a display: table div. Is there any way to limit the height? I've tried setting height, max-height, and overflow: hidden, but it has no effect. (height does set the minimum height, but the others seem to do nothing.
See example at http://jsbin.com/gajaka/1/edit
<div class='table'>
<div class='cell'>This should be maximum 100px. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</div>
css
.table {
display: table;
background: green;
width: 100px;
height: 100px;
max-height: 100px; /* ignored */
overflow: hidden; /* ignored */
}
.cell {
display: table-cell;
vertical-align: middle;
max-height: 100px; /* ignored */
text-align: center; /* doesn't work */
}

As far as I can see with this code, it appears you are using the table cell display in order to vertically align the text. However, table-cell comes with the inherent tradeoff that you lose control of the y-dimension; that is, the table-cell will ignore all height parameters, as you've seen.
The way to fix this would be to change the display sub-attribute from table-cell to inline-block. Then, in order to get the vertical centering, we can do the following: Place a pseudo-element inside the .table element and vertically align this. Vertical align needs to be relative to another inline element, so this pseudo-element gives a reference for the .cell to vertically align itself against. This should vertically align your text.
New output: http://jsbin.com/faqadumasado/1/edit?html,css,output
Article on "Centering in the Unknown" that describes the vertical centering technique above: http://css-tricks.com/centering-in-the-unknown/

Related

Why does translating div remove overflow?

It is not entirely clear to me how CSS transforms affect the flow layout of the document and the positioning of an element. According to the documentation on MDN and W3C, CSS transforms do not interfere with the flow layout:
From MDN on CSS transforms (emphasis mine):
By modifying the coordinate space, CSS transforms change the shape and position of the affected content without disrupting the normal document flow.
Thus, if we translate an element, the original flow layout should remain intact and the result of the transformation should be purely visual.
A trivial example of this is demonstrated below:
.container {
background: white;
margin: 0 auto;
border: 1px solid grey;
}
.block {
width: 100%;
height: 100px;
}
.blue {
background: blue;
}
.red {
background: yellow;
}
.transform {
transform: translateY(-200%);
}
<div class="container">
<div class="block red transform"></div>
<div class="block blue"></div>
</div>
In this example, there are two div elements and the upper element was translated vertically so that it is not visible anymore. However, the flow layout remains unchanged and there is no overflow in the document. That is, the result of the transformation is purely visual.
Now, consider a page layout with a wrapper of fixed width, such that the width of the child elements is bounded by the wrapper element. Now add a positioned element that is wider than the wrapper and add an offset (e.g. left). In "narrow enough" windows, the body overflows and we are able to scroll horizontally. However, if we translate the same element and re-center it, the overflow disappears, implying that the transformation is not purely visual.
A demonstration of this effect is shown in the example below. Initially, the offset element is not transformed. You may try resizing your window to see the overflow and then toggle the transformation with the button in the center.
document.getElementById('toggle').addEventListener('click', function(event) {
const blocks = document.querySelectorAll('.block.wide');
for(let i=0;i<blocks.length;i++) {
const block = blocks[i];
block.classList.toggle('transform');
}
});
html, body {
background: #ddd;
}
.container {
background: white;
max-width: 1152px;
margin: 0 auto;
}
.content {
border: 1px solid grey;
}
.block.wide {
background: yellow;
max-width: 1380px;
width: 100vw;
position: relative;
left: 50%;
}
.block.wide.transform {
transform: translateX(-50%);
}
<div class="container">
<div class="content">
<div class="block">
<h1>Lorem ipsum dolor sit amet</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p><strong>Click the button below to toggle the transform and see the overflow vanish</strong></p>
<button id="toggle">Toggle Transform</button>
</div>
<div class="block wide">
<h1>Lorem ipsum dolor sit amet</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>
Is this the intended behavior according to the specifications? How do offsets and transformations interact?
In all my test cases, the CSS transform achieves the desired result. However, I feel that I am relying on luck rather than a technical specification.
There's several points to cover here.
From the CSS Transforms spec, Section 3. The Transform Rendering Model says:
For elements whose layout is governed by the CSS box model, the transform property does not affect the flow of the content surrounding the transformed element. However, the extent of the overflow area takes into account transformed elements. This behavior is similar to what happens when elements are offset via relative positioning. Therefore, if the value of the overflow property is scroll or auto, scrollbars will appear as needed to see content that is transformed outside the visible area. Specifically, transforms can extend (but do not shrink) the size of the overflow area, which is computed as the union of the bounds of the elements before and after the application of transforms.
Which means transforms are supposed to affect the overflow and scrolling. However, in your first example, the overflow is to a negative coordinate space, and that overflow is always clipped, so it doesn't generate any new scrollbars.
But your second example, on a direct reading, seems to be in contradiction to the specification, with the transform shrinking the overflow area. What I think is happening here is that position relative shifts, and transforms are, as acknowledged by the quote above, very similar operations, and the transform is undoing the effect of the relative positioning.
In other words, the overflow area is being computed as the union of the bounds of the elements before and after the application of relative positioning and transforms.

CSS ONLY vertically center with scroll even when child is bigger than screen

I have a similar problem as described here:
Center page vertically, make it scroll if bigger than screen
however I'm trying to find a pure CSS only solution, not involving JS.
I have a fixed containers defined like that:
.parent{
position: fixed;
z-index: 100;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: auto;
}
.child{
position: absolute;
top: 50%;
left: 0;
right: 0;
transform: translateY(50%);
margin: 0 auto;
width: 600px;
}
It's well centered (as expected) when child is smaller than parent/viewport height. The problem is when child's height is greater then parent's height. Let's say parent has height 1000 px and child's height is 1600 px.
With above styles applied, I can scroll child (as expected) but not all the way to its top. The top of child is hidden and not possible to scroll to it.
What I want to achieve is to be able to scroll the child all the way to its top border.
The main question is if it's possible to achieve that with CSS only?
.parent {
display: flex; /* Use this proparty */
align-items: center; /* For Center align */
justify-content: center; /* For Center align */
overflow: auto; /* For auto scroll */
padding: 20px; /* This is only for spacing */
}
.child {
border: 1px solid red;
margin: 0 auto;
max-width: 560px; /* Use max-width instant of width in responsive it's help you for better view */
max-height: 100%; /* Use max-height instant of heiht in responsive it's tack auto height from text/content */
}
<!-- Parent Div start Here -->
<div class="parent">
<div class="child">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<br><br> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</div>
<!-- Parent Div ends Here -->

CSS trigger hover only for top element

Is there elegant solution to hover only for top element, not for underlying; or i should to do this using javascript?
<div class="WithHover1">
<div class="WithHover2">
I am Top and I want to be the only div hightlighted
</div>
I want to be hightlighted too, but I dont want to be hightlighted when the nested one is
</div>
You can't do this in just CSS, yet. The has selector is in draft for level 4/5 (I forget) CSS selectors, which will be awesome.
For now, javascript/jquery would be the easiest and most practical method.
$(".WithHover2").mouseover(function() {
$(".WithHover1").removeClass("highlight");
$(this).addClass("highlight");
});
Here's a CSS3 solution, using the ::after pseudo-element, with a bottom border that overrides the background color of the bottom text.
The negative z-index prevents the border from covering up the text, and overflow: hidden prevents WithHover1 from expanding due to the large border.
It works in IE11 (at least), Chrome, Firefox, Safari, and Opera:
div.WithHover1 {
font: 14px verdana;
position: relative;
overflow: hidden;
}
div.WithHover1:hover {
background: yellow;
position: relative;
z-index: 1;
}
div.WithHover2:hover {
background: orange;
}
div.WithHover2:hover::after {
content: '';
display: block;
position: absolute;
border-bottom: 1000px solid white;
width: 100%;
z-index: -1;
}
<div class="WithHover1">
<div class="WithHover2">
I am Top and I want to be the only div highlighted
</div>
I want to be highlighted too, but I dont want to be highlighted when the nested one is.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
</div>
This isn't what you want? Your post wasn't that clear to me what you needed when hovering over each.
.WithHover2:hover, .WithHover3:hover {
background-color: yellow;
}
<div class="WithHover1">
<div class="WithHover2">
I want to be the only div hightlighted
</div>
<div class="WithHover3">
I dont want to be hightlighted when the nested one is
</div>
</div>

How to make foreground image in div take up full width/height of screen

I need to make an image auto-fill the width and height of the viewer's screen, while keeping the correct aspect ratio. The ultimate goal is to display a jquery slideshow in the background of the page, while also making it fill the full width and height of the screen.
This jfiddle shows an approximation of what I am talking about: http://jsfiddle.net/hockey2112/s1d2peqh/1/
Here is the CSS from that jfiddle:
#slideshow {
height: auto;
position: fixed;
width: 100%;
z-index: -1;
}
.slide img {
height: auto;
width: 100%;
}
.contentbox {
background-color: #ffffff;
border:5px solid #000000;
margin: 0 auto;
width: 300px;
}
and the code:
<div id="slideshow">
<div class="slide">
<img src="http://www.iapics.org/images/3542-wallpaper-landscape-wallpapers-1920x1080.jpg">
</div>
</div>
<div id="content">
<div class="contentbox">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</div>
I need the image to fit the height of the screen first, and then show as much of the width of the image as will fit in the screen. If you expand and contract the viewport of that jfiddle, you'll see that the image does not fill the height of the preview panel.
Thanks!
I'm not aware of a way to do this in CSS alone.
You can either have the image stretched to 100% horizontally and centered vertically OR you can stretch 100% vertically and center horizontally.
However, with a little but of js, you can switch between these two options pretty easily, and that should get you what you want.
Horizontal Stretch + Vertical Center:
.slide.horz{
height:100%;
width:100%;
}
.slide.horz img {
width: 100%;
height:auto;
display:block;
margin:auto;
position:absolute; /*trick for vertical center*/
top:0; /*trick for vertical center*/
bottom:0; /*trick for vertical center*/
}
Vertical Stretch + Horizontal Center:
.slide.vert{
height:100%;
width:300%; /* trick for 'zoomed' horizontal center */
margin-left:-100%; /* trick for 'zoomed' horizontal center */
}
.slide.vert img {
height: 100%;
width:auto;
display:block;
margin:auto;
}
Then some jquery will let you switch between the classes based on the aspect ratio of the window.
$(window).resize(function() {
setStyle();
});
function setStyle(){
var winRat=($(window).width() +0.0)/($(window).height() + 0.0);
var imgRat = 1920.0 / 1080.0;
//do vertical stretching
if( winRat < imgRat){
$(".slide").removeClass("horz");
$(".slide").addClass("vert");
}else{
//do horizontal stretching
$(".slide").removeClass("vert");
$(".slide").addClass("horz");
}
}
Have only tested this in latest chrome. I have reason to believe it may break in ie<=8.
http://jsfiddle.net/s1d2peqh/3/
This is the purpose of the VH (viewport height) and VW (viewport width)
body { width:100%;height:100%; }
#slideshow { height: 100vh;position: fixed;width: 100vw;z-index: -1; }
.slide img { height: 100vh;width: 100vw; }

Push footer down to page when div content is generated?

I have the page as the showed picture
When something is clicked on the right column, the DIV on the left column will appear with generated content. This Div has a fixed height but its position may vary depending on the clicked position on the right column. As you can see when the Div appears, the footer is not pushed down.
I have tried many solutions on SO to re-position the footer as in How to keep footer at the bottom even with dynamic height website
but none of them works for me. Maybe I have done something wrong?
My footer's css:
#footer{ color: #666666; background: #D3D3D3; border-top: 1px solid #AAA;
padding: 1em; margin-top: 0; position:absolute; width:100%; }
DEMO : http://jsfiddle.net/WTUPn/
<div id="wrapper">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<div class="push"></div>
</div>
<div id="footer">
</div>
<style type="text/css">
body, html { height: 100%; }
#wrapper {
min-height: 100%;
margin-bottom: -90px;
position: relative;
}
#footer, .push { height: 90px; }
#footer {
background: #000; color: #FFF;
}
</style>
apparently you'll need to insert more code but your footer cannot be positioned absolutely as it takes a specific position irrespective of other divs

Resources