0

There is a couple of fixed size inline blocks (material icons) that should be vertically positioned within a fluid block - one is in the middle, another is at the bottom.

Here's an example that explains this:

body {
  width: 100%;
}

.square-container {
  position: relative;
  padding-top: 100%;
  background: #999;
}

.square {
  position: absolute;
  left: 0;
  top: 0;
  width: 20%;
  height: 20%;
  background: #ddd;

  align-items: center;
  display: flex;
  flex-direction: column; 
  justify-content: space-between; 
}
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" type="text/css" rel="stylesheet">

<div class="square-container">
  <div class="square">
    <i class="material-icons">&nbsp;</i>
    <i class="material-icons icon-1">local_see</i>
    <i class="material-icons icon-2">grade</i>
  </div>
</div>

I'd like to address some issues here.

One is that it involves extra <i class="material-icons">&nbsp;</i> placeholder to make both icons stay in places.

Another one is that icons cannot use space efficiently when a container is small enough (a demo). It is desirable that two icons would make use of space occupied by the placeholder instead of overflowing.

How can this be done?

This is primarily flexbox question, but if the same layout can be reached without flexbox with same degree of flexibility, this would be good too.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • Possible duplicate of [Center and bottom-align flex items](https://stackoverflow.com/questions/36191516/center-and-bottom-align-flex-items) – Moher Sep 14 '17 at 20:28

2 Answers2

2

I would not use flex for this, but create a relative/absolute relationship between parent and child elements where the absolute elements can be positioned as desired within the relative parent - settings see below.

A "placeholder" element like in your code is not needed in this case.

Note that i used the vw unit for the width and height of the .square element to make it independent of the window height.

html, body {
  height: 100%;
}
.square-container {
  background: #999;
  height: 100%;
}
.square {
  position: relative;
  width: 20vw;
  height: 20vw;
  background: #ddd;
}
.icon-1 {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.icon-2 {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
}
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" type="text/css" rel="stylesheet">

<div class="square-container">
  <div class="square">
    <i class="material-icons icon-1">local_see</i>
    <i class="material-icons icon-2">grade</i>
  </div>
</div>

ADDED AFTER COMMENT:

There is a flexbox solution, too: Delete the content from the placeholder element and give it height: 1em and flex-shrink: 1;

body {
  width: 300px;
}

.square-container {
  position: relative;
  padding-top: 100%;
  background: #999;
}

.square {
  position: absolute;
  left: 0;
  top: 0;
  width: 20%;
  height: 20%;
  background: #ddd;
  align-items: center;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.placeholder {
  height: 1em;
  flex-shrink: 1;
}
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" type="text/css" rel="stylesheet">

<div class="square-container">
  <div class="square">
    <i class="material-icons placeholder"></i>
    <i class="material-icons icon-1">local_see</i>
    <i class="material-icons icon-2">grade</i>
  </div>
</div>
Johannes
  • 64,305
  • 18
  • 73
  • 130
  • Thanks, `transform` is the important part here, it gives the appropriate effect here and prevents overflowing. Still wonder if it's possible to achieve same effect with flexbox alone. – Estus Flask Sep 14 '17 at 20:43
  • please note the addition / second solution to my answer: there is a flexbox solution, too – Johannes Sep 14 '17 at 20:51
1

Hello See The Below code hope you are looking for this using flexbox only adding extra flex property

flex-wrap: wrap;
justify-content: space-around;
align-items: center;

body {
  width: 300px;
}

.square-container {

 display:flex;
  justify-content: flex-start;
   padding-top: 100%;
   background: #999;
   position: relative;
}

.square {
   
  position:absolute;
  left: 0;
  top: 0;
  width: 20%;
  height: 50%;
  background: #ddd;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  justify-content: space-around;
   align-items: center;
}
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" type="text/css" rel="stylesheet">

<div class="square-container">
      <div class="square">
        <i class="material-icons icon-1">local_see</i>
        <i class="material-icons icon-2">grade</i>
      </div>
    </div>
Asifuzzaman Redoy
  • 1,773
  • 1
  • 15
  • 30
  • Thanks. It results in wrapping on smaller container size http://plnkr.co/edit/SMoNfkk1Dc89Z9rV6KVY?p=preview Not exactly as I expected but this may work as well. – Estus Flask Sep 14 '17 at 20:50