CSS Calc alternative
CssCss CalcCss Problem Overview
I am trying to dynamicly change the width of a div using CSS and no jquery. The following code will work in the following browsers: http://caniuse.com/calc
/* Firefox */
width: -moz-calc(100% - 500px);
/* WebKit */
width: -webkit-calc(100% - 500px);
/* Opera */
width: -o-calc(100% - 500px);
/* Standard */
width: calc(100% - 500px);
I want also support IE 5.5 and higher, i found the following: expression. Is this the correct usage:
/* IE-OLD */
width: expression(100% - 500px);
Can I also support Opera and the Android browser?
Css Solutions
Solution 1 - Css
Almost always box-sizing: border-box
can replace a calc rule such as calc(100% - 500px)
used for layout.
For example:
If I have the following markup:
<div class="sideBar">sideBar</div>
<div class="content">content</div>
Instead of doing this: (Assuming that the sidebar is 300px wide)
.content {
width: calc(100% - 300px);
}
Do this:
.sideBar {
position: absolute;
top:0;
left:0;
width: 300px;
}
.content {
padding-left: 300px;
width: 100%;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
* {
margin: 0;
padding: 0;
}
html,
body,
div {
height: 100%;
}
.sideBar {
position: absolute;
top: 0;
left: 0;
width: 300px;
background: orange;
}
.content {
padding-left: 300px;
width: 100%;
-moz-box-sizing: border-box;
box-sizing: border-box;
background: wheat;
}
<div class="sideBar">sideBar</div>
<div class="content">content</div>
PS: I won't work in IE 5.5 (hahahaha) , but it will work in IE8+ , all mobile, and all modern browsers (caniuse)
I just found this post from Paul Irish's blog where he also shows off box-sizing as a possible alternative for simple calc() expressions: (bold is mine)
> One of my favorite use-cases that border-box solves well is columns. I > might want to divide up my grid with 50% or 20% columns, but want to > add padding via px or em. Without CSS’s upcoming calc() this is > impossible… unless you use border-box.
NB: The above technique does indeed look the same as would a corresponding calc() statement. There is a difference though. When using a calc() rule the value of the width of the content div will actually be 100% - width of fixed div
, however with the above technique, the actual width of the content div is the full 100% width, yet it has the appearance of 'filling up' the remaining width. (which is probably good enough for want most people need here)
That said, if it is important that the content div's width is actually 100% - fixed div width
then a different technique - which makes use of block formatting contexts - may be used (see here and here for the gory details):
-
float the fixed width div
-
set
overflow:hidden
oroverflow:auto
on the content div
Demo
Solution 2 - Css
Just have a fallback before the calc will do the trick.
width: 98%; /* fallback for browsers without support for calc() */
width: calc(100% - 1em);
See more here https://developer.mozilla.org/en-US/docs/Web/CSS/calc
Solution 3 - Css
use this
.content
{
width: 100%;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding-right: 500px;
margin-right: -500px;
}
Solution 4 - Css
Just spent the best part of 3 hours trying to workaround this for a specific case on andriod devices, couldnt get box sizing to work so i've linked it into my JS as a dirty workaround... no jQuery required though! :)
Taken on working code on andriod 2.3.
<div class="sessionDiv" style="width:auto;">
<img> <!-- image to resize -->
</div>
<div class="sessionDiv" style="width:auto;">
<img> <!-- image to resize -->
</div>
JS with event listeners
var orient =
{
orientation:window.orientation,
width: window.innerWidth,
check: function()
{
// if orientation does not match stored value, update
if(window.orientation !== this.orientation)
{
this.orientation = window.orientation; //set new orientation
this.width = window.innerWidth; //set new width
this.adjustIrritatingCSS(this.width); //change ui to current value
}
//if width does not match stored value, update
if(window.innerWidth !== this.width)
{
this.width = window.innerWidth; //set new width
this.adjustIrritatingCSS(this.width); //change ui to current value
}
},
adjustIrritatingCSS: function(screenWidth)
{
//disgusting workaround function
var titleBoxes = document.getElementsByClassName('sessionDiv');
var i = titleBoxes.length;
var sessWidth = screenWidth - 300; // calc(100% - 300px); -> equivalent
while(i--)
{
titleBoxes[i].style.width = String( sessWidth + "px");
//resize image in auto sized div
}
sessWidth = null; //clear width
titleBoxes = null; //clear nodelist
i = null; // clear index int
}
};
window.onload = function()
{
window.addEventListener('resize', function(){orient.check();});
//on resize, check our values for updates and if theres changes run functions
window.addEventListener('orientationchange', function(){orient.check();});
//on rotate, check our values for updates and if theres changes run functions
setInterval(function(){orient.check();}, 2000);
//occasionally check our values for updates and if theres changes run functions(just incase!!)
orient.adjustIrritatingCSS(orient.width);
//sets value on first run
};
Hope this helps anyone who cant get the box-sizing working! PS I have experienced problems with ios using this...
Solution 5 - Css
Change #menuLog width with % or px and you will see magic. Works with every device even < 2.3
*{
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
#menuLog{
width:30%;
/*width:300px;*/
height: 60px;
padding: 5px;
background-color: #ddd;
}
#menuLog > div[inline-log="1"]{
display: inline-block;
vertical-align: top;
width: 100%;
height: 100%;
margin-right: -60px;
}
#menuLog > div[inline-log="1"] > div[inline-log="1.1"]{
margin-right: 60px;
height: 100%;
background-color: red;
}
#menuLog > div[inline-log="2"]{
display: inline-block;
vertical-align: top;
width: 60px;
height: 100%;
}
#menuLog > div[inline-log="2"] > div[inline-log="2.1"]{
display: inline-block;
vertical-align: top;
width: 55px;
height: 100%;
background-color: yellow;
margin-left:5px;
}
<div id="menuLog">
<div inline-log="1">
<div inline-log="1.1">
One
</div>
</div><div inline-log="2">
<div inline-log="2.1">
Two
</div>
</div>
</div>
Solution 6 - Css
I wanted to add the no-calc, no-border-box (i.e., CSS2) alternative.
Normal-flow block elements initially have width: auto
, which is effectively the width of the containing block minus the margin, border, and padding widths.
The example above can be done, without border-box, simply as
.content {
padding-left: 300px;
}
Similarly, with
.content {
margin-left: 1px;
border-left: 1em solid;
padding-left: 1rem;
}
the effective width is 100% - 1px - 1em - 1rem
.
For absolutely positioned elements, height: auto
has similar properties:
.content {
position: absolute;
top: 0;
bottom: 0;
margin-bottom: 1px;
border-bottom: 1em solid;
padding-bottom: 1rem;
}
Here the effective height is 100% - 1px - 1em - 1rem
.