ChatGPT解决这个技术问题 Extra ChatGPT

Align an element to bottom with flexbox

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.

Just give it postition: absolute; bottom 0; ?
@Jonathan the wrapper does not have a fixed height. If I take it out the flow it would overlap the text
@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 the default position of a div is static not relative.
I realize this is an old thread at this point, but Jonathan's suggestion should be renamed to position, not postition.

O
Oriol

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; }

heading 1

heading 2

Some text more or less

Click me

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; }

heading 1

heading 2

Some text more or less

Click me


For me, this works in Chrome, but not in Safari on iOS 10.2. Can anyone confirm?
@Oriol I like this approach, but not the side effect of losing collapsing margins, what would you do about this?
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; }
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;
"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 :)
T
TylerH

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


if you want it at the bottom, make sure to set the flex-direction to column.
What if I cannot provide the height?
What worked for me was just: ``` . content { display: flex; flex-direction: column; justify-content: flex-end; } ```
L
Liam

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:

https://i.stack.imgur.com/jSZfe.png

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; }

Lorem ipsum dolor s at mi imperdiet fringilla vitae id lorem. Donec ut semper sapien, et ullamcorper metu
Lorem ipsum dolor sit amet
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
Lorem ipsum dolor sit amet
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
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


T
Timo Ernst

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; }

heading 1

heading 2

paragraph text


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)
that's not the real result, it will have space between each item (hence the name)
@Barbz_YHOOL No, it works if you increase the container height (see updated example)
After searching a lot, this is just perfect! Thank you.
With a little modification, this answer worked perfectly for me, thank you
T
Tomas Vancoillie

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; }

heading 1

heading 2

Some more or less text


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%
S
Stanley Sathler

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;
}

S
Sanjay Shr

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.


position:fixed wouldn't work because then it wouldn't be relative to the container it is in. Perhaps you meant position:absolute?
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.
Updated answer.
A
Alok Jain
<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:

Change the height of .content as you need 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


a
aj go

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>

m
mohxn ayaz

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; }

heading 1

heading 2

Some more or less text

Click me