29

I wanted to set margin to auto plus some pixel amount using calc(), but my code doesn't seem to work.

selector {
    width: 200px;
    height: 200px;
    margin-left: auto;
    margin-right: auto;
    background: red;
    margin: calc(auto + 5px);
}
<div></div>

Can I set calc() to an automatic margin plus a fixed value? Something like this:

enter image description here

TylerH
  • 20,799
  • 66
  • 75
  • 101
Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231

3 Answers3

20

Looking at my own question today, I feel ashamed why I couldn't think it correctly? Basically, auto margin is what left margin 50% minus width of the div. In this basis, we can layout the element like this:

margin-left: calc(50% + 5px);
transform: translateX(-50%);

Using the preceding code is equivalent to calc(auto + 5px);. Since, calc doesn't support auto we need to trick with actual concept of translation. This means we can also layout with absolute position with the concept of 50% - half of width, but I like transform here for simplicity.

See the demo below:

.parent{
  position: relative;
}
.child{
  border: 2px solid green;
  width: 25%;
  height: 50px;
  margin: 10px auto;
}
.right{
  margin-left: calc(50% + 20px);
  transform: translateX(-50%);
}
.left{
  margin-left: calc(50% - 20px);
  transform: translateX(-50%);
}
#border{
  height: 100%;
  border: 1px solid yellow;
  width: 25%;
  margin: auto;
  position: absolute;
  z-index: -1;
  top: 0;
  left: 0;
  right: 0;
}
<div class="parent">
  <div id="auto" class="child">
    auto margin
  </div>
  <div id="auto-right" class="child right">
    auto + pushed to right
  </div>
  <div class="child left">
    auto + pushed to left
  </div>
  <div id="border"></div>
</div>

Increase or decrease the plus minus value of left and right to understand it correctly.

Note: using the below code

.right{
  margin-left: calc(50% + 20px);
  transform: translateX(-50%);
}

is same as using:

.right{
  margin-right: calc(50% - 20px);
  transform: translateX(-50%);
}

for this concept.

Also note that the question is related to some percentage calculation plus minus desired shift. So in this answer, it has both calc and transform is used. If you exactly require to shift at middle then we could just use (without margin-left or margin-right):

transform: translateX(-20px)

The answer is provided with 50% calc but the question was requiring to use some percentage like calc(20% - 20px).

Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231
17

From MDN :

The calc() CSS function can be used anywhere a <length>, <frequency>, <angle>, <time>, <number>, or <integer> is required. With calc(), you can perform calculations to determine CSS property values.

You cannot use auto there, as it's not a valid value for calc().

Grammar for calc()

term
  : unary_operator?
    [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* |
      TIME S* | FREQ S* ]
  | STRING S* | IDENT S* | URI S* | hexcolor | function | math
  ;

For more information, refer the Docs


As you commented that you want to center the div but you also want a 5px margin on the right than you can achieve it by using text-align: center; on the parent element and make the child div elements to display: inline-block;

Demo

Output

enter image description here

div.wrap {
    text-align: center;
}

div.wrap div {
    display: inline-block;
    height: 100px;
    width: 100px;
    color: #fff;
}

div.wrap div.with_margin {

    margin-right: 5px;
    background: #f00;
}

div.wrap div.without_margin { 
    background: #000;
}
Mr. Alien
  • 153,751
  • 34
  • 298
  • 278
  • 2
    oh! there is function too. how can I use to make likely to auto + 5px? – Bhojendra Rauniyar Jan 22 '14 at 06:26
  • @C-link It doesn't make any sense, how it will be auto, when you are adding `5px` `margin` on the right? Can you show a representational way, of what you expect? – Mr. Alien Jan 22 '14 at 06:27
  • 2
    try to understand comparing these demos: http://jsfiddle.net/jP7mN/1/ http://jsfiddle.net/jP7mN/2/ . It will be set the margin-right 25% whatever the div width is but I wanted to behave like both side auto but plus some width margin from right side. – Bhojendra Rauniyar Jan 22 '14 at 06:36
-1

I just stumbled on this from a search. It seems a bit complicated though. Why not separating and have a div with margin auto and the element inside with a margin left? Like so:

HTML:

 <div class="centered">
   <div>Some sort of element here</div>
 </div>

CSS:

.centered {
  margin: auto;
 }
.centered:first-child {
  max-width: 100%;
  margin-left: -2%;
 }
Patrick_B
  • 1
  • 2