703

I have a div with some children:

<div class="content">
  <h1>heading 1</h1>
  <h2>heading 2</h2>
  <p>Some more or less text</p>
  <a href="/" class="button">Click me</a>
</div>

and I want the following layout:

 -------------------
|heading 1          |
|heading 2          | 
|paragraph text     |
|can have many      |
|rows               |
|                   |
|                   |
|                   | 
|link-button        |
 -------------------

Regardless how much text is in the p I want to stick the .button always at the bottom without taking it out of the flow. I've heard this can be achievable with Flexbox but I can't get it to work.

6
  • 41
    @Jonathan the wrapper does not have a fixed height. If I take it out the flow it would overlap the text
    – supersize
    Commented Jun 23, 2015 at 11:13
  • 5
    @supersize old Q but you could have given the wrapper position:relative - it's goofy because I think it's relative by default but you have SET it in order for the child's absolute positioning to be contained. Then bottom:0 will fit flush.
    – Jacksonkr
    Commented Apr 26, 2019 at 19:56
  • Jacksonkr is right, this is the BEST solution, others are too long, too convoluted or not working the right way Commented Jun 23, 2019 at 16:17
  • 6
    @Jacksonkr the default position of a div is static not relative.
    – supersize
    Commented Jun 24, 2019 at 8:23
  • 3
    I realize this is an old thread at this point, but Jonathan's suggestion should be renamed to position, not postition. Commented Sep 27, 2020 at 7:58

12 Answers 12

1025

You can use auto margins

Prior to alignment via justify-content and align-self, any positive free space is distributed to auto margins in that dimension.

So you can use one of these (or both):

p { margin-bottom: auto; } /* Push following elements to the bottom */
a { margin-top: auto; } /* Push it and following elements to the bottom */

.content {
  height: 200px;
  border: 1px solid;
  display: flex;
  flex-direction: column;
}
h1, h2 {
  margin: 0;
}
a {
  margin-top: auto;
}
<div class="content">
  <h1>heading 1</h1>
  <h2>heading 2</h2>
  <p>Some text more or less</p>
  <a href="/" class="button">Click me</a>
</div>

Alternatively, you can make the element before the a grow to fill the available space:

p { flex-grow: 1; } /* Grow to fill available space */

.content {
  height: 200px;
  border: 1px solid;
  display: flex;
  flex-direction: column;
}
h1, h2 {
  margin: 0;
}
p {
  flex-grow: 1;
}
<div class="content">
  <h1>heading 1</h1>
  <h2>heading 2</h2>
  <p>Some text more or less</p>
  <a href="/" class="button">Click me</a>
</div>

9
  • 2
    For me, this works in Chrome, but not in Safari on iOS 10.2. Can anyone confirm?
    – Matthew
    Commented Dec 30, 2016 at 0:44
  • @Oriol I like this approach, but not the side effect of losing collapsing margins, what would you do about this?
    – Neil
    Commented Feb 13, 2017 at 10:20
  • 17
    flex-grow worked for me. Here's how I did it html { height: 100%; } body { min-height: 100%; display: flex; flex-direction: column; } #site-content { flex: 1; } Commented Mar 2, 2017 at 19:07
  • 11
    Also a side note, remember to height: 100% on the parent element of which you are trying to push something to bottom with margin-top: auto;
    – skolind
    Commented Aug 2, 2018 at 12:53
  • 2
    "any positive free space is distributed to auto margins in that dimension." it's little things like this that are so elegant, for me this solution was 2 lines of code based on your answer. thank you :)
    – danjah
    Commented Aug 7, 2018 at 12:29
218

You can use display: flex to position an element to the bottom, but I do not think you want to use flex in this case, as it will affect all of your elements.

To position an element to the bottom using flex try this:

.container {
  display: flex;
}

.button {
  align-self: flex-end;
}

Your best bet is to set position: absolute to the button and set it to bottom: 0, or you can place the button outside the container and use negative transform: translateY(-100%) to bring it in the container like this:

.content {
    height: 400px;
    background: #000;
    color: #fff;
}
.button {
    transform: translateY(-100%);
    display: inline-block;
}

Check this JSFiddle

3
  • 8
    if you want it at the bottom, make sure to set the flex-direction to column.
    – Viliami
    Commented Jan 14, 2017 at 3:34
  • 3
    What if I cannot provide the height?
    – Mark
    Commented May 17, 2018 at 9:43
  • What worked for me was just: ``` . content { display: flex; flex-direction: column; justify-content: flex-end; } <div class="content"><a class="bottom">Something</a></div> ``` Commented Jan 16, 2019 at 17:48
178

1. Style parent element: style="display:flex; flex-direction:column; flex:1;"

2. Style the element you want to stay at bottom: style="margin-top: auto;"

3. Done! Wow. That was easy.

Example:

enter image description here

section {
  /* ONLY FOR DEMO, NOT NECESSARY */
  display: flex;
  flex-wrap: wrap;
}

div {
  /* PARENT ELEMENT */
  display: flex;
  flex-direction: column;
  flex: 1;
}

button {
  /* TARGET ELEMENT */
  margin-top: auto;
}

/* DECORATIVE STYLES FOR DEMO */

button {
  font-size: 20px;
  background-color: crimson;
  color: white;
  border-style: none;
  border-radius: 3px;
}

section {
  margin: 0;
  padding: 0;
  border: 1px solid black;
  background-color: crimson;
}

div {
  font-size: 20px;
  background-color: khaki;
  border: 2px dashed black;
  margin: 10px;
  padding: 10px;
  min-width: 400px;
  min-height: 300px;
}
<section>
  <div>
    <span>Lorem ipsum dolor s at mi imperdiet fringilla vitae id lorem. Donec ut semper sapien, et ullamcorper metu</span>
    <button>I</button>
  </div>
  <div>
    <span>Lorem ipsum dolor sit amet</span
    ><button>
      stay
    </button>
  </div>
  <div>
    <span
      >Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi at augue ac turpis fringilla egestas. quis mi diam. Quisque faucibus, massa non finibus iaculis, arcu nulla auctor enim, quis accumsan dolor odio quis turpis. Duis convallis pulvinar justo sit amet feugiat.
      Duis sed lectus at mi imperdiet fringilla vitae id lorem. Donec ut semper sapien, et ullamcorper metu</span
    >
    <button>
      at
    </button>
  </div>
  <div>
    <span>Lorem ipsum dolor sit amet</span
    ><button>
      bottom
    </button>
  </div>
  <div>
    <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi at augue ac turpis fringilla egestas. Donec quis mctus at mi imperdiet fringilla vitae id lorem. Donec ut semper sapien, et ullamcorper metu</span>
    <button>
      always
    </button>
  </div>
  <div>
    <span>Lorem ipsum dolor sit amet sit amet, consectetur adipiscing elit. Morbi at augue ac turpis fringilla egestas. Donec quis mctus at mi imperdiet fringilla vitae id lorem. Donec ut semper sapien, et ullamcorper</span
    ><button>
      all ways
    </button>
  </div>
</section>

1
  • The flex: 1 is not needed however this is the most clean flex-like solution. Plus for distinguishing between essential styles (that are needed to achieve desired effect) and visual styles to make the demo easy to understand). Commented Oct 15 at 10:24
105

The solution with align-self: flex-end; didn't work for me but this one did in case you want to use flex:

Result

 -------------------
|heading 1          |
|heading 2          | 
|paragraph text     |
|                   |
|                   |
|                   | 
|link button        |
 -------------------

Code

Note: When "running the code snippet" you have to scroll down to see the link at the bottom.

.content {
  display: flex;
  justify-content: space-between;
  flex-direction: column;
  height: 300px;
}

.content .upper {
  justify-content: normal;
}

/* Just to show container boundaries */
.content .upper, .content .bottom, .content .upper > * {
  border: 1px solid #ccc;
}
<div class="content">
  <div class="upper">
	  <h1>heading 1</h1>
	  <h2>heading 2</h2>
	  <p>paragraph text</p>
  </div>

  <div class="bottom">
	  <a href="/" class="button">link button</a>
  </div>
</div>

6
  • 2
    content is the column container it holds 2 other container, with justify-content: space-between; you tell the flexbox to push the container away from each other how much as possible (in this case limited by the height of the content container) Commented Mar 14, 2018 at 13:21
  • that's not the real result, it will have space between each item (hence the name) Commented Jun 23, 2019 at 16:08
  • 1
    @Barbz_YHOOL No, it works if you increase the container height (see updated example)
    – Timo Ernst
    Commented Jun 24, 2019 at 17:22
  • 1
    After searching a lot, this is just perfect! Thank you.
    – Rudy
    Commented Jun 27, 2019 at 12:25
  • 1
    With a little modification, this answer worked perfectly for me, thank you Commented Sep 28, 2019 at 14:44
18

When setting your display to flex, you could simply use the flex property to mark which content can grow and which content cannot.

Flex property

div.content {
 height: 300px;
 display: flex;
 flex-direction: column;
}

div.up {
  flex: 1;
}

div.down {
  flex: none;
}
<div class="content">
  <div class="up">
    <h1>heading 1</h1>
    <h2>heading 2</h2>
    <p>Some more or less text</p>
  </div>

  <div class="down">
    <a href="/" class="button">Click me</a>
  </div>
</div>

1
  • 3
    note to myself: Remember to set the height in the container. I was struggling and in my scenario all I was missing was to set height: 100%
    – RagnaRock
    Commented Jan 21, 2021 at 11:33
15

If it's fine to modify your HTML, you can wrap all your top elements in a separate div and then use justify-content: space-between.

Something like this:

<div class="content">
  <div>
    <h1>heading 1</h1>
    <h2>heading 2</h2>
    <p>Some more or less text</p>
  </div>
  <a href="/" class="button">Click me</a>
</div>
.content {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
6

Not sure about flexbox but you can do using the position property.

set parent div position: relative and child element which might be an <p> or <h1> etc.. set position: absolute and bottom: 0.

Example:

index.html

<div class="parent">
  <p>Child</p>
</div>

style.css

.parent {
  background: gray;
  width: 10%;
  height: 100px;    
  position: relative;
}
p {
  position: absolute;
  bottom: 0;
}

Code pen here.

3
  • 1
    position:fixed wouldn't work because then it wouldn't be relative to the container it is in. Perhaps you meant position:absolute?
    – Sensoray
    Commented Mar 20, 2018 at 17:38
  • 1
    While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. Commented Mar 20, 2018 at 22:32
  • 1
    Updated answer.
    – Sanjay Shr
    Commented Mar 21, 2018 at 7:30
4
<div class="content">
    <h1>heading 1</h1>
    <h2>heading 2</h2>
    <p>Some more or less text</p>
    <a href="/" class="button">Click me</a>
</div>

Notes for CSS:

  1. Change the height of .content as you need
  2. Button will take the whole empty area at the bottom because of the flex:1 property, making the whole area clickable. I will advise wrapping the button in a div or span

CSS

.content {
    display: flex;
    flex-direction: column;
    height: 100vh;
}

.button {
    display: flex;
    flex: 1;
    align-items: flex-end;
}

https://codepen.io/alokjain_lucky/pen/MWooJGw

1

I just found a solution for this.

for those who are not satisfied with the given answers can try this approach with flexbox

CSS

    .myFlexContainer {
        display: flex;
        width: 100%;
    }

    .myFlexChild {
        width: 100%;
        display: flex;

        /* 
         * set this property if this is set to column by other css class 
         *  that is used by your target element 
         */
        flex-direction: row;

        /* 
         * necessary for our goal 
         */
        flex-wrap: wrap;
        height: 500px;
    }

    /* the element you want to put at the bottom */
    .myTargetElement {
        /*
         * will not work unless flex-wrap is set to wrap and 
         * flex-direction is set to row
         */
        align-self: flex-end;
    }

HTML

    <div class="myFlexContainer">
        <div class="myFlexChild">
            <p>this is just sample</p>
            <a class="myTargetElement" href="#">set this to bottom</a>
        </div>
    </div>
0
<section>
  <div class="top">
    <div class="search-box">
         ... bla-bla-bla 
    </div>
    <div class="processing">
      Do something...
    </div>
  </div>

  <button class="select-lesson">
    Select Lesson
  </button>
</section>

CSS:

section {
display:flex;
flex-direction: column;
}

section {
  box-sizing: border-box;
  width: 100%;
  height: 400px;
  background: yellow;
  color: blue;
  padding: 1.8em;
  border-radius: 1.4em;
  font-family: 'Roboto', sans-serif;
  display: flex;
  margin: 25px 0;

 /* This line does the trick */ 
 justify-content: space-between;
}

.top {
  width: 100%;
}

button.select-lesson, .search-box {
  border-radius: 0.6em;
}

.search-box {
  padding: 1.6em 1.7em;
  background: #232323;
}

.search-box svg {
  display: block;
}

.processing {
  text-align: center;
  padding: 4.5em 0;
  font-size: 1.5em;
}

button.select-lesson {
  border: 0;
  width: 100%;
  background: #14274B;
  color: #9FB8EA;
  text-align: center;
  font-weight: bold;
  font-size: 1.5em;
  padding: 1.7rem;
}
-1

Try

content{
  display:flex; 
  flex-direction:column; 
  justify-items:space-between; 
  heigh:100vh
}
-2

Try This

.content {
      display: flex;
      flex-direction: column;
      height: 250px;
      width: 200px;
      border: solid;
      word-wrap: break-word;
    }

   .content h1 , .content h2 {
     margin-bottom: 0px;
    }

   .content p {
     flex: 1;
    }
   <div class="content">
  <h1>heading 1</h1>
  <h2>heading 2</h2>
  <p>Some more or less text</p>
  <a href="/" class="button">Click me</a>
</div>

Not the answer you're looking for? Browse other questions tagged or ask your own question.