CSS width of div if other div exists - html

In the following HTML, I want to specify the width of .left only if there is .right div in the .wrapper, otherwise it should take the full width. For example, if there is .right div, then the width of the .left should be 300px, otherwise it should be 500px.
I think this can be done using the css + selector, but if I am not sure how can I apply on the .left.
<div class="wrapper">
<div class="left"></div>
<div class="right"></div>
</div>
.wrapper{
width: 500px;
}
.left{
width: 300px;
}
.right{
width: 200px;
}

You can use the :only-child selector
.left:only-child
{
width: 100%;
}
Example
If you don't want to use the :only-child selector you could try the following
.wrapper
{
width: 500px;
min-height: 50px;
}
.left {
overflow: hidden;
min-height: 50px;
border: 1px dashed #f00;
}
.right {
float: right;
width: 200px;
min-height: 50px;
border: 1px dashed #00f;
}
Example

Instead of using CSS for this, why not using the HTML file?
From your question it seems that you have different HMTL files/output. If you add different classes in the HTML files, you can target them directly in CSS:
<div class="wrapper">
<div class="left"></div>
<div class="right"></div>
</div>
and
<div class="wrapper">
<div class="full"></div>
</div>
You CSS would contain something like this:
.wrapper {
width: 500px;
}
.left {
width: 300px;
}
.right {
width: 200px;
}
.full {
/* Whatever is required for full width */
}
Much easier this way! (Assuming you can change the HTML files/output)

I'd go for Veger's solution as well if you control the HTML output.
If not, the + selector only works for the latter element, thus with .left + .right you can change the right div if the left div is present. It doesn't work the other way around.
If you know, you'll always have a left div, you might put the right div into the left div and have it float right with a width of 200px.

There is no way that CSS can detect if an element exists or not, it is only for the presentation of elements.
You can however use javascript to do this. I will show you a jQuery version of it:
You have an element:
<div id="one">
My diiiv.
</div>
And you want to do something if this element exists:
$.fn.exists = function(callback) {
var args = [].slice.call(arguments, 1);
if (this.length) {
callback.call(this, args);
}
return this;
};
This is a function that will determine if an element exists when it's called.
What you can do now is to test if any element exists:
$('div#one').exists(function() {
this.append('<p>I exist!</p>');
});
So if it does, you can augment the DOM in whichever way you want. CSS cannot do this, that's what javascript and its libraries are for :)
http://jsfiddle.net/5Q2Gm/

Related

How to adjust divs to decrease their size as you add new sister divs?

I need a parent div to occupy the entire width of the screen and when adding child divs inside the parent div, the child divs will decrease the width so that they all fit inside the parent div without having scrool.
Equal behavior of browsers when adding new tabs.tabs
Just use display: flex; on the container. The default flex-shrink will handle the rest:
document.querySelector('button').addEventListener('click', function() {
const div = document.createElement("div");
document.querySelector('.container').appendChild(div);
});
.container {
display: flex;
}
/* for visualization only */
.container {
border: 2px dashed red;
height: 50px;
}
.container > div {
width: 100px;
border: 3px solid blue;
}
<div class="container"></div>
<button>Click me to add an Element</button>
One easy way to do this is with display: table. It works in current modern browsers.
#wrapper {
display: table;
table-layout: fixed;
width: 100%;
height: 100px;
}
#wrapper div {
display: table-cell;
height: 100px;
}
#one {
background-color:green
}
#two {
background-color:blue
}
#three {
background-color:red
}
<div id="wrapper">
<div id="one">one one one one one one one one one one one one one one one one one one one one one</div>
<div id="two">two two two two two two</div>
<div id="three">three</div>
</div>
Example : http://jsfiddle.net/dokve351/
You can try
.parent{
display : flex-shrink;
}
.child{
width : auto
max-width : 100px;
min-width : 10%;
}
Thats with basic CSS, if you are using React there will be an easier code.

Make a div with two widths

I have two divs next to each other. The div on the right is 300px x 335px. The div on the left goes all the way down the page. I want the width of the left div to go all the way until the right div. Then under the right div, it takes up the whole width of the page. Is this possible?
div elements are block level elements. So they are like square blocks. No, they can't work as you ask. However, you might Google for CSS Shapes to see if it can do what you wish but it's not available in all browsers and still isn't exactly the same as you request.
Here is some option either you can add min-width to the short div and long div to extend it. or you can add a background-color body to fake the illusion of it. but like Rob said there is no good way that can work out.
.short {
width: 100px; height: 100px;
background:red;
float:left;
//min-height: 500px;
}
.long {
width: 100px; height: 500px;
background:blue;
float:left;
//min-height: 500px;
}
.width {
width: 100%;
height: 200px;
background:yellow;
}
.clearfix {
overflow: auto;
zoom: 1;
}
body {
// background-color: red;
}
<div class="clearfix">
<div class="short"></div>
<div class="long"></div>
</div>
<div class="width"></div>
That is not possible, although you could always put another div under the one on the right and set the margin so that it looks like it's part of the one on the left.
This is one of the method to achieve what you want
CSS
#left1 {
margin-right: 300px;
height: 335px;
background: #aaa;
}
#right {
width: 300px;
height: 335px;
float: right;
}
#left2 {
background: #aaa;
border: 1px soild #000;
min-height: 300px;
}
<div id="right"></div>
<div id="left1"></div>
<div id="left2"></div>

How do i make this layout in css, divs are collapsing

JsFiddle: http://jsfiddle.net/techsin/csfvb91u/
(just realized normal div is collapsing ALSO to size of content, is min height completely useless?)
I need two divs, one left, and on right. Left one is 100px wide and stays that way. While, right div expands infinitely and doesn't shrink beyond 400px. Both Divs should be the height of parent. And parent has no exact height but minimum height of 800. So if content of one of these 2 divs were to push the height of div and extend it. Then The height of parent should increase and thus also the height of other div.
I tried using floats. I managed to some extent. However left side which was on float left, its height kept collapsing and didn't follow height:100% rule. It only worked if parent had definite width.
I tried using inline block but then right div won't expand to fillin the available space..
Why in the world css doesn't have fit-content, fill-available, choose what % refers to, choose what to position against, use vector or use pngs to shape div, inset textshadow, etc.
<div class="cont">
<div class="a"></div>
<div class="b"></div>
</div>
try with display:table and display:table-cell for child you will need to give fixed with for the left div
demo - http://jsfiddle.net/z90fma6e/
html,
body {
height: 100%;
}
* {
margin: 0;
padding: 0;
}
.cont {
display: table;
height: 100%;
}
.left,
.right {
height: 100%;
}
.left {
width: 200px;
background: red;
display: block;
}
.right {
width: 100%;
display: table-cell;
background: green;
}
<div class="cont">
<div class="left">fixed
<br/>height adjusts</div>
<div class="right">expands
<br/>height adjusts</div>
</div>
Sounds like your divs are collapsing. Your going to need a clearfix you can add to divs. There are a few ways to do this; however, this option is best.
.clearfix:after {
content: ".";
visibility: hidden;
display: block;
height: 0;
clear: both;
}
Add this clearfix class and css to your divs so they wont collapse.
You can read more about them at cssTricks
perfect use case for CSS flex layout:
<style>
body {
display: flex;
flex-direction: row;
margin: 0;
padding: 0;
}
div:first-child {
width: 200px;
background: red;
}
div:last-child {
flex: 1;
background: blue;
}
</style>
<div></div>
<div></div>
If you wish to support IE8 or earlier I would suggest you to use positioning:
Here's what I came up with
Fiddle : http://jsfiddle.net/csfvb91u/4/
If the content on the right is going out of the container, you can always use margin-right:200px as the right side container is shifted 200px using left:200px. Hope you get what I'm saying... :)
HTML:
<div class="cont">
<div class="a"></div>
<div class="b"></div>
</div>
CSS:
.a {
position:absolute;
width: 200px;
background-color: green;
height: 100%;
}
.b {
width:100%;
position:absolute;
left:200px;
background-color: blue;
height: 100%;
}
.cont {
position:relative;
border:1px solid #333;
min-height:300px;
overflow:hidden;
}

Textarea CSS {height: 100%} in table-cell div (IE)

NOTE: This is only an issue in IE.
How can a force the textarea to vertically fill the table-cell div? I have applied height: 100% to all the parent elements, but the textarea still maintains its default height.
Screenshot:
Example of my problem: JSFiddle
Example code:
HTML
<div class="table">
<div class="row">
<div class="col col-sm">
<div class="thumbnail">Thumbnail</div>
</div>
<div class="col col-lg">
<textarea>Text area</textarea>
</div>
</div>
</div>
CSS
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.table {
display: table;
width: 100%;
height: 100%;
}
.row {
display: table-row;
height: 100%;
}
.col {
display: table-cell;
border: 1px dashed #FF0000;
padding: 5px;
vertical-align: top;
height: 100%;
}
.col-sm {
width: 30%;
}
.col-lg {
width: 70%;
}
.thumbnail {
height: 150px;
width: 200px;
border: 1px solid #CCC;
}
textarea {
width: 100%;
height: 100%;
}
According to this article, you'll see that what you're looking to do is impossible using a table-cell construction. Here's a fiddle demonstrating what happens when you remove all the height CSS. Spoiler alert: nothing happens, because none of your height tags have a value.
http://jsfiddle.net/py4gs/14/
Height/width CSS percentages are based off the closest parent with a defined height or width, excluding display: table* elements. In your case above, no such element exists, so none of the height tags have an effect.
I have encased your code in a body tag which has a defined width even though it is still relatively positioned. This is achieved by using an absolute positioning:
body {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
Fiddle: http://jsfiddle.net/py4gs/12/
As you can see, the textarea fills the container now. This is because your table has a height and all the other elements compute their height off of the table height.
Unfortunately, this solution is probably suboptimal for you, since it wouldn't work for multiple rows. There is no CSS-only solution for propagating the CSS computed height as the CSS actual height of a sibling in IE. You will need a height attribute defined on a parent and you can then propagate that down to the child.
There are options though. If it is absolutely necessary that the textarea be the same size of the thumbnail element, and the thumbnail height is indeed variable, then you can hook into a render event on your page (such as $(document).ready()) to grab the computed height and set this as the actual height:
$(document).ready(function() {
// avoid layout thrashing! read then write!
var heights = $('row').map(function(row) { return $(row).height(); });
$('row').each(function(i, el) {
$(el).height(heights[i]);
});
});
However, I'm a fan of non-jquery solutions. Therfore, I think the best solution might be to reconsider your layout. Use what you know about the thumbnail element to set the row height in advance or scale your thumbnail element. For example, if you are embedding a YouTube video as your thumbnail, you can scale the max-height of the iframe to 100% and manually set the row height to, say, 200px. If instead you are embedding an image, you could use CSS to scale the max-height and max-width of your image, which will respect aspect ratio (but is relatively computationally intensive), or you could preprocess your images and scale them to a desired height.
Unfortunately looks like IE doesn't support the CSS resize property, and thus cannot resize the textarea vertically. Might have to use a shim, like the answer here:
https://stackoverflow.com/a/9763121/2612012
EDIT this may or may not work, but you can try this:
$(document).ready(function() {
$('textarea').parent().resize(function() {
var $t = $(this);
$t.find('textarea').height($t.height());
}).resize();
});
jsfiddle
.col {
display: table-cell;
border: 1px dashed #FF0000;
padding: 5px;
vertical-align: top;
height:10px;
}
or you can give fixed height to the parent container (.table) which will automatically give full height to its children if set 100%
jsfiddle
.table {
display: table;
width: 100%;
height: 150px;
}
jsfiddle
<div class="col col-lg">
<div contenteditable='true' class='contenteditable'>Text area</div>
</div>
.contenteditable {
width: 100%;
height: 100%;
}
.contenteditable p{margin-top:0px; margin-bottom:0px;}
Since the size of the textarea is a percentage of the page (which changes responsively), I have coupled jQuery and the HTML rows attribute to create a temporary hack. The ratio is calculated based on what I know about the page size and percentages.
$(window).resize(function(){
var padding = 82;
var ratio = 0.009;
var rows = Math.floor(($('.main-container').width()-padding)*ratio);
$('.text-area').attr('rows',rows);
}).resize();
For those who may not want to use the great but as yet not fully supported css table properties, You can also do this. Should be browser-friendly, but I only tested in FireFox, IE and SlimJet. Multiple rows work fine. I set the text area at 90% for demonstration.
(Not sure what the goal is here - perhaps multiple images on the left and one big textarea - but this should work for that also.)
jsfiddle: https://jsfiddle.net/RationalRabbit/wpsqx8kh/7/
HTML:
<body>
<div class="table">
<div class="row">
<div class="col col-sm">
<div class="thumbnail">Thumbnail</div>
</div>
<div class="col col-lg">
<textarea>Text area</textarea>
</div>
</div>
<div class="row">
<div class="col col-sm">
<div class="thumbnail">Thumbnail 2</div>
</div>
<div class="col col-lg">
<textarea>Text area 2</textarea>
</div>
</div>
</div>
</body>
CSS:
* {
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}
.table {
width:500px;
height:100%px;
border:1px dashed blue;
}
.row {
height:200px;
}
.col {
float:left;
border:1px dashed #FF0000;
padding:5px;
vertical-align:top;
height:100%;
}
.col-sm {
width:30%;
}
.col-lg {
width:70%;
height:90%;
}
.thumbnail {
height:150px;
width:100%;
border:1px solid green;
}
textarea {
height:100%;
width:100%;
}
The easiest solution for me was to do it like this:
td{
position:relative;
}
textarea{
position:absolute;
top:0;
bottom:0;
left:0;
right:0;
}

Basic CSS positioning (fitting children in container)

Very basic CSS question. Given the code shown in http://jsfiddle.net/danwoods/65X7X/ why don't the child divs (the colored blocks) fit into the container element?
CSS from fiddle
.container {
width: 360px;
height: 50px;
border: 1px solid black;
}
.container div {
width: 120px;
height: 100%;
display: inline-block;
}
.one {
background: blue;
}
.two {
background: green;
}
.three {
background: red;
}
Thanks in advance,
Dan
Because inline elements are sensitive to white space. You can remove them so the HTML looks like:
<div class="container">
<div class="one"></div><div class="two"></div><div class="three"></div>
</div>
jsFiddle example
Or float the divs left:
.one,.two,.three {
float:left;
}
jsFiddle example
Or use HTML comments to eat up the white space:
<div class="container">
<div class="one"></div><!--
--><div class="two"></div><!--
--><div class="three"></div>
</div>
jsFiddle example
You have to float them left:
http://jsfiddle.net/65X7X/2/
.container div {
width: 120px;
height: 100%;
display: inline-block;
float: left;
}
Hope this helps.
Its not a bug. You can see here why it happens and how you can overcome the problem.
http://css-tricks.com/fighting-the-space-between-inline-block-elements/
While putting literally no spaces between the divs in your code, or using HTML comments both work equally well, there is a better solution. In my opinion, the most elegant solution, by which I mean the way which does not involve having to mess up the look and readability of your code, is to add this line of CSS:
body>.container{font-size:0;}
If your body tag is not the parent of .container, replace body with whatever the parent is. This line basically says that the styles will apply to the .container class, but only that specific class. Not the child elements of .container. So by applying a font size of 0, you eliminate the gaps made by it, thereby bringing everything into alignment.
http://jsfiddle.net/65X7X/6/