Is there a way to have divs "greedily" grab width? - css

I have 2 divs that are side by side. They are both closable via jquery. When they are both visible, they have a fixed width, but when one is closed, I want the remaining div to expand to eat up the width that the closed div used to take up. Is there a way to do this using just CSS (aside from the close button), or do I have to resort to javascript?

The only method I could see for solving this with CSS would be to add classes to the containing element:
<div id="container" class="left|right|both">
<div class="left"></div>
<div class="right"></div>
</div>
Style the contents depending on what the parent class is. If left is the class, you give the first div a non-restricted width and hide the second div. The same goes for right and the second div. When the parent is both, you give both divs 50%.
All your JavaScript would need to do is handle which class is currently applied to the container.

You need to atleast write one line of javascript for this and then you can use css for the effect.
Using jquery, toggle a class to the parent of divs whenever you click on the close. Find the jquery code for the click on the close button and add
$("#parent").toggle("classname");
Use css like
#parent div { width: /*fixed*/100px; }
#parent.classname div { width: 100%; }

Does something like this work?
HTML:
<div id="parent">
<div class="right">div2</div>
<div class="left">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam semper porta sem, at ultrices ante interdum at. Donec condimentum euismod consequat. Ut viverra lorem pretium nisi malesuada a vehicula urna aliquet. Proin at ante nec neque commodo bibendum. Cras bibendum egestas lacus, nec ullamcorper augue varius eget.</div>
</div>
<br />
<button id="remove">Remove Div 2</button>
CSS:
#parent {
overflow: hidden;
border: 1px solid red
}
.right {
float: right;
width: 100px;
height: 100px;
background:green;
}
.left {
overflow: hidden;
height: 100px;
background:red;
}​
​
JS:
$('#remove').on('click', function() {
var div2 = $('.right')
//div2.hide('slow'); // you could hide it as well
div2.remove();
});​
Example:
http://jsfiddle.net/9Q86Y/

Edit
You could mimic tables by using
display:table
and
display:table-cell
See: http://jsfiddle.net/DUx3W/ (hat tip: #Jimmy Breck-McKye).
My original table fiddle: http://jsfiddle.net/6KkRL/

Related

Vertically align a div in a parent which has height auto AND min-height set?

I'm stuck on this one.
I want to vertically center a div. Its parent has an unknown height, however, it does have a min-height.
How can I do this?
Here is one approach using the CSS3 transform property.
Use absolute positioning to place the top edge of the child element at 50% from the top, and then use the transform: translateY(-50%) to adjust for the child's height.
.parent {
height: auto;
min-height: 200px;
border: 1px dotted gray;
position: relative;
}
.child {
border: 1px dotted blue;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
}
.content {
margin-left: 100px;
margin-right: 400px;
}
<div class="parent">
<div class="child">child</div>
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer facilisis velit ut neque tempor quis cursus tortor suscipit. Curabitur rutrum magna vitae arcu pharetra eget cursus ante accumsan. Nunc commodo malesuada adipiscing. Pellentesque consequat laoreet sagittis. Sed sit amet erat augue. Morbi consectetur, elit quis iaculis cursus, mauris nulla hendrerit augue, ut faucibus elit sapien vitae justo. In a ipsum malesuada nulla rutrum luctus. Donec a enim sapien. Sed ultrices ligula ac neque vulputate luctus. Suspendisse pretium pretium felis, in aliquet risus fringilla at. Nunc cursus sagittis commodo.
</div>
</div>
An other solution requires Javascript.
Javascript can help you to get the real height of the parent element :
var myElt = <your parent selector>;
var myEltHeight = myElt.offsetHeight;
After that, you can set the 'line-height' property of the parent to be equal to this height,
myElt.style.lineHeight = myEltHeight + 'px';
And finally add a 'vertical-align: middle' to him.
myElt.style.verticalAlign = 'middle';
Of course you have to re-do the maths each time the parent element is resized (with a window resizing for instance)...
For the record, I did not test this solution. It probably needs some adjustments ...
Use a table display, like this:
div {
height: 80vh;
/* Random height and width */
width: 80%;
border: 5px solid blue;
display: table;
}
p {
display: table-cell;
height: 100%;
vertical-align: middle;
text-align: center;
}
<div>
<p>
Some centered content.
</p>
</div>
I do not recommend this usage, but you can use a display:flex on the parent element, and use one of the following, according to your needs, on the child item :
The flex-direction property establishes the main axis.
The justify-content property defines how flex items are laid out along the main axis on the current line.
The align-items property defines the default for how flex items are laid out along the cross axis on the current line.
The align-self property defines how a single flex item is aligned on the cross axis, and overrides the default established by align-items.
Source : Using CSS flexible boxes
This guide can be helpful to understand the mechanism : A Complete Guide to Flexbox
/!\ Warning :
flexbox properties are really attractive (I have been really interested in them some times ago) but they become really instable as soon as you use some absolute positionning within the DOM.
flexbox properties needs some vendor prefixes for not-even-so-old version of almost all browsers. And sometimes the properties does not even have the same names (there are the old, tweener and new syntaxes. See the end of this post : A Complete Guide to Flexbox)

Flexbox height not updating when content changes

There seems to be a problem with flexbox in chrome which affects columns of variable height. When the contents of these columns change the column should resize, but it doesn't
I have created a JS fiddle here - http://jsfiddle.net/KVQTd/2/
Just hit the 'remove content button' to see what I mean.
This is the simplest example of using flexbox to create columns to demonstrate that nothing else is causing it.
.wrapper{
display: flex;
align-items: stretch;
}
.column1{
flex: 1;
}
.column2{
flex: 1;
}
I'm pretty sure this is a bug in Chrome because when you go into developer tools and switch flex off and on again it then calculates the height correctly.
I have submitted a bug report here - https://code.google.com/p/chromium/issues/detail?id=369869&thanks=369869&ts=1399226675 -
...but I don't have time to wait for new versions of Chrome to be released so I was hoping somebody might be able to think of a clever solution. Perhaps some kind of javascript which watches the height of the inner content and adjusts forces a recalculation of the flexbox height?
This works for me:
var elem = document.getElementById("myFlexbox");
elem.style.display='none';
elem.offsetHeight; // no need to store this anywhere, the reference is enough
elem.style.display='flex';
Also see: How can I force WebKit to redraw/repaint to propagate style changes?
In order to work in Chrome, it needs a refresh or some kind of reflow. DEMO
If you script force the main container to be recalculated, you have something that works.
(this looks like some very old bug of Opera)
In order to do that, we can switch from position static to relative and use a pseudo to insert some content.
CLASS wrapper becomes an ID to easily select it via JavaScript
<div id="wrapper">
<div class="column1">This column Has some content</div>
<div class="column2">This column also has some content
<div id="contentToHide">
<p>Sed egestas, ante et vulputate volutpat, eros pede semper est, vitae luctus metus libero eu augue. Morbi purus libero, faucibus adipiscing, commodo quis, gravida id, est. Sed lectus. Praesent elementum hendrerit tortor. Sed semper lorem at felis. Vestibulum volutpat, lacus a ultrices sagittis, mi neque euismod dui, eu pulvinar nunc sapien ornare nisl. Phasellus pede arcu, dapibus eu, fermentum et, dapibus sed, urna.</p>
</div>
</div>
</div>
<button id="removeButton">Remove Content</button>
<br/>
<button id="addButton">Add Content</button>
javaScript update
document.getElementById('removeButton').addEventListener("click", function (event) {
document.getElementById('contentToHide').classList.add("hidden");
document.getElementById('wrapper').classList.add("prelative");
});
document.getElementById('addButton').addEventListener("click", function (event) {
document.getElementById('contentToHide').classList.remove("hidden");
document.getElementById('wrapper').classList.remove("prelative");
});
CSS update:
#wrapper {
display: flex;
width: 400px;
margin-bottom: 30px;
}
.column1 {
padding: 10px;
background: #DDD;
}
.column2 {
padding: 10px;
background: #EEE;
width:50%;
}
#contentToHide.hidden {
display: none;
}
.prelative {
position:relative;
}
div:before {
content:attr(class);
left:-9999px;
position:absolute;
}
Actually, for .hidden and pseudo you can just do :
#contentToHide.hidden ,
div:before {
content:attr(class);
left:-9999px;
position:absolute;
}
Try to set height: 100% for columns
I solved this by setting height: max-content on the children of the flex container

Resizing background image and content below with CSS

For responsive images, I am using the CSS properties background-image and background-size. This allows the image to automatically resize when the browser window is resized. The problem is, content below the image is not also resizing. For example, in this set up I have an image above a paragraph of text:
<div class="container">
<div class="image></div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ut ligula lacinia, eleifend risus nec, adipiscing magna. Integer egestas fermentum lectus, ac bibendum diam faucibus eu.<p>
</div>
For the CSS I have:
.container {
width: 50%;
}
.image {
background-image: url('image.jpg');
background-repeat: no-repeat;
background-size: 100%;
height: 350px;
}
When the browser is adjusted, the image also is adjusted but since there is a set height to the image (350px), a gap forms beneath the image and the paragraph. Are there some CSS changes I can make that will allow the paragraph to stay directly under the image when the image is resized?
Here is a jsFiddle example http://jsfiddle.net/qKGt9/
You should not be using an image as a background if you want text to flow around it. Responsive design techniques will typically employ this trick to IMG elements:
/* Responsive image CSS */
img {
width: 100%;
height: auto;
}
I've forked your fiddle for a working example:
http://jsfiddle.net/WDFBR/
It requires some slight changes to your HTML structure and CSS. The main thing is that I'm using an IMG element instead of a DIV to display your image. Take a look at the goods under the hood of popular frameworks like Twitter Bootstrap and you'll learn a lot about good responsive design.
Does this fit the requirements?
.image {
background: url('http://c.tadst.com/gfx/600x400/int-mountain-day.jpg?1') no-repeat;
background-size: 100%;
padding-top: 66.667%; /* holds 3:2 aspect ratio */
}
Fiddle
<div class="container">
<div class="image>
<img src="image path" />
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ut ligula lacinia, eleifend risus nec, adipiscing magna. Integer egestas fermentum lectus, ac bibendum diam faucibus eu.<p>
</div>
</div>
try this..
Put the actual image in the html code, and set the universal width of img elements to fill 100% width of their parent containers:
HTML:
<div class="image">
<img src="http://c.tadst.com/gfx/600x400/int-mountain-day.jpg?1">
</div>
CSS:
img {
width: 100%;
}
Fiddle:
http://jsfiddle.net/philsinatra/qKGt9/3/
Here is your 100% solution:
Follow below URL, I have just recently answered on the same question.
Responsive CSS background image - how to make content follow
If need more help, most welcome :)

Float text over bottom positioned box

I'd like to code html+css to achieve result as shown on attached image: .
I mean the coding part with text and arrow box. Putting just position absolute is not an answer, cause I need text to float round the arrow box. Is there any way to do that?
I've alredy tried putting all kinds of floats on box and paragraf tag with text. Placing arrow box before, after and in paragraf tag. Also tried using vertical-align and position on arrow box.
Fiddle to play with:
http://jsfiddle.net/K2S5y/1/
<div class="content">
<p>Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis. Maecenas males elit lectus felis, malesuada ultricies. Curabitur et ligula.</p>
<div class="arrowMore">arr</div>
</div>
.content{width:170px;height:170px;border:1px solid red;}
.arrowMore{background:blue;width:70px;height:70px;}
Use clear:both ex.
<div style="float:left; width:300px">
<img/>
</div>
<div style="float:left; width:300px">
Text text text
</div>
<div style="clear:both"></div>
you can see the live example here:
http://webdesign.about.com/od/examples/l/bl-css-float-examples.htm#floating
#arrow {
float: right;
}
/* then possibly */
#arrow:after {
content: ' ';
display: block;
clear: both;
}

how to enforce hover state div is shown above other elements and outside of container?

i've been going over this one for about two days.
example
it's a fairly complicated design, so to reduce code pasted here i've recreated the main structure on this jsfiddle and included the simplified code at the end of this post:
http://jsfiddle.net/rwone/zwxpG/10/
scenario
i have a container with numerous <li>'s containing a div (containing dynamic content from a database) that initially has the property display: none.
on hovering over an image in these <li>'s however, i wish to show the div.
it is working, however the div appears to be beneath other elements in the container which has a fixed height and overflow-y: auto.
what i've tried
i have tried combinations of z-index's and absolute and relative positioning, but i haven't been able to find a solution yet.
i've isolated two causes in the code below and the jsfiddle (shown as /* comments */) but these do not work on the live test site.
question
my question is therefore, is there another way to enforce that the hover state div is shown on top of and outside of the container that is enclosing it?
it is not an ideal solution that i can fix these issues in the jsfiddle but not the live site, but i just thought i'd ask if there was another way to approach this altogether?
thank you.
html
<div id="wrapper">
<div id ="hbar_one"></div>
<div id="hbar_two"></div>
<div id="container_a">
<div id="container_b">
<ul>
<li>
hover me #1
<div id="container_c">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In fringilla porttitor ante ut varius. Fusce volutpat velit ut orci porttitor cursus. Donec est eros, tempor ac elementum et, volutpat sit amet lorem. Mauris iaculis eros nec sapien hendrerit at sodales nibh iaculis. Morbi imperdiet porta est vitae suscipit. Curabitur sit amet diam in nulla consectetur placerat. Etiam in sapien ac mi scelerisque congue eu id lectus. Proin fermentum auctor turpis vel adipiscing. Maecenas at convallis sapien.
</div>
</li>
<li>
hover me #2
<div id="container_c">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In fringilla porttitor ante ut varius. Fusce volutpat velit ut orci porttitor cursus. Donec est eros, tempor ac elementum et, volutpat sit amet lorem. Mauris iaculis eros nec sapien hendrerit at sodales nibh iaculis. Morbi imperdiet porta est vitae suscipit. Curabitur sit amet diam in nulla consectetur placerat. Etiam in sapien ac mi scelerisque congue eu id lectus. Proin fermentum auctor turpis vel adipiscing. Maecenas at convallis sapien.
</div>
</li>
</ul>
</div>
</div>
<div id="hbar_three"></div>
<div id="hbar_four"></div>
</div>
css
#wrapper {
width: 300px;
}
#hbar_one {
background: #cc0000;
height: 50px;
}
#hbar_two {
background: #ffcc00;
height: 50px;
}
#container_b {
height: 50px;
/* cause one - on its own, this causes the undesired 'underneath' effect */
overflow-y: auto;
}
ul li {
display: inline;
/* cause two - on its own, this causes the undesired 'underneath' effect */
position: relative;
}
#container_c {
display: none;
}
ul li:hover #container_c {
background: #00AFF0;
display: block;
width: 200px;
height: 200px;
position:absolute;
top: -20px;
left: 50px;
z-index: 999;
overflow: hidden;
}
#hbar_three {
background: #cccccc;
height: 50px;
}
#hbar_four {
background: #000000;
height: 50px;
}
update
in response to answer below, here is further information on the actual content that is being displayed upon hover (everything within the #container_c div). each <li> has its own unique content:
​<li class=".class1 .class2">
<img src="http://path/to/image.jpg">
<div id="container_c">
<h4>title</h4>
<div id="container_c_left">
<span id="cl1">text</span>
<span id="cl2">text</span>
<span id="cl3">text</span>
</div>
<div id="container_c_right">
<span id="cr1">text</span>
<span id="cr2">text</span>
</div>
<span id="cc1">text</span>
<span id="cc2"><a class= "linkclass" href="http://path/to/link.html">link</a></span>
</div>
</li>
You only want to display one of these hover elements at a time?
Put a single DIV outside of the main body and make it hidden.
Then use javascript to adjust its position and content every time you hover over an LI.
No need to give every LI its own DIV.
Store the contents inside a data attribute
<li id=something data-some-content="Hello joe">
Then you can retrieve it with jQuery like so
$("#something").data('some-content')
Your CSS styles are correct but in your HTML you have two <div> elements with the id='container_c' and that's invalid, IDs are unique and you can't give same id to two or more elements. If you two ore more elements to be given same style then try class='container_c' and in the CSS change the #container_c to .container_c
Check this fiddle for the fixed version
http://jsfiddle.net/DeepakKamat/zwxpG/13/
the solution was a mixture of #NoPyGod's jquery suggestion and to have a better understanding of how absolute and relative positioning work.
basically, when absolute and relative positioning are applied to a div, this position is relative to the position of the last element that had absolute or relative positioning defined and is a 'container' of the div you are working with.
to escape from the 'container' that had overflow: auto and a fixed height and width, i had to remove erroneous positioning back till a parent div that was not constrained by overflow and height and width restraints that were impacting on the hover state div.
a working jsfiddle is here:
http://jsfiddle.net/rwone/eeaAr/
i also implemented #Deepak Kamat's suggestion to only have one id per page and change the rest of the div's to be identified by classes.
i subsequently read the article below that made more sense to me this time and after working in this context:
http://css-tricks.com/the-difference-between-id-and-class/
thank you to all for your assistance!
html
<div id="wrapper">
<div id ="hbar_one"></div>
<div id="hbar_two"></div>
<div id="container_a">
<div id="container_b">
<div class="class1 class2 magic" data-unique-content=".hidden_db_data_div">
<img src="http://lorempixel.com/g/50/50/">
<div class="hidden_db_data_div">
some amazing html
</div>
</div>
<div class="class1 class2 magic" data-unique-content=".hidden_db_data_div">
<img src="http://lorempixel.com/g/50/50/">
<div class="hidden_db_data_div">
more amazing html
</div>
</div>
<div class="class1 class2 magic" data-unique-content=".hidden_db_data_div">
<img src="http://lorempixel.com/g/50/50/">
<div class="hidden_db_data_div">
even more amazing html
</div>
</div>
</div>
</div>
<div id="hbar_three"></div>
<div id="hbar_four"></div>
</div>
css
#wrapper {
width: 300px;
}
#hbar_one {
background: #cc0000;
height: 50px;
}
#hbar_two {
background: #ffcc00;
height: 50px;
}
#container_b {
height: 100px;
overflow-y: auto;
}
.hidden_db_data_div {
display: none;
background: #00AFF0;
width: 120px;
height: 150px;
color: red;
position:absolute;
overflow: hidden;
z-index: 999;
}
img {
width: 50px;
height: 50px;
}
.magic {
display: inline;
}
#container_a { position:relative; }
#hbar_three {
background: #cccccc;
height: 50px;
}
#hbar_four {
background: #000000;
height: 50px;
}
script
$(".magic").hover(
function () {
$(this)
.find('.hidden_db_data_div')
.css({'left':$(this).position().left+20 + "px", 'top':'-20px'})
.fadeIn(200);
},
function() {
$(this)
.find('.hidden_db_data_div')
.fadeOut(100);
}
);

Resources