3

I'm trying to get a handle on flex containers (from here -- Flexbox: center horizontally and vertically ) in order to create rows of radio buttons and their text in a larger DIV. So I have these classes ...

.flex-container {
    height: 100%;
    padding: 0;
    margin: 0;
    display: -webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    align-items: center;
    justify-content: center;
}
.row {
    width: auto;
    border: 1px solid blue;
}
.flex-item {
    padding: 5px;
    margin: 10px;
    line-height: 20px;
    color: black;
    font-weight: bold;
    font-size: 2em;
    text-align: center;
}

and applied it to these items ...

<div class="flex-container">
    <div class="row">
        <div class="flex-item">
          <img src="images/check.jpg" />
        </div>
        <div class="flex-item">
          <input type="radio" id="radio0" name="choice" ><span>Text1</span>
        </div>
    </div>
    <div class="row">
        <div class="flex-item">
          <img src="images/check.jpg" />
        </div>
        <div class="flex-item">
        <input type="radio" id="radio1" name="choice" ><span>Text2</span>
        </div>
    </div>
    ...
    <div class="row" id="feedback"></div>
    <div class="row">
        <input type="button" value="Submit" id="submitAnswer" />
    </div>
</div>

But oddly what the rows marked with the class "row" are not appearing as their own rows ...

enter image description here

What else do I need to adjust in my flex container to make the horizontal rows appear on separate lines?

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Dave
  • 15,639
  • 133
  • 442
  • 830
  • When you say horizontal rows on a different line I am guessing you mean above or below the boxs in which the elements stack vertically? And then I am guessing you also what the submit input element to wrap bellow as well? – JΛYDΞV Aug 28 '20 at 13:34
  • Yes, you have described it correctly, all rows stacked on top of each other and the Submit button on its own row at the bottom of the stack. – Dave Aug 28 '20 at 16:44
  • Okay, it looks like a couple people have tried but failed to deliver. The question is a little unclear, but understandable if you read the two comments above. Answering with 5 or 6 different mark up is basically answering 5 or 6 times and hoping one sticks. IMO that stratagy is counter productive to the stack community. I prefer CSS-Grid, but flex has its advantages. It should be fairly simple to give you a solid answer using flex-box. Gimme 15mins. – JΛYDΞV Aug 28 '20 at 19:53

5 Answers5

1

In a comment you asked, after I answered, how to get the 3 elements in a row using the first example, which is an example based off of the code you posted when asking your question. I updated the answer to reflect how to do it in both examples. The first I kept very very simple. The second I added a bit of JavaScript and style so you have a guide the you can reference when building your own layout. If you need any other updates, or if this is not exactly to the T what you wanted, let me know and Ill update it to reflect the best possible answer for your question.

  • 2020 AUGUST 28th

Sorry it took so long to get back to you bud. Before answering this I did some searching and reading on flex and found a bit of w3c.org documentation on the CSS Flex Property that hits right on the subject your asking about, 'how to wrap items a certain way', it even has an example that creates a layout like the one you are asking for.

W3C in my opinion is the only site devs can trust 100%.

To touch on the code example you provided us with. Your code was 100% right, at least as far as achieving the layout you desired. It wasn't so much a matter of what was wrong in your code, as much as it was a matter of what was the code was missing or did not have, that it needed in-order to produce the desired layout in the browser, and the good news is, it only needed a single line of code added. You were off by one CSS property. CSS-Property 'Flex-Flow' was not placed inside the style-sheet's flex-container class. Resulting in the property being set to its default value 'row'. Having changed it to column, it would have produced the result you were looking for, changing the entire layout of the page.

  • This is what your flex-container class was missing:
    flex-flow: column;

Below are two examples, the first is what your code looks like, cleaned up and fixed using the flex-flow property. The second is a simple HTML/CSS document pair consisting of the way I would go about it. I created one to post an example of using flex in a way the clean precise manner that expresses web standards to the best of my ability.

    .flex-container {
            flex-flow: column;
            height: 100%;
            padding: 0;
            margin: 0;
            display: -webkit-box;
            display: -moz-box;
            display: -ms-flexbox;
            display: -webkit-flex;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .row {
            display: flex;
            flex-flow: row;
            flex-wrap: nowrap;
            align-items: center;
            justify-content: center;
            width: 250px;
            height: 50px;
            margin: 4px;
            padding: 12px;
            border: 1px solid blue;
            font-size: 20px;
            font-weight: 800;
            font-family: Verdana, sans-serif, sans-serif;
            color: #048;
        }

        .row div.a {
            width: auto;
        }

        .row div.b {
            width: auto;
            margin: 7%;
        }

        .row div.c {
            display: flex;
            width: auto;
        }

        i.fa-check {
            display: inline-block;
            color: #c33;
            font-size: 48px;
        }
    
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <script src="https://kit.fontawesome.com/3d9b68708a.js" crossorigin="anonymous"></script>
</head>

<body>

    <div class="flex-container">
        <div class="row">
            <div class="a"><i class="fas fa-check"></i></div>
            <div class="b"><input type="radio" id="radio0" name="choice"></div>
            <div class="c">SUM TEXT</div>
        </div>

        <div class="row">
            <div class="a"><i class="fas fa-check"></i></div>
            <div class="b"><input type="radio" id="radio0" name="choice"></div>
            <div class="c">SUM TEXT</div>
        </div>

        <input type="button" value="Submit" id="submitAnswer" />
    </div>
</body>

</html>
  • Here is the way I would do it personally. This way could easily be made responsive by using @media queries to change the display and flex-flow properties.

        function toggleCheck(id) {
            if (document.getElementById('cbox-' + id).checked) {
                document.getElementById('cm-' + id).style.display = 'inline';
            } else if (!document.getElementById('cbox-' + id).checked) {
                document.getElementById('cm-' + id).style.display = 'none';
            }
        }

        function setCheck() {
            toggleCheck('alpha');
            toggleCheck('beta');
            toggleCheck('gamma');
            toggleCheck('delta');
        }

        window.onload = () => { setCheck(); };
    
/*______________________________________
*  CSS DOCUMENT: STACKOVERFLOW_CSS 
*  DATE CREATED: 2020 - AUGUST - 28th
*  CREATED BY:  SO User, Aft3rL1f3
----------------------------------------*/

@import url('https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap');

body {
    width: 100vw;
    margin: 0;
    padding: 0;
    background-color: #d4d4d4;
}

i.fa-check {
    display: none;
    color: #c33;
    font-size: 42px;
}

input[type='submit'] {
    width: 112px;
    margin: 12px;
    padding: 6px;
    font-family: 'Lucida Sans Unicode' Arial, sans-serif;
    font-weight: 600;
    font-size: 19px;
    color: #1fc;
    border: 4px outset #1de;
    background-color: #026;
    border-radius: 7px;
}

form.flex-container {
    display: flex;
    flex-flow: column;
    margin: 12px;
    background: #f8f8e8;
    border: 2px dotted #bbb;
    align-items: center;
}

.flex-row {
    display: flex;
    flex-flow: nowrap;
    margin: 2px 0;
    padding: 8px;
    background-color: #e0ffe0;
    border: 1px dashed #bbb;
    align-items: center;
}

.box {
    display: flex;
    flex-wrap: nowrap;
    margin: 0 5px;
    width: 200px;
    padding: 12px 8px;
    line-height: 40px;
    text-align: center;
    border: 1px solid #04a;
    border-radius: 6px;
    background-color: #e8e8ff;
    color: #04a;
    font-size: 26px;
    font-family: 'Kalam', sans-serif;
    font-weight: 600;
}

div.box .a {
    height: 48px;
    width: 30%;
    margin: 0;
}

div.box .b {
    height: 48px;
    width: 20%;
    margin: 0;
}

div.box .c {
    height: 48px;
    width: 50%;
    margin: 0;
}
<!DOCTYPE html>
<html lang="en">

<head>
    <!--
<-------------------------------------------~>
  >> HTML DOCUMENT: STACKOVERFLOW_HTML
  >> DATE CREATED: 2020 - AUGUST - 28th
  >> UPDATED ON: 2020 - AUGUST - 29th
  >> CREATED BY: SO User Aft3rL1f3
<-------------------------------------------->
    <meta charset="UTF-8">
    <meta name="viewport"
        content="width=device-width, initial-scale=1.0">
    <script src="https://kit.fontawesome.com/3d9b68708a.js" crossorigin="anonymous"></script>
    <link rel="stylesheet" type="text/css" href="/style/so.css">
</head>

<body>

    <form class="flex-container" action="/process-form.php" method="post">
        <div class="flex-row">


            <!----( Box Alpha )---->
            <div id='alpha' class="box">
                <div class="a"><i id="cm-alpha" class="fas fa-check"></i></div>

                <div onclick="toggleCheck('alpha')" class="b">
                    <input id="cbox-alpha" name="alpha" type="checkbox">
                </div>

                <div class="c"> ALPHA </div>
            </div>


            <!----( Box Beta )---->
            <div id='beta' class="box">
                <div class="a"><i id="cm-beta" class="fas fa-check"></i></div>

                <div onclick="toggleCheck('beta')" class="b">
                    <input id="cbox-beta" name="beta" type="checkbox">
                </div>

                <div class="c"> BETA </div>
            </div>


        </div>
        <div class="flex-row">


            <!----( Box Gamma )---->
            <div id='gamma' class="box">
                <div class="a"><i id="cm-gamma" class="fas fa-check"></i></div>

                <div onclick="toggleCheck('gamma')" class="b">
                    <input id="cbox-gamma" name="gamma" type="checkbox">
                </div>

                <div class="c"> GAMMA </div>
            </div>


            <!----( Box Delta )---->
            <div id='delta' class="box">
                <div class="a"><i id="cm-delta" class="fas fa-check"></i></div>

                <div onclick="toggleCheck('delta')" class="b">
                    <input id="cbox-delta" name="delta" type="checkbox">
                </div>
                <div class="c">DELTA</div>
            </div>

        </div>

      <input type="submit" value="SUBMIT">
    </form>

</body>
</html>
JΛYDΞV
  • 8,532
  • 3
  • 51
  • 77
  • Thanks so much for taking the time and getting back with me. So I think I'm almost there. On your first solution how would I arrange things such that the check mark graphic appears to the left of the radio button and the "Text" sections? That is, the row would contain checkmark, radio button, and then "Text" all the in the same horizontal plane? – Dave Aug 29 '20 at 15:58
  • When items stack over each other its for 1 of three reasons, the first you should always check what the display properties of the elements are. If an element is a block it it will take up its own row of space across the entire container its in, if its set to inline or inline block then it will stack next to other inline elements. The next thing to check is if there are any
    elements in the HTML Documents. BR = break, and creates a break in the page. Lastly check to make sure the element isn't wrapping because the container is not big enough to hold all the elements on the row.
    – JΛYDΞV Aug 29 '20 at 18:55
  • Im going to edit my answer to adjust the boxes with all three elements in a row – JΛYDΞV Aug 29 '20 at 19:29
  • I upgraded the answer, and changed the bottom example that I created. I kinda went all out and added the js necessary to make the elements functional. As far as I can tell this is what you were looking for, if not let me know, I honestly don't mind helping other people. Also I don't want to offer you somthing unhelpful, so like I said let me know if it helps, and also if somthing isn't helpful. – JΛYDΞV Aug 29 '20 at 23:05
  • I didn't notice you specified the first example when asking for a solution, I updated the second initially, however; I went back and updated the first too now. The first will probably be more helpful thinking about it, because it is simple, yet it holds the answer, perfect for learning. – JΛYDΞV Aug 30 '20 at 00:21
0

Can you provide a screenshot of the desired output, please? Also, I was able to achieve this result by making few changes am not sure if this is the result you wanted... But I hope it can be of any help.

enter image description here

.flex-container {
  height: 100%;
  padding: 0;
  margin: 0;
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  align-items: center;
  justify-content: center;
}

.row {
  width: auto;
}

.flex-item {
  margin: 10px 30px;
  padding: 5px;
  line-height: 36px;
  color: black;
  font-weight: bold;
  font-size: 2em;
  text-align: center;
  align-items: center;
}

.flex-item img {
  display: block;
  margin: 0 auto;
}

.second-flex {
  display: flex;
}
<div class="flex-container">
  <div class="row">
    <div class="flex-item">
      <img src="https://picsum.photos/40" />
    </div>
    <div class="flex-item">
      <input type="radio" id="radio0" name="choice"><span>Text1</span>
    </div>
  </div>
  <div class="row second-flex">
    <div class="flex-item">
      <img src="https://picsum.photos/40" />
    </div>
    <div class="flex-item">
      <input type="radio" id="radio1" name="choice"><span>Text2</span>
    </div>
  </div>
  <div class="row">
    <input type="button" value="Submit" id="submitAnswer" />
  </div>
</div>

Is this the result you are looking for? if not please provide me an image and I will adjust the code according to it. And I will try my best to help you out.

Edited result2

So to make them appear on a different row give the .flex-item class the following properties. display: flex; flex-direction: column; I left the .flex-item with the **text2** as it is so you can see the difference between them.

PS: you can download an extension called Pesticide for Chrome it will draw an outline for each element on the page it makes designing easier.

**

EDITED

** Ok, So which one do you really want from these? Option one:

result1

CSS:

.flex-container {
    height: 100%;
    padding: 0;
    margin: 0;
    display: -webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
}

.row {
    width: auto;
}

.flex-item {
    margin: 10px 30px;
    padding: 5px;
    line-height: 36px;
    color: black;
    font-weight: bold;
    font-size: 2em;
    text-align: center;
    align-items: center;
}

.flex-item img {
    display: block;
    margin: 0 auto;
}

.second-flex {
    display: flex;
}

HTML:

<div class="flex-container">
        <div class="row">
            <div class="flex-item">
                <img src="assets/images/image.jpg" height="40" />
            </div>
            <div class="flex-item third-flex">
                <input type="radio" id="radio0" name="choice"><span>Text1</span>
            </div>
        </div>
        <div class="row second-flex">
            <div class="flex-item">
                <img src="assets/images/image.jpg" height="40" />
            </div>
            <div class="flex-item">
                <input type="radio" id="radio1" name="choice"><span>Text2</span>
            </div>
        </div>
        <div class="row">
            <input type="button" value="Submit" id="submitAnswer" />
        </div>
    </div>

Option Two: result22

It has the same CSS as option one. HTML changes:

<div class="flex-container">
        <div class="row second-flex">
            <div class="flex-item">
                <img src="assets/images/image.jpg" height="40" />
            </div>
            <div class="flex-item third-flex">
                <input type="radio" id="radio0" name="choice"><span>Text1</span>
            </div>
        </div>
        <div class="row second-flex">
            <div class="flex-item">
                <img src="assets/images/image.jpg" height="40" />
            </div>
            <div class="flex-item">
                <input type="radio" id="radio1" name="choice"><span>Text2</span>
            </div>
        </div>
        <div class="row">
            <input type="button" value="Submit" id="submitAnswer" />
        </div>
    </div>

Option three:

result33

This one has the same HTML and CSS as option 2 but with a small change in CSS

.flex-container {
    height: 100%;
    padding: 0;
    margin: 0;
    display: -webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    align-items: center;
    justify-content: center;
    /* flex-direction: column; remove this line */ 
}

option four:

enter image description here

HTML:

 <div class="flex-container">
        <div class="row ">
            <div class="flex-item">
                <img src="assets/images/image.jpg" height="40" />
            </div>
            <div class="flex-item third-flex">
                <input type="radio" id="radio0" name="choice"><span>Text1</span>
            </div>
        </div>
        <div class="row ">
            <div class="flex-item">
                <img src="assets/images/image.jpg" height="40" />
            </div>
            <div class="flex-item">
                <input type="radio" id="radio1" name="choice"><span>Text2</span>
            </div>
        </div>
        <div class="row">
            <input type="button" value="Submit" id="submitAnswer" />
        </div>
    </div>

CSS

.flex-container {
    height: 100%;
    padding: 0;
    margin: 0;
    display: -webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    align-items: center;
    justify-content: center;
}

.row {
    width: auto;
}

.flex-item {
    margin: 10px 30px;
    padding: 5px;
    line-height: 36px;
    color: black;
    font-weight: bold;
    font-size: 2em;
    text-align: center;
    align-items: center;
    display: flex;
    flex-direction: column;
}

.flex-item img {
    display: block;
    margin: 0 auto;
}

.second-flex {
    display: flex;
}

option 5:

result5

HTML:

 <div class="flex-container">
        <div class="row ">
            <div class="flex-item">
                <img src="assets/images/image.jpg" height="40" />
            </div>
            <div class="flex-item third-flex">
                <input type="radio" id="radio0" name="choice"><span>Text1</span>
            </div>
        </div>
        <div class="row ">
            <div class="flex-item">
                <img src="assets/images/image.jpg" height="40" />
            </div>
            <div class="flex-item">
                <input type="radio" id="radio1" name="choice"><span>Text2</span>
            </div>
        </div>
        <div class="row">
            <input type="button" value="Submit" id="submitAnswer" />
        </div>
    </div>

CSS:

.flex-container {
    height: 100%;
    padding: 0;
    margin: 0;
    display: -webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
}

.row {
    width: auto;
}

.flex-item {
    margin: 10px 30px;
    padding: 5px;
    line-height: 36px;
    color: black;
    font-weight: bold;
    font-size: 2em;
    text-align: center;
    align-items: center;
    display: flex;
    flex-direction: column;
}

.flex-item img {
    display: block;
    margin: 0 auto;
}

.second-flex {
    display: flex;
}
Ahmad Dalao
  • 1,968
  • 1
  • 8
  • 14
  • Thanks for this, although in your example, the radio button with "Text1" doesn't appear on a separate row than the radio button with "Text 2". Ideally they would be on different horizontal lines -- that's what I was looking for. – Dave Aug 28 '20 at 12:31
  • You should then give the `.flex-item` the following `display: flex; flex-direction: column;` and they will appear on a separate row. – Ahmad Dalao Aug 28 '20 at 13:08
  • Unfortunately that doesn't work either -- https://imgur.com/a/zeeig7n . I want everything in the '
    ' to appear on its own horizontal row. Notice in the screen shot everything is appearing on one giant horizontal row.
    – Dave Aug 28 '20 at 14:55
  • I edited my answer with some screenshots let me know which one is the answer you are looking for. – Ahmad Dalao Aug 28 '20 at 15:35
  • Hi, Thanks for following up and helping me out. So I do want the image, radio button, and text to be in the same row, but for different groups of those things, I want them to be in different horizontal rows. So above, how do you keep the first image, radio button, and "Text1" in a single row, but move the second image, its button and "text2" to another row, and then move the "Submit" button to a third row? – Dave Aug 28 '20 at 16:11
  • So which option is the closest to what you really need? So I can try and help out more. Feel free to combine them and I will make it happen xD – Ahmad Dalao Aug 28 '20 at 16:23
  • Hey there I edited my answer and I added new options 4 and 5 let me know if these what you are looking for if not do please draw me an image if the desired result and I will do my best to help. – Ahmad Dalao Aug 28 '20 at 16:37
0

I'm guessing that you want each option to take a whole row? If not, please post the expected layout in question.

If Yes, you can add flex-direction: column to the flex-container

.flex-container {
    height: 100%;
    padding: 0;
    margin: 0;
    display: -webkit-box;
    flex-direction: column;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    align-items: center;
    justify-content: center;
}
.row {
    display: flex;
    width: auto;
    border: 1px solid blue;
}
.flex-item {
    padding: 5px;
    margin: 10px;
    line-height: 20px;
    color: black;
    font-weight: bold;
    font-size: 2em;
    text-align: center;
}
<div class="flex-container">
    <div class="row">
        <div class="flex-item">
          <img src="images/check.jpg" />
        </div>
        <div class="flex-item">
          <input type="radio" id="radio0" name="choice" ><span>Text1</span>
        </div>
    </div>
    <div class="row">
        <div class="flex-item">
          <img src="images/check.jpg" />
        </div>
        <div class="flex-item">
        <input type="radio" id="radio1" name="choice" ><span>Text2</span>
        </div>
    </div>
    <div class="row" id="feedback"></div>
    <div class="row">
        <input type="button" value="Submit" id="submitAnswer" />
    </div>
</div>
huan feng
  • 7,307
  • 2
  • 32
  • 56
  • Hi, This is really close to what I want. The only thing is in your code above, the image is appearing above the radio button and text. Ideally, all three things shoudl appear in the same row. – Dave Aug 28 '20 at 14:56
  • It is simple, see the updated answer. Adding display: flex; to the .row class. – huan feng Aug 30 '20 at 02:50
0

I think you're just missing wrap on the container.

An initial setting in flex layout is flex-wrap: nowrap. This means flex items will not wrap. They will always line up in a single row.

You can override that default with flex-wrap: wrap.

Try something like this:

body {
  display: flex;
  justify-content: center;
}

.flex-container {
  display: flex;
  flex-wrap: wrap;
}

.row {
  flex-basis: 100%;
  text-align: center;
  border: 1px solid blue;
}

.flex-item {
  padding: 5px;
  margin: 10px;
  font-weight: bold;
  font-size: 2em;
}
<div class="flex-container">
  <div class="row">
    <div class="flex-item">
      <img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt="">
    </div>
    <div class="flex-item">
      <input type="radio" id="radio0" name="choice"><span>Text1</span>
    </div>
  </div>
  <div class="row">
    <div class="flex-item">
      <img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt="">
    </div>
    <div class="flex-item">
      <input type="radio" id="radio1" name="choice"><span>Text2</span>
    </div>
  </div>
  <div class="row" id="feedback"></div>
  <div class="row">
    <input type="button" value="Submit" id="submitAnswer" />
  </div>
</div>

More info: Force flex item to span full row width

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
0

Simply follow this:

When you want a flex item to occupy an entire row, set it to width: 100% or flex-basis: 100%, and enable wrap on the container.

The item now consumes all available space. Siblings are forced on to other rows.

From the following question/answer:

Force flex item to span full row width

ed2
  • 1,457
  • 1
  • 9
  • 26