Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS set baseline of inline-block element manually and have it take the expected height

Tags:

html

css

I'm designing a sea-sky component. I'd like to have it's baseline at sea-level.

Here's an attempt that's rendering correctly.

.out {
   display:inline-block;
   background-color:yellow;
   padding-bottom:30px; 
}

.outer {
   display:inline-block;
   background-color:cyan;
   width:100px;
   height:100px;
   position:relative;
   bottom:-30px ;
}

.inner {
  position:absolute;
  height:30px;
  background-color:blue;
  bottom:0px;
  width:100%;
}
<div class="out">hello<div class="outer"><div class="inner">
</div></div>foobar</div>

The trick here is to set a negative bottom and use a padding to have the .out bottom at the expected position. Here's what happens without the padding.

.out {
   display:inline-block;
   background-color:yellow;
}

.outer {
   display:inline-block;
   background-color:cyan;
   width:100px;
   height:100px;
   position:relative;
   bottom:-30px ;
}

.inner {
  position:absolute;
  height:30px;
  background-color:blue;
  bottom:0px;
  width:100%;
}
<div class="out">hello<div class="outer"><div class="inner">
</div></div>foobar</div>

However, using multiple such component would require setting the padding to the max of all the bottom of the components which are on the last line. This is not feasible.

Is there a way to do without the padding-bottom ?

like image 245
Gzorg Avatar asked Nov 02 '25 18:11

Gzorg


1 Answers

The problem is that you use bottom: -30px. Yes, aligns the sea with the text, but breaks the layout.

Instead, you should take advantage of inline-blocks having a very interesting baseline:

The baseline of an 'inline-block' is the baseline of its last line box in the normal flow, unless it has either no in-flow line boxes or if its 'overflow' property has a computed value other than 'visible', in which case the baseline is the bottom margin edge.

That is, you only need to fill the sky part with some in-flow content. Since the sea part is already out-of-flow, it won't affect the baseline. Therefore, you can insert a pseudo-element is .outer which takes the remaining height left by .inner:

.outer::before {
  content: '';
  display: inline-block;
  height: calc(100% - 30px);
}

.out {
  display: inline-block;
  background-color: yellow;
}
.outer {
  display: inline-block;
  background-color: cyan;
  width: 100px;
  height: 100px;
  position: relative;
}
.outer::before {
  content: '';
  display: inline-block;
  height: calc(100% - 30px);
}
.inner {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 30px;
  background-color: blue;
}
<div class="out">
  hello
  <div class="outer">
    <div class="inner"></div>
  </div>
  foobar
</div>

To avoid that calc(100% - 30px) you can also use flexbox:

.outer {
  display: inline-flex;
  flex-direction: column;
}
.outer::before {
  flex: 1;
}

.out {
  display: inline-block;
  background-color: yellow;
}
.outer {
  display: inline-flex;
  flex-direction: column;
  background-color: cyan;
  width: 100px;
  height: 100px;
}
.outer::before {
  content: '';
  flex: 1;
}
.inner {
  height: 30px;
  background-color: blue;
}
<div class="out">
  hello
  <div class="outer">
    <div class="inner"></div>
  </div>
  foobar
</div>

But I think the CSS WG hasn't completely decided how baselines in orthogonal flows should behave, so I would recommend calc(100% - 30px) for now.

like image 172
Oriol Avatar answered Nov 05 '25 16:11

Oriol